mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
erofs: support interlaced uncompressed data for compressed files
Currently, uncompressed data is all handled in the shifted way, which means we have to shift the whole on-disk plain pcluster to get the logical data. However, since we are also using in-place I/O for uncompressed data, data copy will be reduced a lot if pcluster is recorded in the interlaced way as illustrated below: _______________________________________________________________ | | | |_ tail part |_ head part _| |<- blk0 ->| .. |<- blkn-2 ->|<- blkn-1 ->| The logical data then becomes: ________________________________________________________ |_ head part _|_ blk0 _| .. |_ blkn-2 _|_ tail part _| In addition, non-4k plain pclusters are also survived by the interlaced way, which can be used for non-4k lclusters as well. However, it's almost impossible to de-duplicate uncompressed data in the interlaced way, therefore shifted uncompressed data is still useful. Signed-off-by: Yue Hu <huyue2@coolpad.com> Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com> Link: https://lore.kernel.org/r/8369112678604fdf4ef796626d59b1fdd0745a53.1663898962.git.huyue2@coolpad.com Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
This commit is contained in:
parent
1ae9470c3e
commit
fdffc091e6
|
@ -317,52 +317,61 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int z_erofs_shifted_transform(struct z_erofs_decompress_req *rq,
|
||||
struct page **pagepool)
|
||||
static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
|
||||
struct page **pagepool)
|
||||
{
|
||||
const unsigned int nrpages_out =
|
||||
const unsigned int inpages = PAGE_ALIGN(rq->inputsize) >> PAGE_SHIFT;
|
||||
const unsigned int outpages =
|
||||
PAGE_ALIGN(rq->pageofs_out + rq->outputsize) >> PAGE_SHIFT;
|
||||
const unsigned int righthalf = min_t(unsigned int, rq->outputsize,
|
||||
PAGE_SIZE - rq->pageofs_out);
|
||||
const unsigned int lefthalf = rq->outputsize - righthalf;
|
||||
const unsigned int interlaced_offset =
|
||||
rq->alg == Z_EROFS_COMPRESSION_SHIFTED ? 0 : rq->pageofs_out;
|
||||
unsigned char *src, *dst;
|
||||
|
||||
if (nrpages_out > 2) {
|
||||
if (outpages > 2 && rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
|
||||
DBG_BUGON(1);
|
||||
return -EIO;
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
|
||||
if (rq->out[0] == *rq->in) {
|
||||
DBG_BUGON(nrpages_out != 1);
|
||||
DBG_BUGON(rq->pageofs_out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
src = kmap_atomic(*rq->in) + rq->pageofs_in;
|
||||
src = kmap_local_page(rq->in[inpages - 1]) + rq->pageofs_in;
|
||||
if (rq->out[0]) {
|
||||
dst = kmap_atomic(rq->out[0]);
|
||||
memcpy(dst + rq->pageofs_out, src, righthalf);
|
||||
kunmap_atomic(dst);
|
||||
dst = kmap_local_page(rq->out[0]);
|
||||
memcpy(dst + rq->pageofs_out, src + interlaced_offset,
|
||||
righthalf);
|
||||
kunmap_local(dst);
|
||||
}
|
||||
|
||||
if (nrpages_out == 2) {
|
||||
DBG_BUGON(!rq->out[1]);
|
||||
if (rq->out[1] == *rq->in) {
|
||||
if (outpages > inpages) {
|
||||
DBG_BUGON(!rq->out[outpages - 1]);
|
||||
if (rq->out[outpages - 1] != rq->in[inpages - 1]) {
|
||||
dst = kmap_local_page(rq->out[outpages - 1]);
|
||||
memcpy(dst, interlaced_offset ? src :
|
||||
(src + righthalf), lefthalf);
|
||||
kunmap_local(dst);
|
||||
} else if (!interlaced_offset) {
|
||||
memmove(src, src + righthalf, lefthalf);
|
||||
} else {
|
||||
dst = kmap_atomic(rq->out[1]);
|
||||
memcpy(dst, src + righthalf, lefthalf);
|
||||
kunmap_atomic(dst);
|
||||
}
|
||||
}
|
||||
kunmap_atomic(src);
|
||||
kunmap_local(src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct z_erofs_decompressor decompressors[] = {
|
||||
[Z_EROFS_COMPRESSION_SHIFTED] = {
|
||||
.decompress = z_erofs_shifted_transform,
|
||||
.decompress = z_erofs_transform_plain,
|
||||
.name = "shifted"
|
||||
},
|
||||
[Z_EROFS_COMPRESSION_INTERLACED] = {
|
||||
.decompress = z_erofs_transform_plain,
|
||||
.name = "interlaced"
|
||||
},
|
||||
[Z_EROFS_COMPRESSION_LZ4] = {
|
||||
.decompress = z_erofs_lz4_decompress,
|
||||
.name = "lz4"
|
||||
|
|
|
@ -295,11 +295,13 @@ struct z_erofs_lzma_cfgs {
|
|||
* bit 1 : HEAD1 big pcluster (0 - off; 1 - on)
|
||||
* bit 2 : HEAD2 big pcluster (0 - off; 1 - on)
|
||||
* bit 3 : tailpacking inline pcluster (0 - off; 1 - on)
|
||||
* bit 4 : interlaced plain pcluster (0 - off; 1 - on)
|
||||
*/
|
||||
#define Z_EROFS_ADVISE_COMPACTED_2B 0x0001
|
||||
#define Z_EROFS_ADVISE_BIG_PCLUSTER_1 0x0002
|
||||
#define Z_EROFS_ADVISE_BIG_PCLUSTER_2 0x0004
|
||||
#define Z_EROFS_ADVISE_INLINE_PCLUSTER 0x0008
|
||||
#define Z_EROFS_ADVISE_INTERLACED_PCLUSTER 0x0010
|
||||
|
||||
struct z_erofs_map_header {
|
||||
__le16 h_reserved1;
|
||||
|
|
|
@ -420,6 +420,7 @@ struct erofs_map_blocks {
|
|||
|
||||
enum {
|
||||
Z_EROFS_COMPRESSION_SHIFTED = Z_EROFS_COMPRESSION_MAX,
|
||||
Z_EROFS_COMPRESSION_INTERLACED,
|
||||
Z_EROFS_COMPRESSION_RUNTIME_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -679,12 +679,18 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN)
|
||||
map->m_algorithmformat = Z_EROFS_COMPRESSION_SHIFTED;
|
||||
else if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2)
|
||||
if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN) {
|
||||
if (vi->z_advise & Z_EROFS_ADVISE_INTERLACED_PCLUSTER)
|
||||
map->m_algorithmformat =
|
||||
Z_EROFS_COMPRESSION_INTERLACED;
|
||||
else
|
||||
map->m_algorithmformat =
|
||||
Z_EROFS_COMPRESSION_SHIFTED;
|
||||
} else if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) {
|
||||
map->m_algorithmformat = vi->z_algorithmtype[1];
|
||||
else
|
||||
} else {
|
||||
map->m_algorithmformat = vi->z_algorithmtype[0];
|
||||
}
|
||||
|
||||
if ((flags & EROFS_GET_BLOCKS_FIEMAP) ||
|
||||
((flags & EROFS_GET_BLOCKS_READMORE) &&
|
||||
|
|
Loading…
Reference in a new issue