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 error = xfs_mod_fdblocks(mp, -(int64_t)hidden_space, true); 215 if (error) { 216 trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno, 217 error, _RET_IP_); 218 xfs_warn(mp, 219 "Per-AG reservation for AG %u failed. Filesystem may run out of space.", 220 pag->pag_agno); 221 return error; 222 } 223 224 /* 225 * Reduce the maximum per-AG allocation length by however much we're 226 * trying to reserve for an AG. Since this is a filesystem-wide 227 * counter, we only make the adjustment for AG 0. This assumes that 228 * there aren't any AGs hungrier for per-AG reservation than AG 0. 229 */ 230 if (pag->pag_agno == 0) 231 mp->m_ag_max_usable -= ask; 232 233 resv = xfs_perag_resv(pag, type); 234 resv->ar_asked = ask; 235 resv->ar_orig_reserved = hidden_space; 236 resv->ar_reserved = ask - used; 237 238 trace_xfs_ag_resv_init(pag, type, ask); 239 return 0; 240 } 241 242 /* Create a per-AG block reservation. */ 243 int 244 xfs_ag_resv_init( 245 struct xfs_perag *pag, 246 struct xfs_trans *tp) 247 { 248 struct xfs_mount *mp = pag->pag_mount; 249 xfs_agnumber_t agno = pag->pag_agno; 250 xfs_extlen_t ask; 251 xfs_extlen_t used; 252 int error = 0; 253 254 /* Create the metadata reservation. */ 255 if (pag->pag_meta_resv.ar_asked == 0) { 256 ask = used = 0; 257 258 error = xfs_refcountbt_calc_reserves(mp, tp, agno, &ask, &used); 259 if (error) 260 goto out; 261 262 error = xfs_finobt_calc_reserves(mp, tp, agno, &ask, &used); 263 if (error) 264 goto out; 265 266 error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, 267 ask, used); 268 if (error) { 269 /* 270 * Because we didn't have per-AG reservations when the 271 * finobt feature was added we might not be able to 272 * reserve all needed blocks. Warn and fall back to the 273 * old and potentially buggy code in that case, but 274 * ensure we do have the reservation for the refcountbt. 275 */ 276 ask = used = 0; 277 278 mp->m_finobt_nores = true; 279 280 error = xfs_refcountbt_calc_reserves(mp, tp, agno, &ask, 281 &used); 282 if (error) 283 goto out; 284 285 error = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, 286 ask, used); 287 if (error) 288 goto out; 289 } 290 } 291 292 /* Create the RMAPBT metadata reservation */ 293 if (pag->pag_rmapbt_resv.ar_asked == 0) { 294 ask = used = 0; 295 296 error = xfs_rmapbt_calc_reserves(mp, tp, agno, &ask, &used); 297 if (error) 298 goto out; 299 300 error = __xfs_ag_resv_init(pag, XFS_AG_RESV_RMAPBT, ask, used); 301 if (error) 302 goto out; 303 } 304 305 #ifdef DEBUG 306 /* need to read in the AGF for the ASSERT below to work */ 307 error = xfs_alloc_pagf_init(pag->pag_mount, tp, pag->pag_agno, 0); 308 if (error) 309 return error; 310 311 ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved + 312 xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <= 313 pag->pagf_freeblks + pag->pagf_flcount); 314 #endif 315 out: 316 return error; 317 } 318 319 /* Allocate a block from the reservation. */ 320 void 321 xfs_ag_resv_alloc_extent( 322 struct xfs_perag *pag, 323 enum xfs_ag_resv_type type, 324 struct xfs_alloc_arg *args) 325 { 326 struct xfs_ag_resv *resv; 327 xfs_extlen_t len; 328 uint field; 329 330 trace_xfs_ag_resv_alloc_extent(pag, type, args->len); 331 332 switch (type) { 333 case XFS_AG_RESV_AGFL: 334 return; 335 case XFS_AG_RESV_METADATA: 336 case XFS_AG_RESV_RMAPBT: 337 resv = xfs_perag_resv(pag, type); 338 break; 339 default: 340 ASSERT(0); 341 /* fall through */ 342 case XFS_AG_RESV_NONE: 343 field = args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : 344 XFS_TRANS_SB_FDBLOCKS; 345 xfs_trans_mod_sb(args->tp, field, -(int64_t)args->len); 346 return; 347 } 348 349 len = min_t(xfs_extlen_t, args->len, resv->ar_reserved); 350 resv->ar_reserved -= len; 351 if (type == XFS_AG_RESV_RMAPBT) 352 return; 353 /* Allocations of reserved blocks only need on-disk sb updates... */ 354 xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_RES_FDBLOCKS, -(int64_t)len); 355 /* ...but non-reserved blocks need in-core and on-disk updates. */ 356 if (args->len > len) 357 xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_FDBLOCKS, 358 -((int64_t)args->len - len)); 359 } 360 361 /* Free a block to the reservation. */ 362 void 363 xfs_ag_resv_free_extent( 364 struct xfs_perag *pag, 365 enum xfs_ag_resv_type type, 366 struct xfs_trans *tp, 367 xfs_extlen_t len) 368 { 369 xfs_extlen_t leftover; 370 struct xfs_ag_resv *resv; 371 372 trace_xfs_ag_resv_free_extent(pag, type, len); 373 374 switch (type) { 375 case XFS_AG_RESV_AGFL: 376 return; 377 case XFS_AG_RESV_METADATA: 378 case XFS_AG_RESV_RMAPBT: 379 resv = xfs_perag_resv(pag, type); 380 break; 381 default: 382 ASSERT(0); 383 /* fall through */ 384 case XFS_AG_RESV_NONE: 385 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (int64_t)len); 386 return; 387 } 388 389 leftover = min_t(xfs_extlen_t, len, resv->ar_asked - resv->ar_reserved); 390 resv->ar_reserved += leftover; 391 if (type == XFS_AG_RESV_RMAPBT) 392 return; 393 /* Freeing into the reserved pool only requires on-disk update... */ 394 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RES_FDBLOCKS, len); 395 /* ...but freeing beyond that requires in-core and on-disk update. */ 396 if (len > leftover) 397 xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, len - leftover); 398 } 399