xfs: Fix missing interval for missing_owner in xfs fsmap

In the fsmap query of xfs, there is an interval missing problem:
[root@fedora ~]# xfs_io -c 'fsmap -vvvv' /mnt
EXT: DEV BLOCK-RANGE OWNER FILE-OFFSET AG AG-OFFSET TOTAL
0: 253:16 [0..7]: static fs metadata 0 (0..7) 8
1: 253:16 [8..23]: per-AG metadata 0 (8..23) 16
2: 253:16 [24..39]: inode btree 0 (24..39) 16
3: 253:16 [40..47]: per-AG metadata 0 (40..47) 8
4: 253:16 [48..55]: refcount btree 0 (48..55) 8
5: 253:16 [56..103]: per-AG metadata 0 (56..103) 48
6: 253:16 [104..127]: free space 0 (104..127) 24
......

BUG:
[root@fedora ~]# xfs_io -c 'fsmap -vvvv -d 104 107' /mnt
[root@fedora ~]#
Normally, we should be able to get [104, 107), but we got nothing.

The problem is caused by shifting. The query for the problem-triggered
scenario is for the missing_owner interval (e.g. freespace in rmapbt/
unknown space in bnobt), which is obtained by subtraction (gap). For this
scenario, the interval is obtained by info->last. However, rec_daddr is
calculated based on the start_block recorded in key[1], which is converted
by calling XFS_BB_TO_FSBT. Then if rec_daddr does not exceed
info->next_daddr, which means keys[1].fmr_physical >> (mp)->m_blkbb_log
<= info->next_daddr, no records will be displayed. In the above example,
104 >> (mp)->m_blkbb_log = 12 and 107 >> (mp)->m_blkbb_log = 12, so the two
are reduced to 0 and the gap is ignored:

before calculate ----------------> after shifting
104(st) 107(ed) 12(st/ed)
|---------| |
sector size block size

Resolve this issue by introducing the "end_daddr" field in
xfs_getfsmap_info. This records |key[1].fmr_physical + key[1].length| at
the granularity of sector. If the current query is the last, the rec_daddr
is end_daddr to prevent missing interval problems caused by shifting. We
only need to focus on the last query, because xfs disks are internally
aligned with disk blocksize that are powers of two and minimum 512, so
there is no problem with shifting in previous queries.

After applying this patch, the above problem have been solved:
[root@fedora ~]# xfs_io -c 'fsmap -vvvv -d 104 107' /mnt
EXT: DEV BLOCK-RANGE OWNER FILE-OFFSET AG AG-OFFSET TOTAL
0: 253:16 [104..106]: free space 0 (104..106) 3

Fixes: e89c041338ed ("xfs: implement the GETFSMAP ioctl")
Signed-off-by: Zizhi Wo <wozizhi@huawei.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
[djwong: limit the range of end_addr correctly]
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>

authored by Zizhi Wo and committed by Chandan Babu R ca6448ae 6b35cc8d

+23 -1
+23 -1
fs/xfs/xfs_fsmap.c
··· 162 xfs_daddr_t next_daddr; /* next daddr we expect */ 163 /* daddr of low fsmap key when we're using the rtbitmap */ 164 xfs_daddr_t low_daddr; 165 u64 missing_owner; /* owner of holes */ 166 u32 dev; /* device id */ 167 /* ··· 183 int (*fn)(struct xfs_trans *tp, 184 const struct xfs_fsmap *keys, 185 struct xfs_getfsmap_info *info); 186 }; 187 188 /* Compare two getfsmap device handlers. */ ··· 295 info->next_daddr = rec_daddr; 296 return 0; 297 } 298 299 /* Are we just counting mappings? */ 300 if (info->head->fmh_count == 0) { ··· 918 919 /* Set up our device handlers. */ 920 memset(handlers, 0, sizeof(handlers)); 921 handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev); 922 if (use_rmap) 923 handlers[0].fn = xfs_getfsmap_datadev_rmapbt; 924 else 925 handlers[0].fn = xfs_getfsmap_datadev_bnobt; 926 if (mp->m_logdev_targp != mp->m_ddev_targp) { 927 handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev); 928 handlers[1].fn = xfs_getfsmap_logdev; 929 } 930 #ifdef CONFIG_XFS_RT 931 if (mp->m_rtdev_targp) { 932 handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev); 933 handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap; 934 } ··· 964 965 info.next_daddr = head->fmh_keys[0].fmr_physical + 966 head->fmh_keys[0].fmr_length; 967 info.fsmap_recs = fsmap_recs; 968 info.head = head; 969 ··· 985 * low key, zero out the low key so that we get 986 * everything from the beginning. 987 */ 988 - if (handlers[i].dev == head->fmh_keys[1].fmr_device) 989 dkeys[1] = head->fmh_keys[1]; 990 if (handlers[i].dev > head->fmh_keys[0].fmr_device) 991 memset(&dkeys[0], 0, sizeof(struct xfs_fsmap)); 992
··· 162 xfs_daddr_t next_daddr; /* next daddr we expect */ 163 /* daddr of low fsmap key when we're using the rtbitmap */ 164 xfs_daddr_t low_daddr; 165 + xfs_daddr_t end_daddr; /* daddr of high fsmap key */ 166 u64 missing_owner; /* owner of holes */ 167 u32 dev; /* device id */ 168 /* ··· 182 int (*fn)(struct xfs_trans *tp, 183 const struct xfs_fsmap *keys, 184 struct xfs_getfsmap_info *info); 185 + sector_t nr_sectors; 186 }; 187 188 /* Compare two getfsmap device handlers. */ ··· 293 info->next_daddr = rec_daddr; 294 return 0; 295 } 296 + 297 + /* 298 + * For an info->last query, we're looking for a gap between the last 299 + * mapping emitted and the high key specified by userspace. If the 300 + * user's query spans less than 1 fsblock, then info->high and 301 + * info->low will have the same rm_startblock, which causes rec_daddr 302 + * and next_daddr to be the same. Therefore, use the end_daddr that 303 + * we calculated from userspace's high key to synthesize the record. 304 + * Note that if the btree query found a mapping, there won't be a gap. 305 + */ 306 + if (info->last && info->end_daddr != XFS_BUF_DADDR_NULL) 307 + rec_daddr = info->end_daddr; 308 309 /* Are we just counting mappings? */ 310 if (info->head->fmh_count == 0) { ··· 904 905 /* Set up our device handlers. */ 906 memset(handlers, 0, sizeof(handlers)); 907 + handlers[0].nr_sectors = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); 908 handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev); 909 if (use_rmap) 910 handlers[0].fn = xfs_getfsmap_datadev_rmapbt; 911 else 912 handlers[0].fn = xfs_getfsmap_datadev_bnobt; 913 if (mp->m_logdev_targp != mp->m_ddev_targp) { 914 + handlers[1].nr_sectors = XFS_FSB_TO_BB(mp, 915 + mp->m_sb.sb_logblocks); 916 handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev); 917 handlers[1].fn = xfs_getfsmap_logdev; 918 } 919 #ifdef CONFIG_XFS_RT 920 if (mp->m_rtdev_targp) { 921 + handlers[2].nr_sectors = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks); 922 handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev); 923 handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap; 924 } ··· 946 947 info.next_daddr = head->fmh_keys[0].fmr_physical + 948 head->fmh_keys[0].fmr_length; 949 + info.end_daddr = XFS_BUF_DADDR_NULL; 950 info.fsmap_recs = fsmap_recs; 951 info.head = head; 952 ··· 966 * low key, zero out the low key so that we get 967 * everything from the beginning. 968 */ 969 + if (handlers[i].dev == head->fmh_keys[1].fmr_device) { 970 dkeys[1] = head->fmh_keys[1]; 971 + info.end_daddr = min(handlers[i].nr_sectors - 1, 972 + dkeys[1].fmr_physical); 973 + } 974 if (handlers[i].dev > head->fmh_keys[0].fmr_device) 975 memset(&dkeys[0], 0, sizeof(struct xfs_fsmap)); 976