FILE
xfs_zones.c
File preview with syntax highlighting.
linux-6.19.14/fs/xfs/libxfs/xfs_zones.c
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2023-2025 Christoph Hellwig. 4 * Copyright (c) 2024-2025, Western Digital Corporation or its affiliates. 5 */ 6#include "xfs.h" 7#include "xfs_fs.h" 8#include "xfs_shared.h" 9#include "xfs_format.h" 10#include "xfs_log_format.h" 11#include "xfs_trans_resv.h" 12#include "xfs_mount.h" 13#include "xfs_inode.h" 14#include "xfs_rtgroup.h" 15#include "xfs_zones.h" 16 17static bool 18xfs_zone_validate_empty( 19 struct blk_zone *zone, 20 struct xfs_rtgroup *rtg, 21 xfs_rgblock_t *write_pointer) 22{ 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 35static bool 36xfs_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 66static bool 67xfs_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 84static bool 85xfs_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 switch (zone->cond) { 93 case BLK_ZONE_COND_EMPTY: 94 return xfs_zone_validate_empty(zone, rtg, write_pointer); 95 case BLK_ZONE_COND_IMP_OPEN: 96 case BLK_ZONE_COND_EXP_OPEN: 97 case BLK_ZONE_COND_CLOSED: 98 case BLK_ZONE_COND_ACTIVE: 99 return xfs_zone_validate_wp(zone, rtg, write_pointer); 100 case BLK_ZONE_COND_FULL: 101 return xfs_zone_validate_full(zone, rtg, write_pointer); 102 case BLK_ZONE_COND_NOT_WP: 103 case BLK_ZONE_COND_OFFLINE: 104 case BLK_ZONE_COND_READONLY: 105 xfs_warn(mp, "zone %u has unsupported zone condition 0x%x.", 106 rtg_rgno(rtg), zone->cond); 107 return false; 108 default: 109 xfs_warn(mp, "zone %u has unknown zone condition 0x%x.", 110 rtg_rgno(rtg), zone->cond); 111 return false; 112 } 113} 114 115static bool 116xfs_zone_validate_conv( 117 struct blk_zone *zone, 118 struct xfs_rtgroup *rtg) 119{ 120 struct xfs_mount *mp = rtg_mount(rtg); 121 122 switch (zone->cond) { 123 case BLK_ZONE_COND_NOT_WP: 124 return true; 125 default: 126 xfs_warn(mp, 127"conventional zone %u has unsupported zone condition 0x%x.", 128 rtg_rgno(rtg), zone->cond); 129 return false; 130 } 131} 132 133bool 134xfs_zone_validate( 135 struct blk_zone *zone, 136 struct xfs_rtgroup *rtg, 137 xfs_rgblock_t *write_pointer) 138{ 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 /* 144 * Check that the zone capacity matches the rtgroup size stored in the 145 * superblock. Note that all zones including the last one must have a 146 * uniform capacity. 147 */ 148 if (XFS_BB_TO_FSB(mp, zone->capacity) != g->blocks) { 149 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); 153 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 } 169 170 if (XFS_BB_TO_FSB(mp, zone->len) != expected_size) { 171 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), 174 expected_size); 175 } 176 177 switch (zone->type) { 178 case BLK_ZONE_TYPE_CONVENTIONAL: 179 return xfs_zone_validate_conv(zone, rtg); 180 case BLK_ZONE_TYPE_SEQWRITE_REQ: 181 return xfs_zone_validate_seq(zone, rtg, write_pointer); 182 default: 183 xfs_warn(mp, "zoned %u has unsupported type 0x%x.", 184 rtg_rgno(rtg), zone->type); 185 return false; 186 } 187}
~/
Read-only file preview.