From: Hu Weiwen <seh...@mail.scut.edu.cn> When the subsequent erofs_battach() is called on an buffer block of which (bb->buffers.off % EROFS_BLKSIZ == 0), `tail_blkaddr' won't be updated correctly. This bug can be reproduced by:
mkdir bug-repo head -c 4032 /dev/urandom > bug-repo/1 head -c 4095 /dev/urandom > bug-repo/2 head -c 12345 /dev/urandom > bug-repo/3 # arbitrary size mkfs.erofs -Eforce-inode-compact bug-repo.erofs.img bug-repo Then mount this image and see that file `3' in the image is different from `bug-repo/3'. This patch fix this by: * Handle `oob' and `tail_blkaddr' for the case above properly; * Don't inline tail-packing data for such case, since the tail-packing data is actually in a different block from inode itself even kernel can handle such cases properly. Signed-off-by: Hu Weiwen <seh...@mail.scut.edu.cn> Reviewed-by: Gao Xiang <hsiang...@aol.com> Signed-off-by: Gao Xiang <hsiang...@aol.com> --- changes since v2: - update commit message; - refine 2 asserts from < 0 to != EROFS_BLKSIZ. lib/cache.c | 4 ++-- lib/compress.c | 3 ++- lib/inode.c | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 40d3b1f3f4d5..e3327c3f1586 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -102,7 +102,7 @@ static int __erofs_battach(struct erofs_buffer_block *bb, bool dryrun) { const erofs_off_t alignedoffset = roundup(bb->buffers.off, alignsize); - const int oob = cmpsgn(roundup(bb->buffers.off % EROFS_BLKSIZ, + const int oob = cmpsgn(roundup((bb->buffers.off - 1) % EROFS_BLKSIZ + 1, alignsize) + incr + extrasize, EROFS_BLKSIZ); bool tailupdate = false; @@ -134,7 +134,7 @@ static int __erofs_battach(struct erofs_buffer_block *bb, tail_blkaddr = blkaddr + BLK_ROUND_UP(bb->buffers.off); erofs_bupdate_mapped(bb); } - return (alignedoffset + incr) % EROFS_BLKSIZ; + return (alignedoffset + incr - 1) % EROFS_BLKSIZ + 1; } int erofs_bh_balloon(struct erofs_buffer_head *bh, erofs_off_t incr) diff --git a/lib/compress.c b/lib/compress.c index 2b1f93c389ff..4b685cd27080 100644 --- a/lib/compress.c +++ b/lib/compress.c @@ -456,8 +456,9 @@ int erofs_write_compressed_file(struct erofs_inode *inode) vle_write_indexes_final(&ctx); close(fd); + DBG_BUGON(!compressed_blocks); ret = erofs_bh_balloon(bh, blknr_to_addr(compressed_blocks)); - DBG_BUGON(ret); + DBG_BUGON(ret != EROFS_BLKSIZ); erofs_info("compressed %s (%llu bytes) into %u blocks", inode->i_srcpath, (unsigned long long)inode->i_size, diff --git a/lib/inode.c b/lib/inode.c index 6371aa563673..40189fed37dd 100644 --- a/lib/inode.c +++ b/lib/inode.c @@ -531,7 +531,7 @@ int erofs_prepare_tail_block(struct erofs_inode *inode) } /* expend a block as the tail block (should be successful) */ ret = erofs_bh_balloon(bh, EROFS_BLKSIZ); - DBG_BUGON(ret); + DBG_BUGON(ret != EROFS_BLKSIZ); return 0; } -- 2.24.0