1055 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * Copyright (c) 2000-2005 Silicon Graphics, Inc.4 * Copyright (c) 2018 Red Hat, Inc.5 * All rights reserved.6 */7 8#include "xfs.h"9#include "xfs_fs.h"10#include "xfs_shared.h"11#include "xfs_format.h"12#include "xfs_trans_resv.h"13#include "xfs_bit.h"14#include "xfs_sb.h"15#include "xfs_mount.h"16#include "xfs_btree.h"17#include "xfs_alloc_btree.h"18#include "xfs_rmap_btree.h"19#include "xfs_alloc.h"20#include "xfs_ialloc.h"21#include "xfs_rmap.h"22#include "xfs_ag.h"23#include "xfs_ag_resv.h"24#include "xfs_health.h"25#include "xfs_error.h"26#include "xfs_bmap.h"27#include "xfs_defer.h"28#include "xfs_log_format.h"29#include "xfs_trans.h"30#include "xfs_trace.h"31#include "xfs_inode.h"32#include "xfs_icache.h"33 34 35/*36 * Passive reference counting access wrappers to the perag structures. If the37 * per-ag structure is to be freed, the freeing code is responsible for cleaning38 * up objects with passive references before freeing the structure. This is39 * things like cached buffers.40 */41struct xfs_perag *42xfs_perag_get(43 struct xfs_mount *mp,44 xfs_agnumber_t agno)45{46 struct xfs_perag *pag;47 48 rcu_read_lock();49 pag = xa_load(&mp->m_perags, agno);50 if (pag) {51 trace_xfs_perag_get(pag, _RET_IP_);52 ASSERT(atomic_read(&pag->pag_ref) >= 0);53 atomic_inc(&pag->pag_ref);54 }55 rcu_read_unlock();56 return pag;57}58 59/* Get a passive reference to the given perag. */60struct xfs_perag *61xfs_perag_hold(62 struct xfs_perag *pag)63{64 ASSERT(atomic_read(&pag->pag_ref) > 0 ||65 atomic_read(&pag->pag_active_ref) > 0);66 67 trace_xfs_perag_hold(pag, _RET_IP_);68 atomic_inc(&pag->pag_ref);69 return pag;70}71 72void73xfs_perag_put(74 struct xfs_perag *pag)75{76 trace_xfs_perag_put(pag, _RET_IP_);77 ASSERT(atomic_read(&pag->pag_ref) > 0);78 atomic_dec(&pag->pag_ref);79}80 81/*82 * Active references for perag structures. This is for short term access to the83 * per ag structures for walking trees or accessing state. If an AG is being84 * shrunk or is offline, then this will fail to find that AG and return NULL85 * instead.86 */87struct xfs_perag *88xfs_perag_grab(89 struct xfs_mount *mp,90 xfs_agnumber_t agno)91{92 struct xfs_perag *pag;93 94 rcu_read_lock();95 pag = xa_load(&mp->m_perags, agno);96 if (pag) {97 trace_xfs_perag_grab(pag, _RET_IP_);98 if (!atomic_inc_not_zero(&pag->pag_active_ref))99 pag = NULL;100 }101 rcu_read_unlock();102 return pag;103}104 105void106xfs_perag_rele(107 struct xfs_perag *pag)108{109 trace_xfs_perag_rele(pag, _RET_IP_);110 if (atomic_dec_and_test(&pag->pag_active_ref))111 wake_up(&pag->pag_active_wq);112}113 114/*115 * xfs_initialize_perag_data116 *117 * Read in each per-ag structure so we can count up the number of118 * allocated inodes, free inodes and used filesystem blocks as this119 * information is no longer persistent in the superblock. Once we have120 * this information, write it into the in-core superblock structure.121 */122int123xfs_initialize_perag_data(124 struct xfs_mount *mp,125 xfs_agnumber_t agcount)126{127 xfs_agnumber_t index;128 struct xfs_perag *pag;129 struct xfs_sb *sbp = &mp->m_sb;130 uint64_t ifree = 0;131 uint64_t ialloc = 0;132 uint64_t bfree = 0;133 uint64_t bfreelst = 0;134 uint64_t btree = 0;135 uint64_t fdblocks;136 int error = 0;137 138 for (index = 0; index < agcount; index++) {139 /*140 * Read the AGF and AGI buffers to populate the per-ag141 * structures for us.142 */143 pag = xfs_perag_get(mp, index);144 error = xfs_alloc_read_agf(pag, NULL, 0, NULL);145 if (!error)146 error = xfs_ialloc_read_agi(pag, NULL, 0, NULL);147 if (error) {148 xfs_perag_put(pag);149 return error;150 }151 152 ifree += pag->pagi_freecount;153 ialloc += pag->pagi_count;154 bfree += pag->pagf_freeblks;155 bfreelst += pag->pagf_flcount;156 btree += pag->pagf_btreeblks;157 xfs_perag_put(pag);158 }159 fdblocks = bfree + bfreelst + btree;160 161 /*162 * If the new summary counts are obviously incorrect, fail the163 * mount operation because that implies the AGFs are also corrupt.164 * Clear FS_COUNTERS so that we don't unmount with a dirty log, which165 * will prevent xfs_repair from fixing anything.166 */167 if (fdblocks > sbp->sb_dblocks || ifree > ialloc) {168 xfs_alert(mp, "AGF corruption. Please run xfs_repair.");169 xfs_fs_mark_sick(mp, XFS_SICK_FS_COUNTERS);170 error = -EFSCORRUPTED;171 goto out;172 }173 174 /* Overwrite incore superblock counters with just-read data */175 spin_lock(&mp->m_sb_lock);176 sbp->sb_ifree = ifree;177 sbp->sb_icount = ialloc;178 sbp->sb_fdblocks = fdblocks;179 spin_unlock(&mp->m_sb_lock);180 181 xfs_reinit_percpu_counters(mp);182out:183 xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS);184 return error;185}186 187/*188 * Free up the per-ag resources within the specified AG range.189 */190void191xfs_free_perag_range(192 struct xfs_mount *mp,193 xfs_agnumber_t first_agno,194 xfs_agnumber_t end_agno)195 196{197 xfs_agnumber_t agno;198 199 for (agno = first_agno; agno < end_agno; agno++) {200 struct xfs_perag *pag = xa_erase(&mp->m_perags, agno);201 202 ASSERT(pag);203 XFS_IS_CORRUPT(pag->pag_mount, atomic_read(&pag->pag_ref) != 0);204 xfs_defer_drain_free(&pag->pag_intents_drain);205 206 cancel_delayed_work_sync(&pag->pag_blockgc_work);207 xfs_buf_cache_destroy(&pag->pag_bcache);208 209 /* drop the mount's active reference */210 xfs_perag_rele(pag);211 XFS_IS_CORRUPT(pag->pag_mount,212 atomic_read(&pag->pag_active_ref) != 0);213 kfree_rcu_mightsleep(pag);214 }215}216 217/* Find the size of the AG, in blocks. */218static xfs_agblock_t219__xfs_ag_block_count(220 struct xfs_mount *mp,221 xfs_agnumber_t agno,222 xfs_agnumber_t agcount,223 xfs_rfsblock_t dblocks)224{225 ASSERT(agno < agcount);226 227 if (agno < agcount - 1)228 return mp->m_sb.sb_agblocks;229 return dblocks - (agno * mp->m_sb.sb_agblocks);230}231 232xfs_agblock_t233xfs_ag_block_count(234 struct xfs_mount *mp,235 xfs_agnumber_t agno)236{237 return __xfs_ag_block_count(mp, agno, mp->m_sb.sb_agcount,238 mp->m_sb.sb_dblocks);239}240 241/* Calculate the first and last possible inode number in an AG. */242static void243__xfs_agino_range(244 struct xfs_mount *mp,245 xfs_agblock_t eoag,246 xfs_agino_t *first,247 xfs_agino_t *last)248{249 xfs_agblock_t bno;250 251 /*252 * Calculate the first inode, which will be in the first253 * cluster-aligned block after the AGFL.254 */255 bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align);256 *first = XFS_AGB_TO_AGINO(mp, bno);257 258 /*259 * Calculate the last inode, which will be at the end of the260 * last (aligned) cluster that can be allocated in the AG.261 */262 bno = round_down(eoag, M_IGEO(mp)->cluster_align);263 *last = XFS_AGB_TO_AGINO(mp, bno) - 1;264}265 266void267xfs_agino_range(268 struct xfs_mount *mp,269 xfs_agnumber_t agno,270 xfs_agino_t *first,271 xfs_agino_t *last)272{273 return __xfs_agino_range(mp, xfs_ag_block_count(mp, agno), first, last);274}275 276int277xfs_update_last_ag_size(278 struct xfs_mount *mp,279 xfs_agnumber_t prev_agcount)280{281 struct xfs_perag *pag = xfs_perag_grab(mp, prev_agcount - 1);282 283 if (!pag)284 return -EFSCORRUPTED;285 pag->block_count = __xfs_ag_block_count(mp, prev_agcount - 1,286 mp->m_sb.sb_agcount, mp->m_sb.sb_dblocks);287 __xfs_agino_range(mp, pag->block_count, &pag->agino_min,288 &pag->agino_max);289 xfs_perag_rele(pag);290 return 0;291}292 293int294xfs_initialize_perag(295 struct xfs_mount *mp,296 xfs_agnumber_t old_agcount,297 xfs_agnumber_t new_agcount,298 xfs_rfsblock_t dblocks,299 xfs_agnumber_t *maxagi)300{301 struct xfs_perag *pag;302 xfs_agnumber_t index;303 int error;304 305 for (index = old_agcount; index < new_agcount; index++) {306 pag = kzalloc(sizeof(*pag), GFP_KERNEL);307 if (!pag) {308 error = -ENOMEM;309 goto out_unwind_new_pags;310 }311 pag->pag_agno = index;312 pag->pag_mount = mp;313 314 error = xa_insert(&mp->m_perags, index, pag, GFP_KERNEL);315 if (error) {316 WARN_ON_ONCE(error == -EBUSY);317 goto out_free_pag;318 }319 320#ifdef __KERNEL__321 /* Place kernel structure only init below this point. */322 spin_lock_init(&pag->pag_ici_lock);323 spin_lock_init(&pag->pagb_lock);324 spin_lock_init(&pag->pag_state_lock);325 INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker);326 INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);327 xfs_defer_drain_init(&pag->pag_intents_drain);328 init_waitqueue_head(&pag->pagb_wait);329 init_waitqueue_head(&pag->pag_active_wq);330 pag->pagb_count = 0;331 pag->pagb_tree = RB_ROOT;332 xfs_hooks_init(&pag->pag_rmap_update_hooks);333#endif /* __KERNEL__ */334 335 error = xfs_buf_cache_init(&pag->pag_bcache);336 if (error)337 goto out_remove_pag;338 339 /* Active ref owned by mount indicates AG is online. */340 atomic_set(&pag->pag_active_ref, 1);341 342 /*343 * Pre-calculated geometry344 */345 pag->block_count = __xfs_ag_block_count(mp, index, new_agcount,346 dblocks);347 pag->min_block = XFS_AGFL_BLOCK(mp);348 __xfs_agino_range(mp, pag->block_count, &pag->agino_min,349 &pag->agino_max);350 }351 352 index = xfs_set_inode_alloc(mp, new_agcount);353 354 if (maxagi)355 *maxagi = index;356 357 mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp);358 return 0;359 360out_remove_pag:361 xfs_defer_drain_free(&pag->pag_intents_drain);362 pag = xa_erase(&mp->m_perags, index);363out_free_pag:364 kfree(pag);365out_unwind_new_pags:366 xfs_free_perag_range(mp, old_agcount, index);367 return error;368}369 370static int371xfs_get_aghdr_buf(372 struct xfs_mount *mp,373 xfs_daddr_t blkno,374 size_t numblks,375 struct xfs_buf **bpp,376 const struct xfs_buf_ops *ops)377{378 struct xfs_buf *bp;379 int error;380 381 error = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, 0, &bp);382 if (error)383 return error;384 385 bp->b_maps[0].bm_bn = blkno;386 bp->b_ops = ops;387 388 *bpp = bp;389 return 0;390}391 392/*393 * Generic btree root block init function394 */395static void396xfs_btroot_init(397 struct xfs_mount *mp,398 struct xfs_buf *bp,399 struct aghdr_init_data *id)400{401 xfs_btree_init_buf(mp, bp, id->bc_ops, 0, 0, id->agno);402}403 404/* Finish initializing a free space btree. */405static void406xfs_freesp_init_recs(407 struct xfs_mount *mp,408 struct xfs_buf *bp,409 struct aghdr_init_data *id)410{411 struct xfs_alloc_rec *arec;412 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);413 414 arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1);415 arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks);416 417 if (xfs_ag_contains_log(mp, id->agno)) {418 struct xfs_alloc_rec *nrec;419 xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp,420 mp->m_sb.sb_logstart);421 422 ASSERT(start >= mp->m_ag_prealloc_blocks);423 if (start != mp->m_ag_prealloc_blocks) {424 /*425 * Modify first record to pad stripe align of log and426 * bump the record count.427 */428 arec->ar_blockcount = cpu_to_be32(start -429 mp->m_ag_prealloc_blocks);430 be16_add_cpu(&block->bb_numrecs, 1);431 nrec = arec + 1;432 433 /*434 * Insert second record at start of internal log435 * which then gets trimmed.436 */437 nrec->ar_startblock = cpu_to_be32(438 be32_to_cpu(arec->ar_startblock) +439 be32_to_cpu(arec->ar_blockcount));440 arec = nrec;441 }442 /*443 * Change record start to after the internal log444 */445 be32_add_cpu(&arec->ar_startblock, mp->m_sb.sb_logblocks);446 }447 448 /*449 * Calculate the block count of this record; if it is nonzero,450 * increment the record count.451 */452 arec->ar_blockcount = cpu_to_be32(id->agsize -453 be32_to_cpu(arec->ar_startblock));454 if (arec->ar_blockcount)455 be16_add_cpu(&block->bb_numrecs, 1);456}457 458/*459 * bnobt/cntbt btree root block init functions460 */461static void462xfs_bnoroot_init(463 struct xfs_mount *mp,464 struct xfs_buf *bp,465 struct aghdr_init_data *id)466{467 xfs_btree_init_buf(mp, bp, id->bc_ops, 0, 0, id->agno);468 xfs_freesp_init_recs(mp, bp, id);469}470 471/*472 * Reverse map root block init473 */474static void475xfs_rmaproot_init(476 struct xfs_mount *mp,477 struct xfs_buf *bp,478 struct aghdr_init_data *id)479{480 struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp);481 struct xfs_rmap_rec *rrec;482 483 xfs_btree_init_buf(mp, bp, id->bc_ops, 0, 4, id->agno);484 485 /*486 * mark the AG header regions as static metadata The BNO487 * btree block is the first block after the headers, so488 * it's location defines the size of region the static489 * metadata consumes.490 *491 * Note: unlike mkfs, we never have to account for log492 * space when growing the data regions493 */494 rrec = XFS_RMAP_REC_ADDR(block, 1);495 rrec->rm_startblock = 0;496 rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp));497 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS);498 rrec->rm_offset = 0;499 500 /* account freespace btree root blocks */501 rrec = XFS_RMAP_REC_ADDR(block, 2);502 rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp));503 rrec->rm_blockcount = cpu_to_be32(2);504 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);505 rrec->rm_offset = 0;506 507 /* account inode btree root blocks */508 rrec = XFS_RMAP_REC_ADDR(block, 3);509 rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp));510 rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) -511 XFS_IBT_BLOCK(mp));512 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT);513 rrec->rm_offset = 0;514 515 /* account for rmap btree root */516 rrec = XFS_RMAP_REC_ADDR(block, 4);517 rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp));518 rrec->rm_blockcount = cpu_to_be32(1);519 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG);520 rrec->rm_offset = 0;521 522 /* account for refc btree root */523 if (xfs_has_reflink(mp)) {524 rrec = XFS_RMAP_REC_ADDR(block, 5);525 rrec->rm_startblock = cpu_to_be32(xfs_refc_block(mp));526 rrec->rm_blockcount = cpu_to_be32(1);527 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC);528 rrec->rm_offset = 0;529 be16_add_cpu(&block->bb_numrecs, 1);530 }531 532 /* account for the log space */533 if (xfs_ag_contains_log(mp, id->agno)) {534 rrec = XFS_RMAP_REC_ADDR(block,535 be16_to_cpu(block->bb_numrecs) + 1);536 rrec->rm_startblock = cpu_to_be32(537 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart));538 rrec->rm_blockcount = cpu_to_be32(mp->m_sb.sb_logblocks);539 rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_LOG);540 rrec->rm_offset = 0;541 be16_add_cpu(&block->bb_numrecs, 1);542 }543}544 545/*546 * Initialise new secondary superblocks with the pre-grow geometry, but mark547 * them as "in progress" so we know they haven't yet been activated. This will548 * get cleared when the update with the new geometry information is done after549 * changes to the primary are committed. This isn't strictly necessary, but we550 * get it for free with the delayed buffer write lists and it means we can tell551 * if a grow operation didn't complete properly after the fact.552 */553static void554xfs_sbblock_init(555 struct xfs_mount *mp,556 struct xfs_buf *bp,557 struct aghdr_init_data *id)558{559 struct xfs_dsb *dsb = bp->b_addr;560 561 xfs_sb_to_disk(dsb, &mp->m_sb);562 dsb->sb_inprogress = 1;563}564 565static void566xfs_agfblock_init(567 struct xfs_mount *mp,568 struct xfs_buf *bp,569 struct aghdr_init_data *id)570{571 struct xfs_agf *agf = bp->b_addr;572 xfs_extlen_t tmpsize;573 574 agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC);575 agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION);576 agf->agf_seqno = cpu_to_be32(id->agno);577 agf->agf_length = cpu_to_be32(id->agsize);578 agf->agf_bno_root = cpu_to_be32(XFS_BNO_BLOCK(mp));579 agf->agf_cnt_root = cpu_to_be32(XFS_CNT_BLOCK(mp));580 agf->agf_bno_level = cpu_to_be32(1);581 agf->agf_cnt_level = cpu_to_be32(1);582 if (xfs_has_rmapbt(mp)) {583 agf->agf_rmap_root = cpu_to_be32(XFS_RMAP_BLOCK(mp));584 agf->agf_rmap_level = cpu_to_be32(1);585 agf->agf_rmap_blocks = cpu_to_be32(1);586 }587 588 agf->agf_flfirst = cpu_to_be32(1);589 agf->agf_fllast = 0;590 agf->agf_flcount = 0;591 tmpsize = id->agsize - mp->m_ag_prealloc_blocks;592 agf->agf_freeblks = cpu_to_be32(tmpsize);593 agf->agf_longest = cpu_to_be32(tmpsize);594 if (xfs_has_crc(mp))595 uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid);596 if (xfs_has_reflink(mp)) {597 agf->agf_refcount_root = cpu_to_be32(598 xfs_refc_block(mp));599 agf->agf_refcount_level = cpu_to_be32(1);600 agf->agf_refcount_blocks = cpu_to_be32(1);601 }602 603 if (xfs_ag_contains_log(mp, id->agno)) {604 int64_t logblocks = mp->m_sb.sb_logblocks;605 606 be32_add_cpu(&agf->agf_freeblks, -logblocks);607 agf->agf_longest = cpu_to_be32(id->agsize -608 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart) - logblocks);609 }610}611 612static void613xfs_agflblock_init(614 struct xfs_mount *mp,615 struct xfs_buf *bp,616 struct aghdr_init_data *id)617{618 struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp);619 __be32 *agfl_bno;620 int bucket;621 622 if (xfs_has_crc(mp)) {623 agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC);624 agfl->agfl_seqno = cpu_to_be32(id->agno);625 uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid);626 }627 628 agfl_bno = xfs_buf_to_agfl_bno(bp);629 for (bucket = 0; bucket < xfs_agfl_size(mp); bucket++)630 agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK);631}632 633static void634xfs_agiblock_init(635 struct xfs_mount *mp,636 struct xfs_buf *bp,637 struct aghdr_init_data *id)638{639 struct xfs_agi *agi = bp->b_addr;640 int bucket;641 642 agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC);643 agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION);644 agi->agi_seqno = cpu_to_be32(id->agno);645 agi->agi_length = cpu_to_be32(id->agsize);646 agi->agi_count = 0;647 agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp));648 agi->agi_level = cpu_to_be32(1);649 agi->agi_freecount = 0;650 agi->agi_newino = cpu_to_be32(NULLAGINO);651 agi->agi_dirino = cpu_to_be32(NULLAGINO);652 if (xfs_has_crc(mp))653 uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid);654 if (xfs_has_finobt(mp)) {655 agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp));656 agi->agi_free_level = cpu_to_be32(1);657 }658 for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)659 agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);660 if (xfs_has_inobtcounts(mp)) {661 agi->agi_iblocks = cpu_to_be32(1);662 if (xfs_has_finobt(mp))663 agi->agi_fblocks = cpu_to_be32(1);664 }665}666 667typedef void (*aghdr_init_work_f)(struct xfs_mount *mp, struct xfs_buf *bp,668 struct aghdr_init_data *id);669static int670xfs_ag_init_hdr(671 struct xfs_mount *mp,672 struct aghdr_init_data *id,673 aghdr_init_work_f work,674 const struct xfs_buf_ops *ops)675{676 struct xfs_buf *bp;677 int error;678 679 error = xfs_get_aghdr_buf(mp, id->daddr, id->numblks, &bp, ops);680 if (error)681 return error;682 683 (*work)(mp, bp, id);684 685 xfs_buf_delwri_queue(bp, &id->buffer_list);686 xfs_buf_relse(bp);687 return 0;688}689 690struct xfs_aghdr_grow_data {691 xfs_daddr_t daddr;692 size_t numblks;693 const struct xfs_buf_ops *ops;694 aghdr_init_work_f work;695 const struct xfs_btree_ops *bc_ops;696 bool need_init;697};698 699/*700 * Prepare new AG headers to be written to disk. We use uncached buffers here,701 * as it is assumed these new AG headers are currently beyond the currently702 * valid filesystem address space. Using cached buffers would trip over EOFS703 * corruption detection alogrithms in the buffer cache lookup routines.704 *705 * This is a non-transactional function, but the prepared buffers are added to a706 * delayed write buffer list supplied by the caller so they can submit them to707 * disk and wait on them as required.708 */709int710xfs_ag_init_headers(711 struct xfs_mount *mp,712 struct aghdr_init_data *id)713 714{715 struct xfs_aghdr_grow_data aghdr_data[] = {716 { /* SB */717 .daddr = XFS_AG_DADDR(mp, id->agno, XFS_SB_DADDR),718 .numblks = XFS_FSS_TO_BB(mp, 1),719 .ops = &xfs_sb_buf_ops,720 .work = &xfs_sbblock_init,721 .need_init = true722 },723 { /* AGF */724 .daddr = XFS_AG_DADDR(mp, id->agno, XFS_AGF_DADDR(mp)),725 .numblks = XFS_FSS_TO_BB(mp, 1),726 .ops = &xfs_agf_buf_ops,727 .work = &xfs_agfblock_init,728 .need_init = true729 },730 { /* AGFL */731 .daddr = XFS_AG_DADDR(mp, id->agno, XFS_AGFL_DADDR(mp)),732 .numblks = XFS_FSS_TO_BB(mp, 1),733 .ops = &xfs_agfl_buf_ops,734 .work = &xfs_agflblock_init,735 .need_init = true736 },737 { /* AGI */738 .daddr = XFS_AG_DADDR(mp, id->agno, XFS_AGI_DADDR(mp)),739 .numblks = XFS_FSS_TO_BB(mp, 1),740 .ops = &xfs_agi_buf_ops,741 .work = &xfs_agiblock_init,742 .need_init = true743 },744 { /* BNO root block */745 .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_BNO_BLOCK(mp)),746 .numblks = BTOBB(mp->m_sb.sb_blocksize),747 .ops = &xfs_bnobt_buf_ops,748 .work = &xfs_bnoroot_init,749 .bc_ops = &xfs_bnobt_ops,750 .need_init = true751 },752 { /* CNT root block */753 .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_CNT_BLOCK(mp)),754 .numblks = BTOBB(mp->m_sb.sb_blocksize),755 .ops = &xfs_cntbt_buf_ops,756 .work = &xfs_bnoroot_init,757 .bc_ops = &xfs_cntbt_ops,758 .need_init = true759 },760 { /* INO root block */761 .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_IBT_BLOCK(mp)),762 .numblks = BTOBB(mp->m_sb.sb_blocksize),763 .ops = &xfs_inobt_buf_ops,764 .work = &xfs_btroot_init,765 .bc_ops = &xfs_inobt_ops,766 .need_init = true767 },768 { /* FINO root block */769 .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_FIBT_BLOCK(mp)),770 .numblks = BTOBB(mp->m_sb.sb_blocksize),771 .ops = &xfs_finobt_buf_ops,772 .work = &xfs_btroot_init,773 .bc_ops = &xfs_finobt_ops,774 .need_init = xfs_has_finobt(mp)775 },776 { /* RMAP root block */777 .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_RMAP_BLOCK(mp)),778 .numblks = BTOBB(mp->m_sb.sb_blocksize),779 .ops = &xfs_rmapbt_buf_ops,780 .work = &xfs_rmaproot_init,781 .bc_ops = &xfs_rmapbt_ops,782 .need_init = xfs_has_rmapbt(mp)783 },784 { /* REFC root block */785 .daddr = XFS_AGB_TO_DADDR(mp, id->agno, xfs_refc_block(mp)),786 .numblks = BTOBB(mp->m_sb.sb_blocksize),787 .ops = &xfs_refcountbt_buf_ops,788 .work = &xfs_btroot_init,789 .bc_ops = &xfs_refcountbt_ops,790 .need_init = xfs_has_reflink(mp)791 },792 { /* NULL terminating block */793 .daddr = XFS_BUF_DADDR_NULL,794 }795 };796 struct xfs_aghdr_grow_data *dp;797 int error = 0;798 799 /* Account for AG free space in new AG */800 id->nfree += id->agsize - mp->m_ag_prealloc_blocks;801 for (dp = &aghdr_data[0]; dp->daddr != XFS_BUF_DADDR_NULL; dp++) {802 if (!dp->need_init)803 continue;804 805 id->daddr = dp->daddr;806 id->numblks = dp->numblks;807 id->bc_ops = dp->bc_ops;808 error = xfs_ag_init_hdr(mp, id, dp->work, dp->ops);809 if (error)810 break;811 }812 return error;813}814 815int816xfs_ag_shrink_space(817 struct xfs_perag *pag,818 struct xfs_trans **tpp,819 xfs_extlen_t delta)820{821 struct xfs_mount *mp = pag->pag_mount;822 struct xfs_alloc_arg args = {823 .tp = *tpp,824 .mp = mp,825 .pag = pag,826 .minlen = delta,827 .maxlen = delta,828 .oinfo = XFS_RMAP_OINFO_SKIP_UPDATE,829 .resv = XFS_AG_RESV_NONE,830 .prod = 1831 };832 struct xfs_buf *agibp, *agfbp;833 struct xfs_agi *agi;834 struct xfs_agf *agf;835 xfs_agblock_t aglen;836 int error, err2;837 838 ASSERT(pag->pag_agno == mp->m_sb.sb_agcount - 1);839 error = xfs_ialloc_read_agi(pag, *tpp, 0, &agibp);840 if (error)841 return error;842 843 agi = agibp->b_addr;844 845 error = xfs_alloc_read_agf(pag, *tpp, 0, &agfbp);846 if (error)847 return error;848 849 agf = agfbp->b_addr;850 aglen = be32_to_cpu(agi->agi_length);851 /* some extra paranoid checks before we shrink the ag */852 if (XFS_IS_CORRUPT(mp, agf->agf_length != agi->agi_length)) {853 xfs_ag_mark_sick(pag, XFS_SICK_AG_AGF);854 return -EFSCORRUPTED;855 }856 if (delta >= aglen)857 return -EINVAL;858 859 /*860 * Make sure that the last inode cluster cannot overlap with the new861 * end of the AG, even if it's sparse.862 */863 error = xfs_ialloc_check_shrink(pag, *tpp, agibp, aglen - delta);864 if (error)865 return error;866 867 /*868 * Disable perag reservations so it doesn't cause the allocation request869 * to fail. We'll reestablish reservation before we return.870 */871 xfs_ag_resv_free(pag);872 873 /* internal log shouldn't also show up in the free space btrees */874 error = xfs_alloc_vextent_exact_bno(&args,875 XFS_AGB_TO_FSB(mp, pag->pag_agno, aglen - delta));876 if (!error && args.agbno == NULLAGBLOCK)877 error = -ENOSPC;878 879 if (error) {880 /*881 * If extent allocation fails, need to roll the transaction to882 * ensure that the AGFL fixup has been committed anyway.883 *884 * We need to hold the AGF across the roll to ensure nothing can885 * access the AG for allocation until the shrink is fully886 * cleaned up. And due to the resetting of the AG block887 * reservation space needing to lock the AGI, we also have to888 * hold that so we don't get AGI/AGF lock order inversions in889 * the error handling path.890 */891 xfs_trans_bhold(*tpp, agfbp);892 xfs_trans_bhold(*tpp, agibp);893 err2 = xfs_trans_roll(tpp);894 if (err2)895 return err2;896 xfs_trans_bjoin(*tpp, agfbp);897 xfs_trans_bjoin(*tpp, agibp);898 goto resv_init_out;899 }900 901 /*902 * if successfully deleted from freespace btrees, need to confirm903 * per-AG reservation works as expected.904 */905 be32_add_cpu(&agi->agi_length, -delta);906 be32_add_cpu(&agf->agf_length, -delta);907 908 err2 = xfs_ag_resv_init(pag, *tpp);909 if (err2) {910 be32_add_cpu(&agi->agi_length, delta);911 be32_add_cpu(&agf->agf_length, delta);912 if (err2 != -ENOSPC)913 goto resv_err;914 915 err2 = xfs_free_extent_later(*tpp, args.fsbno, delta, NULL,916 XFS_AG_RESV_NONE, XFS_FREE_EXTENT_SKIP_DISCARD);917 if (err2)918 goto resv_err;919 920 /*921 * Roll the transaction before trying to re-init the per-ag922 * reservation. The new transaction is clean so it will cancel923 * without any side effects.924 */925 error = xfs_defer_finish(tpp);926 if (error)927 return error;928 929 error = -ENOSPC;930 goto resv_init_out;931 }932 933 /* Update perag geometry */934 pag->block_count -= delta;935 __xfs_agino_range(pag->pag_mount, pag->block_count, &pag->agino_min,936 &pag->agino_max);937 938 xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH);939 xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH);940 return 0;941 942resv_init_out:943 err2 = xfs_ag_resv_init(pag, *tpp);944 if (!err2)945 return error;946resv_err:947 xfs_warn(mp, "Error %d reserving per-AG metadata reserve pool.", err2);948 xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);949 return err2;950}951 952/*953 * Extent the AG indicated by the @id by the length passed in954 */955int956xfs_ag_extend_space(957 struct xfs_perag *pag,958 struct xfs_trans *tp,959 xfs_extlen_t len)960{961 struct xfs_buf *bp;962 struct xfs_agi *agi;963 struct xfs_agf *agf;964 int error;965 966 ASSERT(pag->pag_agno == pag->pag_mount->m_sb.sb_agcount - 1);967 968 error = xfs_ialloc_read_agi(pag, tp, 0, &bp);969 if (error)970 return error;971 972 agi = bp->b_addr;973 be32_add_cpu(&agi->agi_length, len);974 xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH);975 976 /*977 * Change agf length.978 */979 error = xfs_alloc_read_agf(pag, tp, 0, &bp);980 if (error)981 return error;982 983 agf = bp->b_addr;984 be32_add_cpu(&agf->agf_length, len);985 ASSERT(agf->agf_length == agi->agi_length);986 xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH);987 988 /*989 * Free the new space.990 *991 * XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that992 * this doesn't actually exist in the rmap btree.993 */994 error = xfs_rmap_free(tp, bp, pag, be32_to_cpu(agf->agf_length) - len,995 len, &XFS_RMAP_OINFO_SKIP_UPDATE);996 if (error)997 return error;998 999 error = xfs_free_extent(tp, pag, be32_to_cpu(agf->agf_length) - len,1000 len, &XFS_RMAP_OINFO_SKIP_UPDATE, XFS_AG_RESV_NONE);1001 if (error)1002 return error;1003 1004 /* Update perag geometry */1005 pag->block_count = be32_to_cpu(agf->agf_length);1006 __xfs_agino_range(pag->pag_mount, pag->block_count, &pag->agino_min,1007 &pag->agino_max);1008 return 0;1009}1010 1011/* Retrieve AG geometry. */1012int1013xfs_ag_get_geometry(1014 struct xfs_perag *pag,1015 struct xfs_ag_geometry *ageo)1016{1017 struct xfs_buf *agi_bp;1018 struct xfs_buf *agf_bp;1019 struct xfs_agi *agi;1020 struct xfs_agf *agf;1021 unsigned int freeblks;1022 int error;1023 1024 /* Lock the AG headers. */1025 error = xfs_ialloc_read_agi(pag, NULL, 0, &agi_bp);1026 if (error)1027 return error;1028 error = xfs_alloc_read_agf(pag, NULL, 0, &agf_bp);1029 if (error)1030 goto out_agi;1031 1032 /* Fill out form. */1033 memset(ageo, 0, sizeof(*ageo));1034 ageo->ag_number = pag->pag_agno;1035 1036 agi = agi_bp->b_addr;1037 ageo->ag_icount = be32_to_cpu(agi->agi_count);1038 ageo->ag_ifree = be32_to_cpu(agi->agi_freecount);1039 1040 agf = agf_bp->b_addr;1041 ageo->ag_length = be32_to_cpu(agf->agf_length);1042 freeblks = pag->pagf_freeblks +1043 pag->pagf_flcount +1044 pag->pagf_btreeblks -1045 xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE);1046 ageo->ag_freeblks = freeblks;1047 xfs_ag_geom_health(pag, ageo);1048 1049 /* Release resources. */1050 xfs_buf_relse(agf_bp);1051out_agi:1052 xfs_buf_relse(agi_bp);1053 return error;1054}1055