When __erofs_battach() is called on an buffer block of which (bb->buffers.off % EROFS_BLKSIZ == 0), `tail_blkaddr' will not 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: * Don't inline tail-end data in this case, since the tail-end data will be in a different block from inode. * Correctly handle `battach' in this case. Signed-off-by: Hu Weiwen <[email protected]> --- lib/cache.c | 4 ++-- lib/inode.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/cache.c b/lib/cache.c index 9e65429..464a43c 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/inode.c b/lib/inode.c index 4ed6aed..d6a64cc 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 < 0); return 0; } -- 2.30.0
