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_platform.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 17 static bool 18 xfs_validate_blk_zone_seq( 19 struct xfs_mount *mp, 20 struct blk_zone *zone, 21 unsigned int zone_no, 22 xfs_rgblock_t *write_pointer) 23 { 24 switch (zone->cond) { 25 case BLK_ZONE_COND_EMPTY: 26 *write_pointer = 0; 27 return true; 28 case BLK_ZONE_COND_IMP_OPEN: 29 case BLK_ZONE_COND_EXP_OPEN: 30 case BLK_ZONE_COND_CLOSED: 31 case BLK_ZONE_COND_ACTIVE: 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; 42 case BLK_ZONE_COND_FULL: 43 *write_pointer = XFS_BB_TO_FSB(mp, zone->capacity); 44 return true; 45 case BLK_ZONE_COND_NOT_WP: 46 case BLK_ZONE_COND_OFFLINE: 47 case BLK_ZONE_COND_READONLY: 48 xfs_warn(mp, "zone %u has unsupported zone condition 0x%x.", 49 zone_no, zone->cond); 50 return false; 51 default: 52 xfs_warn(mp, "zone %u has unknown zone condition 0x%x.", 53 zone_no, zone->cond); 54 return false; 55 } 56 } 57 58 static bool 59 xfs_validate_blk_zone_conv( 60 struct xfs_mount *mp, 61 struct blk_zone *zone, 62 unsigned int zone_no) 63 { 64 switch (zone->cond) { 65 case BLK_ZONE_COND_NOT_WP: 66 return true; 67 default: 68 xfs_warn(mp, 69 "conventional zone %u has unsupported zone condition 0x%x.", 70 zone_no, zone->cond); 71 return false; 72 } 73 } 74 75 bool 76 xfs_validate_blk_zone( 77 struct xfs_mount *mp, 78 struct blk_zone *zone, 79 unsigned int zone_no, 80 uint32_t expected_size, 81 uint32_t expected_capacity, 82 xfs_rgblock_t *write_pointer) 83 { 84 /* 85 * Check that the zone capacity matches the rtgroup size stored in the 86 * superblock. Note that all zones including the last one must have a 87 * uniform capacity. 88 */ 89 if (XFS_BB_TO_FSB(mp, zone->capacity) != expected_capacity) { 90 xfs_warn(mp, 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); 94 return false; 95 } 96 97 if (XFS_BB_TO_FSB(mp, zone->len) != expected_size) { 98 xfs_warn(mp, 99 "zone %u length (%llu) does not match geometry (%u).", 100 zone_no, XFS_BB_TO_FSB(mp, zone->len), 101 expected_size); 102 return false; 103 } 104 105 switch (zone->type) { 106 case BLK_ZONE_TYPE_CONVENTIONAL: 107 return xfs_validate_blk_zone_conv(mp, zone, zone_no); 108 case BLK_ZONE_TYPE_SEQWRITE_REQ: 109 return xfs_validate_blk_zone_seq(mp, zone, zone_no, 110 write_pointer); 111 default: 112 xfs_warn(mp, "zoned %u has unsupported type 0x%x.", 113 zone_no, zone->type); 114 return false; 115 } 116 } 117