Revert "erofs: support decompress big pcluster for lz4 backend"

This reverts commit 3337f63708.

Reason: Conflicts with next change and doesn't exist upstream

Change-Id: I65fdef31d221f6536254a3dffa3f0b1e871e28ff
This commit is contained in:
Sebastiano Barezzi
2024-03-17 02:12:25 +01:00
parent 0a6b1078f5
commit 950e1e4a2d
2 changed files with 96 additions and 139 deletions

View File

@@ -123,85 +123,44 @@ static int z_erofs_lz4_prepare_destpages(struct z_erofs_decompress_req *rq,
return kaddr ? 1 : 0; return kaddr ? 1 : 0;
} }
static void *z_erofs_handle_inplace_io(struct z_erofs_decompress_req *rq, static void *generic_copy_inplace_data(struct z_erofs_decompress_req *rq,
void *inpage, unsigned int *inputmargin, int *maptype, u8 *src, unsigned int pageofs_in)
bool support_0padding)
{ {
unsigned int nrpages_in, nrpages_out; /*
unsigned int ofull, oend, inputsize, total, i, j; * if in-place decompression is ongoing, those decompressed
struct page **in; * pages should be copied in order to avoid being overlapped.
void *src, *tmp; */
struct page **in = rq->in;
u8 *const tmp = erofs_get_pcpubuf(1);
u8 *tmpp = tmp;
unsigned int inlen = rq->inputsize - pageofs_in;
unsigned int count = min_t(uint, inlen, PAGE_SIZE - pageofs_in);
inputsize = rq->inputsize; while (tmpp < tmp + inlen) {
nrpages_in = PAGE_ALIGN(inputsize) >> PAGE_SHIFT;
oend = rq->pageofs_out + rq->outputsize;
ofull = PAGE_ALIGN(oend);
nrpages_out = ofull >> PAGE_SHIFT;
if (rq->inplace_io) {
if (rq->partial_decoding || !support_0padding ||
ofull - oend < LZ4_DECOMPRESS_INPLACE_MARGIN(inputsize))
goto docopy;
for (i = 0; i < nrpages_in; ++i) {
DBG_BUGON(rq->in[i] == NULL);
for (j = 0; j < nrpages_out - nrpages_in + i; ++j)
if (rq->out[j] == rq->in[i])
goto docopy;
}
}
if (nrpages_in <= 1) {
*maptype = 0;
return inpage;
}
kunmap_atomic(inpage);
might_sleep();
src = erofs_vm_map_ram(rq->in, nrpages_in);
if (!src) if (!src)
return ERR_PTR(-ENOMEM); src = kmap_atomic(*in);
*maptype = 1; memcpy(tmpp, src + pageofs_in, count);
return src; kunmap_atomic(src);
src = NULL;
docopy: tmpp += count;
/* Or copy compressed data which can be overlapped to per-CPU buffer */ pageofs_in = 0;
in = rq->in; count = PAGE_SIZE;
src = erofs_get_pcpubuf(nrpages_in);
if (!src) {
DBG_BUGON(1);
kunmap_atomic(inpage);
return ERR_PTR(-EFAULT);
}
tmp = src;
total = rq->inputsize;
while (total) {
unsigned int page_copycnt =
min_t(unsigned int, total, PAGE_SIZE - *inputmargin);
if (!inpage)
inpage = kmap_atomic(*in);
memcpy(tmp, inpage + *inputmargin, page_copycnt);
kunmap_atomic(inpage);
inpage = NULL;
tmp += page_copycnt;
total -= page_copycnt;
++in; ++in;
*inputmargin = 0;
} }
*maptype = 2; return tmp;
return src;
} }
static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out) static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
{ {
unsigned int inputmargin; unsigned int inputmargin, inlen;
u8 *headpage, *src; u8 *src;
bool support_0padding; bool copied, support_0padding;
int ret, maptype; int ret;
DBG_BUGON(*rq->in == NULL); if (rq->inputsize > PAGE_SIZE)
headpage = kmap_atomic(*rq->in); return -EOPNOTSUPP;
src = kmap_atomic(*rq->in);
inputmargin = 0; inputmargin = 0;
support_0padding = false; support_0padding = false;
@@ -209,36 +168,49 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
if (erofs_sb_has_lz4_0padding(EROFS_SB(rq->sb))) { if (erofs_sb_has_lz4_0padding(EROFS_SB(rq->sb))) {
support_0padding = true; support_0padding = true;
while (!headpage[inputmargin & ~PAGE_MASK]) while (!src[inputmargin & ~PAGE_MASK])
if (!(++inputmargin & ~PAGE_MASK)) if (!(++inputmargin & ~PAGE_MASK))
break; break;
if (inputmargin >= rq->inputsize) { if (inputmargin >= rq->inputsize) {
kunmap_atomic(headpage); kunmap_atomic(src);
return -EIO; return -EIO;
} }
} }
rq->inputsize -= inputmargin; copied = false;
src = z_erofs_handle_inplace_io(rq, headpage, &inputmargin, &maptype, inlen = rq->inputsize - inputmargin;
support_0padding); if (rq->inplace_io) {
if (IS_ERR(src)) const uint oend = (rq->pageofs_out +
return PTR_ERR(src); rq->outputsize) & ~PAGE_MASK;
const uint nr = PAGE_ALIGN(rq->pageofs_out +
rq->outputsize) >> PAGE_SHIFT;
if (rq->partial_decoding || !support_0padding ||
rq->out[nr - 1] != rq->in[0] ||
rq->inputsize - oend <
LZ4_DECOMPRESS_INPLACE_MARGIN(inlen)) {
src = generic_copy_inplace_data(rq, src, inputmargin);
inputmargin = 0;
copied = true;
}
}
/* legacy format could compress extra data in a pcluster. */ /* legacy format could compress extra data in a pcluster. */
if (rq->partial_decoding || !support_0padding) if (rq->partial_decoding || !support_0padding)
ret = LZ4_decompress_safe_partial(src + inputmargin, out, ret = LZ4_decompress_safe_partial(src + inputmargin, out,
rq->inputsize, rq->outputsize, rq->outputsize); inlen, rq->outputsize,
rq->outputsize);
else else
ret = LZ4_decompress_safe(src + inputmargin, out, ret = LZ4_decompress_safe(src + inputmargin, out,
rq->inputsize, rq->outputsize); inlen, rq->outputsize);
if (ret != rq->outputsize) { if (ret != rq->outputsize) {
erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]", erofs_err(rq->sb, "failed to decompress %d in[%u, %u] out[%u]",
ret, rq->inputsize, inputmargin, rq->outputsize); ret, inlen, inputmargin, rq->outputsize);
print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET, print_hex_dump(KERN_DEBUG, "[ in]: ", DUMP_PREFIX_OFFSET,
16, 1, src + inputmargin, rq->inputsize, true); 16, 1, src + inputmargin, inlen, true);
print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET, print_hex_dump(KERN_DEBUG, "[out]: ", DUMP_PREFIX_OFFSET,
16, 1, out, rq->outputsize, true); 16, 1, out, rq->outputsize, true);
@@ -247,16 +219,10 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq, u8 *out)
ret = -EIO; ret = -EIO;
} }
if (maptype == 0) { if (copied)
kunmap_atomic(src);
} else if (maptype == 1) {
vm_unmap_ram(src, PAGE_ALIGN(rq->inputsize) >> PAGE_SHIFT);
} else if (maptype == 2) {
erofs_put_pcpubuf(src); erofs_put_pcpubuf(src);
} else { else
DBG_BUGON(1); kunmap_atomic(src);
return -EFAULT;
}
return ret; return ret;
} }
@@ -306,10 +272,8 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq,
const struct z_erofs_decompressor *alg = decompressors + rq->alg; const struct z_erofs_decompressor *alg = decompressors + rq->alg;
unsigned int dst_maptype; unsigned int dst_maptype;
void *dst; void *dst;
int ret; int ret, i;
/* two optimized fast paths only for non bigpcluster cases yet */
if (rq->inputsize <= PAGE_SIZE) {
if (nrpages_out == 1 && !rq->inplace_io) { if (nrpages_out == 1 && !rq->inplace_io) {
DBG_BUGON(!*rq->out); DBG_BUGON(!*rq->out);
dst = kmap_atomic(*rq->out); dst = kmap_atomic(*rq->out);
@@ -336,21 +300,29 @@ static int z_erofs_decompress_generic(struct z_erofs_decompress_req *rq,
erofs_put_pcpubuf(dst); erofs_put_pcpubuf(dst);
return ret; return ret;
} }
}
/* general decoding path which can be used for all cases */
ret = alg->prepare_destpages(rq, pagepool); ret = alg->prepare_destpages(rq, pagepool);
if (ret < 0) if (ret < 0) {
return ret; return ret;
if (ret) { } else if (ret) {
dst = page_address(*rq->out); dst = page_address(*rq->out);
dst_maptype = 1; dst_maptype = 1;
goto dstmap_out; goto dstmap_out;
} }
dst = erofs_vm_map_ram(rq->out, nrpages_out); i = 0;
while (1) {
dst = vm_map_ram(rq->out, nrpages_out, -1, PAGE_KERNEL);
/* retry two more times (totally 3 times) */
if (dst || ++i >= 3)
break;
vm_unmap_aliases();
}
if (!dst) if (!dst)
return -ENOMEM; return -ENOMEM;
dst_maptype = 2; dst_maptype = 2;
dstmap_out: dstmap_out:

View File

@@ -396,21 +396,6 @@ int erofs_namei(struct inode *dir, struct qstr *name,
/* dir.c */ /* dir.c */
extern const struct file_operations erofs_dir_fops; extern const struct file_operations erofs_dir_fops;
static inline void *erofs_vm_map_ram(struct page **pages, unsigned int count)
{
int retried = 0;
while (1) {
void *p = vm_map_ram(pages, count, -1, PAGE_KERNEL);
/* retry two more times (totally 3 times) */
if (p || ++retried >= 3)
return p;
vm_unmap_aliases();
}
return NULL;
}
/* pcpubuf.c */ /* pcpubuf.c */
void *erofs_get_pcpubuf(unsigned int requiredpages); void *erofs_get_pcpubuf(unsigned int requiredpages);
void erofs_put_pcpubuf(void *ptr); void erofs_put_pcpubuf(void *ptr);