1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2022-2024 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <djwong@kernel.org> 5 */ 6 #include "xfs.h" 7 #include "xfs_fs.h" 8 #include "xfs_shared.h" 9 #include "xfs_format.h" 10 #include "xfs_trans_resv.h" 11 #include "xfs_bit.h" 12 #include "xfs_sb.h" 13 #include "xfs_mount.h" 14 #include "xfs_btree.h" 15 #include "xfs_alloc_btree.h" 16 #include "xfs_rmap_btree.h" 17 #include "xfs_alloc.h" 18 #include "xfs_ialloc.h" 19 #include "xfs_rmap.h" 20 #include "xfs_ag.h" 21 #include "xfs_ag_resv.h" 22 #include "xfs_health.h" 23 #include "xfs_error.h" 24 #include "xfs_bmap.h" 25 #include "xfs_defer.h" 26 #include "xfs_log_format.h" 27 #include "xfs_trans.h" 28 #include "xfs_trace.h" 29 #include "xfs_inode.h" 30 #include "xfs_icache.h" 31 #include "xfs_rtgroup.h" 32 #include "xfs_rtbitmap.h" 33 34 int 35 xfs_rtgroup_alloc( 36 struct xfs_mount *mp, 37 xfs_rgnumber_t rgno, 38 xfs_rgnumber_t rgcount, 39 xfs_rtbxlen_t rextents) 40 { 41 struct xfs_rtgroup *rtg; 42 int error; 43 44 rtg = kzalloc(sizeof(struct xfs_rtgroup), GFP_KERNEL); 45 if (!rtg) 46 return -ENOMEM; 47 48 error = xfs_group_insert(mp, rtg_group(rtg), rgno, XG_TYPE_RTG); 49 if (error) 50 goto out_free_rtg; 51 return 0; 52 53 out_free_rtg: 54 kfree(rtg); 55 return error; 56 } 57 58 void 59 xfs_rtgroup_free( 60 struct xfs_mount *mp, 61 xfs_rgnumber_t rgno) 62 { 63 xfs_group_free(mp, rgno, XG_TYPE_RTG, NULL); 64 } 65 66 /* Free a range of incore rtgroup objects. */ 67 void 68 xfs_free_rtgroups( 69 struct xfs_mount *mp, 70 xfs_rgnumber_t first_rgno, 71 xfs_rgnumber_t end_rgno) 72 { 73 xfs_rgnumber_t rgno; 74 75 for (rgno = first_rgno; rgno < end_rgno; rgno++) 76 xfs_rtgroup_free(mp, rgno); 77 } 78 79 /* Initialize some range of incore rtgroup objects. */ 80 int 81 xfs_initialize_rtgroups( 82 struct xfs_mount *mp, 83 xfs_rgnumber_t first_rgno, 84 xfs_rgnumber_t end_rgno, 85 xfs_rtbxlen_t rextents) 86 { 87 xfs_rgnumber_t index; 88 int error; 89 90 if (first_rgno >= end_rgno) 91 return 0; 92 93 for (index = first_rgno; index < end_rgno; index++) { 94 error = xfs_rtgroup_alloc(mp, index, end_rgno, rextents); 95 if (error) 96 goto out_unwind_new_rtgs; 97 } 98 99 return 0; 100 101 out_unwind_new_rtgs: 102 xfs_free_rtgroups(mp, first_rgno, index); 103 return error; 104 } 105 106 /* Compute the number of rt extents in this realtime group. */ 107 xfs_rtxnum_t 108 __xfs_rtgroup_extents( 109 struct xfs_mount *mp, 110 xfs_rgnumber_t rgno, 111 xfs_rgnumber_t rgcount, 112 xfs_rtbxlen_t rextents) 113 { 114 ASSERT(rgno < rgcount); 115 if (rgno == rgcount - 1) 116 return rextents - ((xfs_rtxnum_t)rgno * mp->m_sb.sb_rgextents); 117 118 ASSERT(xfs_has_rtgroups(mp)); 119 return mp->m_sb.sb_rgextents; 120 } 121 122 xfs_rtxnum_t 123 xfs_rtgroup_extents( 124 struct xfs_mount *mp, 125 xfs_rgnumber_t rgno) 126 { 127 return __xfs_rtgroup_extents(mp, rgno, mp->m_sb.sb_rgcount, 128 mp->m_sb.sb_rextents); 129 } 130 131 /* 132 * Update the rt extent count of the previous tail rtgroup if it changed during 133 * recovery (i.e. recovery of a growfs). 134 */ 135 int 136 xfs_update_last_rtgroup_size( 137 struct xfs_mount *mp, 138 xfs_rgnumber_t prev_rgcount) 139 { 140 struct xfs_rtgroup *rtg; 141 142 ASSERT(prev_rgcount > 0); 143 144 rtg = xfs_rtgroup_grab(mp, prev_rgcount - 1); 145 if (!rtg) 146 return -EFSCORRUPTED; 147 rtg->rtg_extents = __xfs_rtgroup_extents(mp, prev_rgcount - 1, 148 mp->m_sb.sb_rgcount, mp->m_sb.sb_rextents); 149 xfs_rtgroup_rele(rtg); 150 return 0; 151 } 152 153 /* Lock metadata inodes associated with this rt group. */ 154 void 155 xfs_rtgroup_lock( 156 struct xfs_rtgroup *rtg, 157 unsigned int rtglock_flags) 158 { 159 ASSERT(!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS)); 160 ASSERT(!(rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) || 161 !(rtglock_flags & XFS_RTGLOCK_BITMAP)); 162 163 if (rtglock_flags & XFS_RTGLOCK_BITMAP) 164 xfs_rtbitmap_lock(rtg_mount(rtg)); 165 else if (rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) 166 xfs_rtbitmap_lock_shared(rtg_mount(rtg), XFS_RBMLOCK_BITMAP); 167 } 168 169 /* Unlock metadata inodes associated with this rt group. */ 170 void 171 xfs_rtgroup_unlock( 172 struct xfs_rtgroup *rtg, 173 unsigned int rtglock_flags) 174 { 175 ASSERT(!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS)); 176 ASSERT(!(rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) || 177 !(rtglock_flags & XFS_RTGLOCK_BITMAP)); 178 179 if (rtglock_flags & XFS_RTGLOCK_BITMAP) 180 xfs_rtbitmap_unlock(rtg_mount(rtg)); 181 else if (rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED) 182 xfs_rtbitmap_unlock_shared(rtg_mount(rtg), XFS_RBMLOCK_BITMAP); 183 } 184 185 /* 186 * Join realtime group metadata inodes to the transaction. The ILOCKs will be 187 * released on transaction commit. 188 */ 189 void 190 xfs_rtgroup_trans_join( 191 struct xfs_trans *tp, 192 struct xfs_rtgroup *rtg, 193 unsigned int rtglock_flags) 194 { 195 ASSERT(!(rtglock_flags & ~XFS_RTGLOCK_ALL_FLAGS)); 196 ASSERT(!(rtglock_flags & XFS_RTGLOCK_BITMAP_SHARED)); 197 198 if (rtglock_flags & XFS_RTGLOCK_BITMAP) 199 xfs_rtbitmap_trans_join(tp); 200 } 201