xref: /linux/fs/xfs/libxfs/xfs_rtgroup.c (revision 0e4875b3fb24c5bfdf685876c76713cda5a23b65)
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