1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2016 Oracle. All Rights Reserved. 4 * Author: Darrick J. Wong <darrick.wong@oracle.com> 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_alloc.h" 14 #include "xfs_errortag.h" 15 #include "xfs_error.h" 16 #include "xfs_trace.h" 17 #include "xfs_trans.h" 18 #include "xfs_rmap_btree.h" 19 #include "xfs_btree.h" 20 #include "xfs_refcount_btree.h" 21 #include "xfs_ialloc_btree.h" 22 #include "xfs_sb.h" 23 #include "xfs_ag_resv.h" 24 25 /* 26 * Per-AG Block Reservations 27 * 28 * For some kinds of allocation group metadata structures, it is advantageous 29 * to reserve a small number of blocks in each AG so that future expansions of 30 * that data structure do not encounter ENOSPC because errors during a btree 31 * split cause the filesystem to go offline. 32 * 33 * Prior to the introduction of reflink, this wasn't an issue because the free 34 * space btrees maintain a reserve of space (the AGFL) to handle any expansion 35 * that may be necessary; and allocations of other metadata (inodes, BMBT, 36 * dir/attr) aren't restricted to a single AG. However, with reflink it is 37 * possible to allocate all the space in an AG, have subsequent reflink/CoW 38 * activity expand the refcount btree, and discover that there's no space left 39 * to handle that expansion. Since we can calculate the maximum size of the 40 * refcount btree, we can reserve space for it and avoid ENOSPC. 41 * 42 * Handling per-AG reservations consists of three changes to the allocator's 43 * behavior: First, because these reservations are always needed, we decrease 44 * the ag_max_usable counter to reflect the size of the AG after the reserved 45 * blocks are taken. Second, the reservations must be reflected in the 46 * fdblocks count to maintain proper accounting. Third, each AG must maintain 47 * its own reserved block counter so that we can calculate the amount of space 48 * that must remain free to maintain the reservations. Fourth, the "remaining 49 * reserved blocks" count must be used when calculating the length of the 50 * longest free extent in an AG and to clamp maxlen in the per-AG allocation 51 * functions. In other words, we maintain a virtual allocation via in-core 52 * accounting tricks so that we don't have to clean up after a crash. :) 53 * 54 * Reserved blocks can be managed by passing one of the enum xfs_ag_resv_type 55 * values via struct xfs_alloc_arg or directly to the xfs_free_extent 56 * function. It might seem a little funny to maintain a reservoir of blocks 57 * to feed another reservoir, but the AGFL only holds enough blocks to get 58 * through the next transaction. The per-AG reservation is to ensure (we 59 * hope) that each AG never runs out of blocks. Each data structure wanting 60 * to use the reservation system should update ask/used in xfs_ag_resv_init. 61 */ 62 63 /* 64 * Are we critically low on blocks? For now we'll define that as the number 65 * of blocks we can get our hands on being less than 10% of what we reserved 66 * or less than some arbitrary number (maximum btree height). 67 */ 68 bool 69 xfs_ag_resv_critical( 70 struct xfs_perag *pag, 71 enum xfs_ag_resv_type type) 72 { 73 xfs_extlen_t avail; 74 xfs_extlen_t orig; 75 76 switch (type) { 77 case XFS_AG_RESV_METADATA: 78 avail = pag->pagf_freeblks - pag->pag_rmapbt_resv.ar_reserved; 79 orig = pag->pag_meta_resv.ar_asked; 80 break; 81 case XFS_AG_RESV_RMAPBT: 82 avail = pag->pagf_freeblks + pag->pagf_flcount - 83 pag->pag_meta_resv.ar_reserved; 84 orig = pag->pag_rmapbt_resv.ar_asked; 85 break; 86 default: 87 ASSERT(0); 88 return false; 89 } 90 91 trace_xfs_ag_resv_critical(pag, type, avail); 92 93 /* Critically low if less than 10% or max btree height remains. */ 94 return XFS_TEST_ERROR(avail < orig / 10 || avail < XFS_BTREE_MAXLEVELS, 95 pag->pag_mount, XFS_ERRTAG_AG_RESV_CRITICAL); 96 } 97 98 /* 99 * How many blocks are reserved but not used, and therefore must not be 100 * allocated away? 101 */ 102 xfs_extlen_t 103 xfs_ag_resv_needed( 104 struct xfs_perag *pag, 105 enum xfs_ag_resv_type type) 106 { 107 xfs_extlen_t len; 108 109 len = pag->pag_meta_resv.ar_reserved + pag->pag_rmapbt_resv.ar_reserved; 110 switch (type) { 111 case XFS_AG_RESV_METADATA: 112 case XFS_AG_RESV_RMAPBT: 113 len -= xfs_perag_resv(pag, type)->ar_reserved; 114 break; 115 case XFS_AG_RESV_NONE: 116 /* empty */ 117 break; 118 default: 119 ASSERT(0); 120 } 121 122 trace_xfs_ag_resv_needed(pag, type, len); 123 124 return len; 125 } 126 127 /* Clean out a reservation */ 128 static int 129 __xfs_ag_resv_free( 130 struct xfs_perag *pag, 131 enum xfs_ag_resv_type type) 132 { 133 struct xfs_ag_resv *resv; 134 xfs_extlen_t oldresv; 135 int error; 136 137 trace_xfs_ag_resv_free(pag, type, 0); 138 139 resv = xfs_perag_resv(pag, type); 140 if (pag->pag_agno == 0) 141 pag->pag_mount->m_ag_max_usable += resv->ar_asked; 142 /* 143 * RMAPBT blocks come from the AGFL and AGFL blocks are always 144 * considered "free", so whatever was reserved at mount time must be 145 * given back at umount. 146 */ 147 if (type == XFS_AG_RESV_RMAPBT) 148 oldresv = resv->ar_orig_reserved; 149 else 150 oldresv = resv->ar_reserved; 151 error = xfs_mod_fdblocks(pag->pag_mount, oldresv, true); 152 resv->ar_reserved = 0; 153 resv->ar_asked = 0; 154 resv->ar_orig_reserved = 0; 155 156 if (error) 157 trace_xfs_ag_resv_free_error(pag->pag_mount, pag->pag_agno, 158 error, _RET_IP_); 159 return error; 160 } 161 162 /* Free a per-AG reservation. */ 163 int 164 xfs_ag_resv_free( 165 struct xfs_perag *pag) 166 { 167 int error; 168 int err2; 169 170 error = __xfs_ag_resv_free(pag, XFS_AG_RESV_RMAPBT); 171 err2 = __xfs_ag_resv_free(pag, XFS_AG_RESV_METADATA); 172 if (err2 && !error) 173 error = err2; 174 return error; 175 } 176 177 static int 178 __xfs_ag_resv_init( 179 struct xfs_perag *pag, 180 enum xfs_ag_resv_type type, 181 xfs_extlen_t ask, 182 xfs_extlen_t used) 183 { 184 struct xfs_mount *mp = pag->pag_mount; 185 struct xfs_ag_resv *resv; 186 int error; 187 xfs_extlen_t hidden_space; 188 189 if (used > ask) 190 ask = used; 191 192 switch (type) { 193 case XFS_AG_RESV_RMAPBT: 194 /* 195 * Space taken by the rmapbt is not subtracted from fdblocks 196 * because the rmapbt lives in the free space. Here we must 197 * subtract the entire reservation from fdblocks so that we 198 * always have blocks available for rmapbt expansion. 199 */ 200 hidden_space = ask; 201 break; 202 case XFS_AG_RESV_METADATA: 203 /* 204 * Space taken by all other metadata btrees are accounted 205 * on-disk as used space. We therefore only hide the space 206 * that is reserved but not used by the trees. 207 */ 208 hidden_space = ask - used; 209 break; 210 default: 211 ASSERT(0); 212 return -EINVAL; 213 } 214 215 if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_AG_RESV_FAIL)) 216 error = -ENOSPC; 217 else 218 error = xfs_mod_fdblocks(mp, -(int64_t)hidden_space, true); 219 if (error) { 220 trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno, 221 error, _RET_IP_); 222 xfs_warn(mp, 223 "Per-AG reservation for AG %u failed. Filesystem may run out of space.", 224 pag->pag_agno); 225 return error; 226 } 227 228 /* 229 * Reduce the maximum per-AG allocation length by however much we're 230 * trying to reserve for an AG. Since this is a filesystem-wide 231 * counter, we only make the adjustment for AG 0. This assumes that 232 * there aren't any AGs hungrier for per-AG reservation than AG 0. 233 */ 234 if (pag->pag_agno == 0) 235 mp->m_ag_max_usable -= ask; 236 237 resv = xfs_perag_resv(pag, type); 238 resv->ar_asked = ask; 239 resv->ar_orig_reserved = hidden_space; 240 resv->ar_reserved = ask - used; 241 242 trace_xfs_ag_resv_init(pag, type, ask); 243 return 0; 244 } 245 246 /* Create a per-AG block reservation. */ 247 int 248 xfs_ag_resv_init( 249 struct xfs_perag *pag, 250 struct xfs_trans *tp) 251 { 252 struct xfs_mount *mp = pag->pag_mount; 253 xfs_agnumber_t agno = pag->pag_agno; 254 xfs_extlen_t ask; 255 xfs_extlen_t used; 256 int error = 0; 257 258 /* Create the metadata reservation. */ 259 if (pag->pag_meta_resv.ar_asked == 0) { 260 ask = used = 0; 261 262 error = xfs_refcountbt_calc_reserves(mp, tp, agno, &ask, &used); 263 if (error) 264 goto out; 265 266 error = xfs_finobt_calc_reserves(mp, tp, agno, &ask, &used); 267 if (error) 268 goto out; 269 270 error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, 271 ask, used); 272 if (error) { 273 /* 274 * Because we didn't have per-AG reservations when the 275 * finobt feature was added we might not be able to 276 * reserve all needed blocks. Warn and fall back to the 277 * old and potentially buggy code in that case, but 278 * ensure we do have the reservation for the refcountbt. 279 */ 280 ask = used = 0; 281 282 mp->m_finobt_nores = true; 283 284 error = xfs_refcountbt_calc_reserves(mp, tp, agno, &ask, 285 &used); 286 if (error) 287 goto out; 288 289 error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, 290 ask, used); 291 if (error) 292 goto out; 293 } 294 } 295 296 /* Create the RMAPBT metadata reservation */ 297 if (pag->pag_rmapbt_resv.ar_asked == 0) { 298 ask = used = 0; 299 300 error = xfs_rmapbt_calc_reserves(mp, tp, agno, &ask, &used); 301 if (error) 302 goto out; 303 304 error = __xfs_ag_resv_init(pag, XFS_AG_RESV_RMAPBT, ask, used); 305 if (error) 306 goto out; 307 } 308 309 #ifdef DEBUG 310 /* need to read in the AGF for the ASSERT below to work */ 311 error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0); 312 if (error) 313 return error; 314 315 ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved + 316 xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <= 317 pag->pagf_freeblks + pag->pagf_flcount); 318 #endif 319 out: 320 return error; 321 } 322 323 /* Allocate a block from the reservation. */ 324 void 325 xfs_ag_resv_alloc_extent( 326 struct xfs_perag *pag, 327 enum xfs_ag_resv_type type, 328 struct xfs_alloc_arg *args) 329 { 330 struct xfs_ag_resv *resv; 331 xfs_extlen_t len; 332 uint field; 333 334 trace_xfs_ag_resv_alloc_extent(pag, type, args->len); 335 336 switch (type) { 337 case XFS_AG_RESV_AGFL: 338 return; 339 case XFS_AG_RESV_METADATA: 340 case XFS_AG_RESV_RMAPBT: 341 resv = xfs_perag_resv(pag, type); 342 break; 343 default: 344 ASSERT(0); 345 /* fall through */ 346 case XFS_AG_RESV_NONE: 347 field = args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : 348 XFS_TRANS_SB_FDBLOCKS; 349 xfs_trans_mod_sb(args->tp, field, -(int64_t)args->len); 350 return; 351 } 352 353 len = min_t(xfs_extlen_t, args->len, resv->ar_reserved); 354 resv->ar_reserved -= len; 355 if (type == XFS_AG_RESV_RMAPBT) 356 return; 357 /* Allocations of reserved blocks only need on-disk sb updates... */ 358 xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_RES_FDBLOCKS, -(int64_t)len); 359 /* ...but non-reserved blocks need in-core and on-disk updates. */ 360 if (args->len > len) 361 xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_FDBLOCKS, 362 -((int64_t)args->len - len)); 363 } 364 365 /* Free a block to the reservation. */ 366 void 367 xfs_ag_resv_free_extent( 368 struct xfs_perag *pag, 369 enum xfs_ag_resv_type type, 370 struct xfs_trans *tp, 371 xfs_extlen_t len) 372 { 373 xfs_extlen_t leftover; 374 struct xfs_ag_resv *resv; 375 376 trace_xfs_ag_resv_free_extent(pag, type, len); 377 378 switch (type) { 379 case XFS_AG_RESV_AGFL: 380 return; 381 case XFS_AG_RESV_METADATA: 382 case XFS_AG_RESV_RMAPBT: 383 resv = xfs_perag_resv(pag, type); 384 break; 385 default: 386 ASSERT(0); 387 /* fall through */ 388 case XFS_AG_RESV_NONE: 389 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (int64_t)len); 390 return; 391 } 392 393 leftover = min_t(xfs_extlen_t, len, resv->ar_asked - resv->ar_reserved); 394 resv->ar_reserved += leftover; 395 if (type == XFS_AG_RESV_RMAPBT) 396 return; 397 /* Freeing into the reserved pool only requires on-disk update... */ 398 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FDBLOCKS, len); 399 /* ...but freeing beyond that requires in-core and on-disk update. */ 400 if (len > leftover) 401 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, len - leftover); 402 } 403