diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c index b43dcc526..4dd6f598e 100644 --- a/lib/ext2fs/alloc.c +++ b/lib/ext2fs/alloc.c @@ -202,7 +202,11 @@ errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal, ext2fs_clear_block_uninit(fs, ext2fs_group_of_blk2(fs, b)); *ret = b; - fs->reserved[3] = (__u32)b; // not 64-bit safe + /* reserved[] is 32 bits wide; drop a hint that would be truncated */ + if (b <= 0xFFFFFFFFULL) + fs->reserved[3] = (__u32) b; + else + fs->reserved[3] = 0; return 0; } @@ -445,8 +449,7 @@ errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal, if (!map) return EXT2_ET_NO_BLOCK_BITMAP; if (!goal || goal >= ext2fs_blocks_count(fs->super)) - goal = fs->reserved[3]; - // goal = fs->super->s_first_data_block; + goal = fs->reserved[3] ? fs->reserved[3] : fs->super->s_first_data_block; start = goal; while (!looped || start <= goal) { @@ -493,7 +496,16 @@ errcode_t ext2fs_new_range(ext2_filsys fs, int flags, blk64_t goal, b += fs->super->s_blocks_per_group) ext2fs_clear_block_uninit(fs, ext2fs_group_of_blk2(fs, b)); - fs->reserved[3] = (__u32) end; + /* + * Only keep a hint which can still be used as a + * search start: reserved[] is 32 bits wide, so a + * larger value would be truncated into an unrelated + * block number. + */ + if (end < ext2fs_blocks_count(fs->super) && end <= 0xFFFFFFFFULL) + fs->reserved[3] = (__u32) end; + else + fs->reserved[3] = 0; return 0; } diff --git a/lib/ext2fs/fallocate.c b/lib/ext2fs/fallocate.c index b619d3852..b61fe9903 100644 --- a/lib/ext2fs/fallocate.c +++ b/lib/ext2fs/fallocate.c @@ -695,7 +695,12 @@ static errcode_t extent_fallocate(ext2_filsys fs, int flags, ext2_ino_t ino, if (err == EXT2_ET_NO_CURRENT_NODE) { blk64_t max_blocks = ext2fs_blocks_count(fs->super); - goal = fs->reserved[3]; + /* + * Only follow the hint while it still points inside the file + * system, so that the ~0ULL goal sentinel keeps working. + */ + if (fs->reserved[3] && fs->reserved[3] < max_blocks) + goal = fs->reserved[3]; if (goal == ~0ULL) goal = ext2fs_find_inode_goal(fs, ino, inode, start); err = ext2fs_find_first_zero_block_bitmap2(fs->block_map,