linux/fs/ext4
Ojaswin Mujoo bae76c035b ext4: fix fsmap end of range reporting with bigalloc
With bigalloc enabled, the logic to report last extent has a bug since
we try to use cluster units instead of block units. This can cause an
issue where extra incorrect entries might be returned back to the
user. This was flagged by generic/365 with 64k bs and -O bigalloc.

** Details of issue **

The issue was noticed on 5G 64k blocksize FS with -O bigalloc which has
only 1 bg.

$ xfs_io -c "fsmap -d" /mnt/scratch

  0: 253:48 [0..127]: static fs metadata 128   /* sb */
  1: 253:48 [128..255]: special 102:1 128   /* gdt */
  3: 253:48 [256..383]: special 102:3 128   /* block bitmap */
  4: 253:48 [384..2303]: unknown 1920       /* flex bg empty space */
  5: 253:48 [2304..2431]: special 102:4 128   /* inode bitmap */
  6: 253:48 [2432..4351]: unknown 1920      /* flex bg empty space */
  7: 253:48 [4352..6911]: inodes 2560
  8: 253:48 [6912..538623]: unknown 531712
  9: 253:48 [538624..10485759]: free space 9947136

The issue can be seen with:

$ xfs_io -c "fsmap -d 0 3" /mnt/scratch

  0: 253:48 [0..127]: static fs metadata 128
  1: 253:48 [384..2047]: unknown 1664

Only the first entry was expected to be returned but we get 2. This is
because:

ext4_getfsmap_datadev()
  first_cluster, last_cluster = 0
  ...
  info->gfi_last = true;
  ext4_getfsmap_datadev_helper(sb, end_ag, last_cluster + 1, 0, info);
    fsb = C2B(1) = 16
    fslen = 0
    ...
    /* Merge in any relevant extents from the meta_list */
    list_for_each_entry_safe(p, tmp, &info->gfi_meta_list, fmr_list) {
      ...
      // since fsb = 16, considers all metadata which starts before 16 blockno
      iter 1: error = ext4_getfsmap_helper(sb, info, p);  // p = sb (0,1), nop
        info->gfi_next_fsblk = 1
      iter 2: error = ext4_getfsmap_helper(sb, info, p);  // p = gdt (1,2), nop
        info->gfi_next_fsblk = 2
      iter 3: error = ext4_getfsmap_helper(sb, info, p);  // p = blk bitmap (2,3), nop
        info->gfi_next_fsblk = 3
      iter 4: error = ext4_getfsmap_helper(sb, info, p);  // p = ino bitmap (18,19)
        if (rec_blk > info->gfi_next_fsblk) { // (18 > 3)
          // emits an extra entry ** BUG **
        }
    }

Fix this by directly calling ext4_getfsmap_datadev() with a dummy
record that has fmr_physical set to (end_fsb + 1) instead of
last_cluster + 1. By using the block instead of cluster we get the
correct behavior.

Replacing ext4_getfsmap_datadev_helper() with ext4_getfsmap_helper()
is okay since the gfi_lastfree and metadata checks in
ext4_getfsmap_datadev_helper() are anyways redundant when we only want
to emit the last allocated block of the range, as we have already
taken care of emitting metadata and any last free blocks.

Cc: stable@kernel.org
Reported-by: Disha Goel <disgoel@linux.ibm.com>
Fixes: 4a622e4d47 ("ext4: fix FS_IOC_GETFSMAP handling")
Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Link: https://patch.msgid.link/e7472c8535c9c5ec10f425f495366864ea12c9da.1754377641.git.ojaswin@linux.ibm.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
History 2025-08-12 23:15:05 -04:00
..
.kunitconfig ext4: add .kunitconfig fragment to enable ext4-specific tests 2021-02-11 23:16:30 -05:00
acl.c ext4: convert to ctime accessor functions 2023-07-24 10:29:54 +02:00
acl.h Revert "ext4: apply umask if ACL support is disabled" 2024-05-02 18:25:39 -04:00
balloc.c ext4: convert sbi->s_mb_free_pending to atomic_t 2025-07-25 09:14:17 -04:00
bitmap.c ext4: remove sbi argument from ext4_chksum() 2025-05-20 10:31:12 -04:00
block_validity.c ext4: make block validity check resistent to sb bh corruption 2025-04-12 22:01:37 -04:00
crypto.c ext4: Move CONFIG_UNICODE defguards into the code flow 2024-06-07 17:00:45 +02:00
dir.c ext4: fix OOB read when checking dotdot dir 2025-03-21 01:33:11 -04:00
ext4.h ext4: refactor choose group to scan group 2025-07-25 09:14:17 -04:00
ext4_extents.h ext4: remove unused EXT_STATS macro from ext4_extents.h 2025-07-12 19:01:38 -04:00
ext4_jbd2.c ext4: enable large folio for regular file 2025-05-20 10:31:12 -04:00
ext4_jbd2.h ext4/jbd2: convert jbd2_journal_blocks_per_page() to support large folio 2025-05-20 10:31:12 -04:00
extents.c ext4: replace ext4_writepage_trans_blocks() 2025-07-13 23:41:52 -04:00
extents_status.c ext4: clairfy the rules for modifying extents 2025-05-15 13:14:56 -04:00
extents_status.h ext4: don't pass full mapping flags to ext4_es_insert_extent() 2024-11-12 23:54:14 -05:00
fast_commit.c ext4: remove sbi argument from ext4_chksum() 2025-05-20 10:31:12 -04:00
fast_commit.h ext4 fast_commit: make use of name_snapshot primitives 2025-01-27 19:24:43 -05:00
file.c ext4: Add multi-fsblock atomic write support with bigalloc 2025-05-20 10:31:12 -04:00
fsmap.c ext4: fix fsmap end of range reporting with bigalloc 2025-08-12 23:15:05 -04:00
fsmap.h ext4: fsmap: fix the block/inode bitmap comment 2021-06-24 09:48:29 -04:00
fsync.c ext4: add ext4_emergency_state() helper function 2025-03-13 10:16:34 -04:00
hash.c ext4: hash: simplify kzalloc(n * 1, ...) to kzalloc(n, ...) 2025-03-21 01:10:10 -04:00
ialloc.c ext4: limit the maximum folio order 2025-07-14 23:48:15 -04:00
indirect.c ext4: fix race in buffer_head read fault injection 2024-11-12 23:54:14 -05:00
inline.c ext4: do not BUG when INLINE_DATA_FL lacks system.data xattr 2025-07-25 09:14:17 -04:00
inode-test.c ext4: add missing MODULE_DESCRIPTION() 2024-07-05 16:07:24 -04:00
inode.c ext4: check fast symlink for ea_inode correctly 2025-08-12 23:15:05 -04:00
ioctl.c ext4: remove sb argument from ext4_superblock_csum() 2025-05-20 10:31:12 -04:00
Kconfig ext4: switch to using the crc32c library 2024-12-01 17:23:02 -08:00
Makefile ext4: move ext4 crypto code to its own file crypto.c 2022-05-21 22:24:24 -04:00
mballoc-test.c ext4: convert free groups order lists to xarrays 2025-07-25 09:14:17 -04:00
mballoc.c ext4: implement linear-like traversal across order xarrays 2025-07-25 09:14:17 -04:00
mballoc.h ext4: refactor choose group to scan group 2025-07-25 09:14:17 -04:00
migrate.c ext4: fix i_data_sem unlock order in ext4_ind_migrate() 2024-09-03 22:14:17 -04:00
mmp.c ext4: remove sbi argument from ext4_chksum() 2025-05-20 10:31:12 -04:00
move_extent.c ext4: replace ext4_writepage_trans_blocks() 2025-07-13 23:41:52 -04:00
namei.c ext4: fix unused variable warning in ext4_init_new_dir 2025-08-12 23:15:05 -04:00
orphan.c ext4: remove sbi argument from ext4_chksum() 2025-05-20 10:31:12 -04:00
page-io.c ext4: remove redundant __GFP_NOWARN 2025-08-12 23:15:05 -04:00
readpage.c ext4: make ext4_mpage_readpages() support large folios 2025-05-20 10:31:11 -04:00
resize.c ext4: remove sb argument from ext4_superblock_csum() 2025-05-20 10:31:12 -04:00
super.c ext4: remove redundant __GFP_NOWARN 2025-08-12 23:15:05 -04:00
symlink.c ext4_get_link(): fix breakage in RCU mode 2024-02-25 02:10:32 -05:00
sysfs.c ext4: Make sb update interval tunable 2025-03-21 01:12:33 -04:00
truncate.h ext4: Convert to use mapping->invalidate_lock 2021-07-13 14:29:00 +02:00
verity.c fs: Convert aops->write_begin to take a folio 2024-08-07 11:33:21 +02:00
xattr.c ext4: Refactor breaking condition for xattr_find_entry() 2025-07-17 10:41:05 -04:00
xattr.h ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all() 2025-03-18 00:15:19 -04:00
xattr_hurd.c fs: port xattr to mnt_idmap 2023-01-19 09:24:28 +01:00
xattr_security.c fs: port xattr to mnt_idmap 2023-01-19 09:24:28 +01:00
xattr_trusted.c fs: port xattr to mnt_idmap 2023-01-19 09:24:28 +01:00
xattr_user.c fs: port xattr to mnt_idmap 2023-01-19 09:24:28 +01:00