Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

xfs: split and refactor zone validation

Currently xfs_zone_validate mixes validating the software zone state in
the XFS realtime group with validating the hardware state reported in
struct blk_zone and deriving the write pointer from that.

Move all code that works on the realtime group to xfs_init_zone, and only
keep the hardware state validation in xfs_zone_validate. This makes the
code more clear, and allows for better reuse in userspace.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>

authored by

Christoph Hellwig and committed by
Carlos Maiolino
19c5b605 776b76f7

+68 -114
+39 -110
fs/xfs/libxfs/xfs_zones.c
··· 15 15 #include "xfs_zones.h" 16 16 17 17 static bool 18 - xfs_zone_validate_empty( 18 + xfs_validate_blk_zone_seq( 19 + struct xfs_mount *mp, 19 20 struct blk_zone *zone, 20 - struct xfs_rtgroup *rtg, 21 + unsigned int zone_no, 21 22 xfs_rgblock_t *write_pointer) 22 23 { 23 - struct xfs_mount *mp = rtg_mount(rtg); 24 - 25 - if (rtg_rmap(rtg)->i_used_blocks > 0) { 26 - xfs_warn(mp, "empty zone %u has non-zero used counter (0x%x).", 27 - rtg_rgno(rtg), rtg_rmap(rtg)->i_used_blocks); 28 - return false; 29 - } 30 - 31 - *write_pointer = 0; 32 - return true; 33 - } 34 - 35 - static bool 36 - xfs_zone_validate_wp( 37 - struct blk_zone *zone, 38 - struct xfs_rtgroup *rtg, 39 - xfs_rgblock_t *write_pointer) 40 - { 41 - struct xfs_mount *mp = rtg_mount(rtg); 42 - xfs_rtblock_t wp_fsb = xfs_daddr_to_rtb(mp, zone->wp); 43 - 44 - if (rtg_rmap(rtg)->i_used_blocks > rtg->rtg_extents) { 45 - xfs_warn(mp, "zone %u has too large used counter (0x%x).", 46 - rtg_rgno(rtg), rtg_rmap(rtg)->i_used_blocks); 47 - return false; 48 - } 49 - 50 - if (xfs_rtb_to_rgno(mp, wp_fsb) != rtg_rgno(rtg)) { 51 - xfs_warn(mp, "zone %u write pointer (0x%llx) outside of zone.", 52 - rtg_rgno(rtg), wp_fsb); 53 - return false; 54 - } 55 - 56 - *write_pointer = xfs_rtb_to_rgbno(mp, wp_fsb); 57 - if (*write_pointer >= rtg->rtg_extents) { 58 - xfs_warn(mp, "zone %u has invalid write pointer (0x%x).", 59 - rtg_rgno(rtg), *write_pointer); 60 - return false; 61 - } 62 - 63 - return true; 64 - } 65 - 66 - static bool 67 - xfs_zone_validate_full( 68 - struct blk_zone *zone, 69 - struct xfs_rtgroup *rtg, 70 - xfs_rgblock_t *write_pointer) 71 - { 72 - struct xfs_mount *mp = rtg_mount(rtg); 73 - 74 - if (rtg_rmap(rtg)->i_used_blocks > rtg->rtg_extents) { 75 - xfs_warn(mp, "zone %u has too large used counter (0x%x).", 76 - rtg_rgno(rtg), rtg_rmap(rtg)->i_used_blocks); 77 - return false; 78 - } 79 - 80 - *write_pointer = rtg->rtg_extents; 81 - return true; 82 - } 83 - 84 - static bool 85 - xfs_zone_validate_seq( 86 - struct blk_zone *zone, 87 - struct xfs_rtgroup *rtg, 88 - xfs_rgblock_t *write_pointer) 89 - { 90 - struct xfs_mount *mp = rtg_mount(rtg); 91 - 92 24 switch (zone->cond) { 93 25 case BLK_ZONE_COND_EMPTY: 94 - return xfs_zone_validate_empty(zone, rtg, write_pointer); 26 + *write_pointer = 0; 27 + return true; 95 28 case BLK_ZONE_COND_IMP_OPEN: 96 29 case BLK_ZONE_COND_EXP_OPEN: 97 30 case BLK_ZONE_COND_CLOSED: 98 31 case BLK_ZONE_COND_ACTIVE: 99 - return xfs_zone_validate_wp(zone, rtg, write_pointer); 32 + if (zone->wp < zone->start || 33 + zone->wp >= zone->start + zone->capacity) { 34 + xfs_warn(mp, 35 + "zone %u write pointer (%llu) outside of zone.", 36 + zone_no, zone->wp); 37 + return false; 38 + } 39 + 40 + *write_pointer = XFS_BB_TO_FSB(mp, zone->wp - zone->start); 41 + return true; 100 42 case BLK_ZONE_COND_FULL: 101 - return xfs_zone_validate_full(zone, rtg, write_pointer); 43 + *write_pointer = XFS_BB_TO_FSB(mp, zone->capacity); 44 + return true; 102 45 case BLK_ZONE_COND_NOT_WP: 103 46 case BLK_ZONE_COND_OFFLINE: 104 47 case BLK_ZONE_COND_READONLY: 105 48 xfs_warn(mp, "zone %u has unsupported zone condition 0x%x.", 106 - rtg_rgno(rtg), zone->cond); 49 + zone_no, zone->cond); 107 50 return false; 108 51 default: 109 52 xfs_warn(mp, "zone %u has unknown zone condition 0x%x.", 110 - rtg_rgno(rtg), zone->cond); 53 + zone_no, zone->cond); 111 54 return false; 112 55 } 113 56 } 114 57 115 58 static bool 116 - xfs_zone_validate_conv( 59 + xfs_validate_blk_zone_conv( 60 + struct xfs_mount *mp, 117 61 struct blk_zone *zone, 118 - struct xfs_rtgroup *rtg) 62 + unsigned int zone_no) 119 63 { 120 - struct xfs_mount *mp = rtg_mount(rtg); 121 - 122 64 switch (zone->cond) { 123 65 case BLK_ZONE_COND_NOT_WP: 124 66 return true; 125 67 default: 126 68 xfs_warn(mp, 127 69 "conventional zone %u has unsupported zone condition 0x%x.", 128 - rtg_rgno(rtg), zone->cond); 70 + zone_no, zone->cond); 129 71 return false; 130 72 } 131 73 } 132 74 133 75 bool 134 - xfs_zone_validate( 76 + xfs_validate_blk_zone( 77 + struct xfs_mount *mp, 135 78 struct blk_zone *zone, 136 - struct xfs_rtgroup *rtg, 79 + unsigned int zone_no, 80 + uint32_t expected_size, 81 + uint32_t expected_capacity, 137 82 xfs_rgblock_t *write_pointer) 138 83 { 139 - struct xfs_mount *mp = rtg_mount(rtg); 140 - struct xfs_groups *g = &mp->m_groups[XG_TYPE_RTG]; 141 - uint32_t expected_size; 142 - 143 84 /* 144 85 * Check that the zone capacity matches the rtgroup size stored in the 145 86 * superblock. Note that all zones including the last one must have a 146 87 * uniform capacity. 147 88 */ 148 - if (XFS_BB_TO_FSB(mp, zone->capacity) != g->blocks) { 89 + if (XFS_BB_TO_FSB(mp, zone->capacity) != expected_capacity) { 149 90 xfs_warn(mp, 150 - "zone %u capacity (0x%llx) does not match RT group size (0x%x).", 151 - rtg_rgno(rtg), XFS_BB_TO_FSB(mp, zone->capacity), 152 - g->blocks); 91 + "zone %u capacity (%llu) does not match RT group size (%u).", 92 + zone_no, XFS_BB_TO_FSB(mp, zone->capacity), 93 + expected_capacity); 153 94 return false; 154 - } 155 - 156 - if (g->has_daddr_gaps) { 157 - expected_size = 1 << g->blklog; 158 - } else { 159 - if (zone->len != zone->capacity) { 160 - xfs_warn(mp, 161 - "zone %u has capacity != size ((0x%llx vs 0x%llx)", 162 - rtg_rgno(rtg), 163 - XFS_BB_TO_FSB(mp, zone->len), 164 - XFS_BB_TO_FSB(mp, zone->capacity)); 165 - return false; 166 - } 167 - expected_size = g->blocks; 168 95 } 169 96 170 97 if (XFS_BB_TO_FSB(mp, zone->len) != expected_size) { 171 98 xfs_warn(mp, 172 - "zone %u length (0x%llx) does match geometry (0x%x).", 173 - rtg_rgno(rtg), XFS_BB_TO_FSB(mp, zone->len), 99 + "zone %u length (%llu) does not match geometry (%u).", 100 + zone_no, XFS_BB_TO_FSB(mp, zone->len), 174 101 expected_size); 102 + return false; 175 103 } 176 104 177 105 switch (zone->type) { 178 106 case BLK_ZONE_TYPE_CONVENTIONAL: 179 - return xfs_zone_validate_conv(zone, rtg); 107 + return xfs_validate_blk_zone_conv(mp, zone, zone_no); 180 108 case BLK_ZONE_TYPE_SEQWRITE_REQ: 181 - return xfs_zone_validate_seq(zone, rtg, write_pointer); 109 + return xfs_validate_blk_zone_seq(mp, zone, zone_no, 110 + write_pointer); 182 111 default: 183 112 xfs_warn(mp, "zoned %u has unsupported type 0x%x.", 184 - rtg_rgno(rtg), zone->type); 113 + zone_no, zone->type); 185 114 return false; 186 115 } 187 116 }
+3 -2
fs/xfs/libxfs/xfs_zones.h
··· 37 37 */ 38 38 #define XFS_DEFAULT_MAX_OPEN_ZONES 128 39 39 40 - bool xfs_zone_validate(struct blk_zone *zone, struct xfs_rtgroup *rtg, 41 - xfs_rgblock_t *write_pointer); 40 + bool xfs_validate_blk_zone(struct xfs_mount *mp, struct blk_zone *zone, 41 + unsigned int zone_no, uint32_t expected_size, 42 + uint32_t expected_capacity, xfs_rgblock_t *write_pointer); 42 43 43 44 #endif /* _LIBXFS_ZONES_H */
+26 -2
fs/xfs/xfs_zone_alloc.c
··· 977 977 978 978 struct xfs_init_zones { 979 979 struct xfs_mount *mp; 980 + uint32_t zone_size; 981 + uint32_t zone_capacity; 980 982 uint64_t available; 981 983 uint64_t reclaimable; 982 984 }; 983 985 984 986 /* 985 987 * For sequential write required zones, we restart writing at the hardware write 986 - * pointer returned by xfs_zone_validate(). 988 + * pointer returned by xfs_validate_blk_zone(). 987 989 * 988 990 * For conventional zones or conventional devices we have to query the rmap to 989 991 * find the highest recorded block and set the write pointer to the block after ··· 1019 1017 struct xfs_zone_info *zi = mp->m_zone_info; 1020 1018 uint32_t used = rtg_rmap(rtg)->i_used_blocks; 1021 1019 int error; 1020 + 1021 + if (write_pointer > rtg->rtg_extents) { 1022 + xfs_warn(mp, "zone %u has invalid write pointer (0x%x).", 1023 + rtg_rgno(rtg), write_pointer); 1024 + return -EFSCORRUPTED; 1025 + } 1026 + 1027 + if (used > rtg->rtg_extents) { 1028 + xfs_warn(mp, 1029 + "zone %u has used counter (0x%x) larger than zone capacity (0x%llx).", 1030 + rtg_rgno(rtg), used, rtg->rtg_extents); 1031 + return -EFSCORRUPTED; 1032 + } 1033 + 1034 + if (write_pointer == 0 && used != 0) { 1035 + xfs_warn(mp, "empty zone %u has non-zero used counter (0x%x).", 1036 + rtg_rgno(rtg), used); 1037 + return -EFSCORRUPTED; 1038 + } 1022 1039 1023 1040 /* 1024 1041 * If there are no used blocks, but the zone is not in empty state yet ··· 1102 1081 xfs_warn(mp, "realtime group not found for zone %u.", rgno); 1103 1082 return -EFSCORRUPTED; 1104 1083 } 1105 - if (!xfs_zone_validate(zone, rtg, &write_pointer)) { 1084 + if (!xfs_validate_blk_zone(mp, zone, idx, iz->zone_size, 1085 + iz->zone_capacity, &write_pointer)) { 1106 1086 xfs_rtgroup_rele(rtg); 1107 1087 return -EFSCORRUPTED; 1108 1088 } ··· 1249 1227 { 1250 1228 struct xfs_init_zones iz = { 1251 1229 .mp = mp, 1230 + .zone_capacity = mp->m_groups[XG_TYPE_RTG].blocks, 1231 + .zone_size = xfs_rtgroup_raw_size(mp), 1252 1232 }; 1253 1233 struct xfs_buftarg *bt = mp->m_rtdev_targp; 1254 1234 xfs_extlen_t zone_blocks = mp->m_groups[XG_TYPE_RTG].blocks;