Skip to content

Commit d8cb5e4

Browse files
committed
xfs: fix fdblocks accounting w/ RMAPBT per-AG reservation
In __xfs_ag_resv_init we incorrectly calculate the amount by which to decrease fdblocks when reserving blocks for the rmapbt. Because rmapbt allocations do not decrease fdblocks, we must decrease fdblocks by the entire size of the requested reservation in order to achieve our goal of always having enough free blocks to satisfy an rmapbt expansion. This is in contrast to the refcountbt/finobt, which /do/ subtract from fdblocks whenever they allocate a block. For this allocation type we preserve the existing behavior where we decrease fdblocks only by the requested reservation minus the size of the existing tree. This fixes the problem where the available block counts reported by statfs change across a remount if there had been an rmapbt size change since mount time. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
1 parent e53c4b5 commit d8cb5e4

File tree

1 file changed

+27
-4
lines changed

1 file changed

+27
-4
lines changed

fs/xfs/libxfs/xfs_ag_resv.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ __xfs_ag_resv_free(
157157
error = xfs_mod_fdblocks(pag->pag_mount, oldresv, true);
158158
resv->ar_reserved = 0;
159159
resv->ar_asked = 0;
160+
resv->ar_orig_reserved = 0;
160161

161162
if (error)
162163
trace_xfs_ag_resv_free_error(pag->pag_mount, pag->pag_agno,
@@ -189,13 +190,34 @@ __xfs_ag_resv_init(
189190
struct xfs_mount *mp = pag->pag_mount;
190191
struct xfs_ag_resv *resv;
191192
int error;
192-
xfs_extlen_t reserved;
193+
xfs_extlen_t hidden_space;
193194

194195
if (used > ask)
195196
ask = used;
196-
reserved = ask - used;
197197

198-
error = xfs_mod_fdblocks(mp, -(int64_t)reserved, true);
198+
switch (type) {
199+
case XFS_AG_RESV_RMAPBT:
200+
/*
201+
* Space taken by the rmapbt is not subtracted from fdblocks
202+
* because the rmapbt lives in the free space. Here we must
203+
* subtract the entire reservation from fdblocks so that we
204+
* always have blocks available for rmapbt expansion.
205+
*/
206+
hidden_space = ask;
207+
break;
208+
case XFS_AG_RESV_METADATA:
209+
/*
210+
* Space taken by all other metadata btrees are accounted
211+
* on-disk as used space. We therefore only hide the space
212+
* that is reserved but not used by the trees.
213+
*/
214+
hidden_space = ask - used;
215+
break;
216+
default:
217+
ASSERT(0);
218+
return -EINVAL;
219+
}
220+
error = xfs_mod_fdblocks(mp, -(int64_t)hidden_space, true);
199221
if (error) {
200222
trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno,
201223
error, _RET_IP_);
@@ -216,7 +238,8 @@ __xfs_ag_resv_init(
216238

217239
resv = xfs_perag_resv(pag, type);
218240
resv->ar_asked = ask;
219-
resv->ar_reserved = resv->ar_orig_reserved = reserved;
241+
resv->ar_orig_reserved = hidden_space;
242+
resv->ar_reserved = ask - used;
220243

221244
trace_xfs_ag_resv_init(pag, type, ask);
222245
return 0;

0 commit comments

Comments
 (0)