1b16817b6SDave Chinner /* SPDX-License-Identifier: GPL-2.0 */ 2b16817b6SDave Chinner /* 3b16817b6SDave Chinner * Copyright (c) 2000-2005 Silicon Graphics, Inc. 4b16817b6SDave Chinner * Copyright (c) 2018 Red Hat, Inc. 5b16817b6SDave Chinner * All rights reserved. 6b16817b6SDave Chinner */ 7b16817b6SDave Chinner 8b16817b6SDave Chinner #include "xfs.h" 9b16817b6SDave Chinner #include "xfs_fs.h" 10b16817b6SDave Chinner #include "xfs_shared.h" 11b16817b6SDave Chinner #include "xfs_format.h" 12b16817b6SDave Chinner #include "xfs_trans_resv.h" 13f327a007SDarrick J. Wong #include "xfs_bit.h" 14b16817b6SDave Chinner #include "xfs_sb.h" 15b16817b6SDave Chinner #include "xfs_mount.h" 16b16817b6SDave Chinner #include "xfs_btree.h" 17b16817b6SDave Chinner #include "xfs_alloc_btree.h" 18b16817b6SDave Chinner #include "xfs_rmap_btree.h" 19b16817b6SDave Chinner #include "xfs_alloc.h" 2049dd56f2SDave Chinner #include "xfs_ialloc.h" 21b16817b6SDave Chinner #include "xfs_rmap.h" 22b16817b6SDave Chinner #include "xfs_ag.h" 237cd5006bSDarrick J. Wong #include "xfs_ag_resv.h" 241302c6a2SDarrick J. Wong #include "xfs_health.h" 2546141dc8SGao Xiang #include "xfs_error.h" 2646141dc8SGao Xiang #include "xfs_bmap.h" 2746141dc8SGao Xiang #include "xfs_defer.h" 2846141dc8SGao Xiang #include "xfs_log_format.h" 2946141dc8SGao Xiang #include "xfs_trans.h" 309bbafc71SDave Chinner #include "xfs_trace.h" 3107b6403aSDave Chinner #include "xfs_inode.h" 3207b6403aSDave Chinner #include "xfs_icache.h" 3307b6403aSDave Chinner 349bbafc71SDave Chinner 359bbafc71SDave Chinner /* 369bbafc71SDave Chinner * Passive reference counting access wrappers to the perag structures. If the 379bbafc71SDave Chinner * per-ag structure is to be freed, the freeing code is responsible for cleaning 389bbafc71SDave Chinner * up objects with passive references before freeing the structure. This is 399bbafc71SDave Chinner * things like cached buffers. 409bbafc71SDave Chinner */ 419bbafc71SDave Chinner struct xfs_perag * 429bbafc71SDave Chinner xfs_perag_get( 439bbafc71SDave Chinner struct xfs_mount *mp, 449bbafc71SDave Chinner xfs_agnumber_t agno) 459bbafc71SDave Chinner { 469bbafc71SDave Chinner struct xfs_perag *pag; 479bbafc71SDave Chinner int ref = 0; 489bbafc71SDave Chinner 499bbafc71SDave Chinner rcu_read_lock(); 509bbafc71SDave Chinner pag = radix_tree_lookup(&mp->m_perag_tree, agno); 519bbafc71SDave Chinner if (pag) { 529bbafc71SDave Chinner ASSERT(atomic_read(&pag->pag_ref) >= 0); 539bbafc71SDave Chinner ref = atomic_inc_return(&pag->pag_ref); 549bbafc71SDave Chinner } 559bbafc71SDave Chinner rcu_read_unlock(); 569bbafc71SDave Chinner trace_xfs_perag_get(mp, agno, ref, _RET_IP_); 579bbafc71SDave Chinner return pag; 589bbafc71SDave Chinner } 599bbafc71SDave Chinner 609bbafc71SDave Chinner /* 619bbafc71SDave Chinner * search from @first to find the next perag with the given tag set. 629bbafc71SDave Chinner */ 639bbafc71SDave Chinner struct xfs_perag * 649bbafc71SDave Chinner xfs_perag_get_tag( 659bbafc71SDave Chinner struct xfs_mount *mp, 669bbafc71SDave Chinner xfs_agnumber_t first, 67ffc18582SDarrick J. Wong unsigned int tag) 689bbafc71SDave Chinner { 699bbafc71SDave Chinner struct xfs_perag *pag; 709bbafc71SDave Chinner int found; 719bbafc71SDave Chinner int ref; 729bbafc71SDave Chinner 739bbafc71SDave Chinner rcu_read_lock(); 749bbafc71SDave Chinner found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, 759bbafc71SDave Chinner (void **)&pag, first, 1, tag); 769bbafc71SDave Chinner if (found <= 0) { 779bbafc71SDave Chinner rcu_read_unlock(); 789bbafc71SDave Chinner return NULL; 799bbafc71SDave Chinner } 809bbafc71SDave Chinner ref = atomic_inc_return(&pag->pag_ref); 819bbafc71SDave Chinner rcu_read_unlock(); 829bbafc71SDave Chinner trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_); 839bbafc71SDave Chinner return pag; 849bbafc71SDave Chinner } 859bbafc71SDave Chinner 869bbafc71SDave Chinner void 879bbafc71SDave Chinner xfs_perag_put( 889bbafc71SDave Chinner struct xfs_perag *pag) 899bbafc71SDave Chinner { 909bbafc71SDave Chinner int ref; 919bbafc71SDave Chinner 929bbafc71SDave Chinner ASSERT(atomic_read(&pag->pag_ref) > 0); 939bbafc71SDave Chinner ref = atomic_dec_return(&pag->pag_ref); 949bbafc71SDave Chinner trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); 959bbafc71SDave Chinner } 969bbafc71SDave Chinner 979bbafc71SDave Chinner /* 989bbafc71SDave Chinner * xfs_initialize_perag_data 999bbafc71SDave Chinner * 1009bbafc71SDave Chinner * Read in each per-ag structure so we can count up the number of 1019bbafc71SDave Chinner * allocated inodes, free inodes and used filesystem blocks as this 1029bbafc71SDave Chinner * information is no longer persistent in the superblock. Once we have 1039bbafc71SDave Chinner * this information, write it into the in-core superblock structure. 1049bbafc71SDave Chinner */ 1059bbafc71SDave Chinner int 1069bbafc71SDave Chinner xfs_initialize_perag_data( 1079bbafc71SDave Chinner struct xfs_mount *mp, 1089bbafc71SDave Chinner xfs_agnumber_t agcount) 1099bbafc71SDave Chinner { 1109bbafc71SDave Chinner xfs_agnumber_t index; 11150920116SDave Chinner struct xfs_perag *pag; 11250920116SDave Chinner struct xfs_sb *sbp = &mp->m_sb; 1139bbafc71SDave Chinner uint64_t ifree = 0; 1149bbafc71SDave Chinner uint64_t ialloc = 0; 1159bbafc71SDave Chinner uint64_t bfree = 0; 1169bbafc71SDave Chinner uint64_t bfreelst = 0; 1179bbafc71SDave Chinner uint64_t btree = 0; 1189bbafc71SDave Chinner uint64_t fdblocks; 1199bbafc71SDave Chinner int error = 0; 1209bbafc71SDave Chinner 1219bbafc71SDave Chinner for (index = 0; index < agcount; index++) { 1229bbafc71SDave Chinner /* 12308d3e84fSDave Chinner * Read the AGF and AGI buffers to populate the per-ag 12408d3e84fSDave Chinner * structures for us. 1259bbafc71SDave Chinner */ 1269bbafc71SDave Chinner pag = xfs_perag_get(mp, index); 12708d3e84fSDave Chinner error = xfs_alloc_read_agf(pag, NULL, 0, NULL); 12808d3e84fSDave Chinner if (!error) 12999b13c7fSDave Chinner error = xfs_ialloc_read_agi(pag, NULL, NULL); 13099b13c7fSDave Chinner if (error) { 13199b13c7fSDave Chinner xfs_perag_put(pag); 13299b13c7fSDave Chinner return error; 13399b13c7fSDave Chinner } 13499b13c7fSDave Chinner 1359bbafc71SDave Chinner ifree += pag->pagi_freecount; 1369bbafc71SDave Chinner ialloc += pag->pagi_count; 1379bbafc71SDave Chinner bfree += pag->pagf_freeblks; 1389bbafc71SDave Chinner bfreelst += pag->pagf_flcount; 1399bbafc71SDave Chinner btree += pag->pagf_btreeblks; 1409bbafc71SDave Chinner xfs_perag_put(pag); 1419bbafc71SDave Chinner } 1429bbafc71SDave Chinner fdblocks = bfree + bfreelst + btree; 1439bbafc71SDave Chinner 1449bbafc71SDave Chinner /* 1459bbafc71SDave Chinner * If the new summary counts are obviously incorrect, fail the 1469bbafc71SDave Chinner * mount operation because that implies the AGFs are also corrupt. 1479bbafc71SDave Chinner * Clear FS_COUNTERS so that we don't unmount with a dirty log, which 1489bbafc71SDave Chinner * will prevent xfs_repair from fixing anything. 1499bbafc71SDave Chinner */ 1509bbafc71SDave Chinner if (fdblocks > sbp->sb_dblocks || ifree > ialloc) { 1519bbafc71SDave Chinner xfs_alert(mp, "AGF corruption. Please run xfs_repair."); 1529bbafc71SDave Chinner error = -EFSCORRUPTED; 1539bbafc71SDave Chinner goto out; 1549bbafc71SDave Chinner } 1559bbafc71SDave Chinner 1569bbafc71SDave Chinner /* Overwrite incore superblock counters with just-read data */ 1579bbafc71SDave Chinner spin_lock(&mp->m_sb_lock); 1589bbafc71SDave Chinner sbp->sb_ifree = ifree; 1599bbafc71SDave Chinner sbp->sb_icount = ialloc; 1609bbafc71SDave Chinner sbp->sb_fdblocks = fdblocks; 1619bbafc71SDave Chinner spin_unlock(&mp->m_sb_lock); 1629bbafc71SDave Chinner 1639bbafc71SDave Chinner xfs_reinit_percpu_counters(mp); 1649bbafc71SDave Chinner out: 1659bbafc71SDave Chinner xfs_fs_mark_healthy(mp, XFS_SICK_FS_COUNTERS); 1669bbafc71SDave Chinner return error; 1679bbafc71SDave Chinner } 168b16817b6SDave Chinner 16907b6403aSDave Chinner STATIC void 17007b6403aSDave Chinner __xfs_free_perag( 17107b6403aSDave Chinner struct rcu_head *head) 17207b6403aSDave Chinner { 17307b6403aSDave Chinner struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head); 17407b6403aSDave Chinner 17507b6403aSDave Chinner ASSERT(!delayed_work_pending(&pag->pag_blockgc_work)); 17607b6403aSDave Chinner kmem_free(pag); 17707b6403aSDave Chinner } 17807b6403aSDave Chinner 17907b6403aSDave Chinner /* 18007b6403aSDave Chinner * Free up the per-ag resources associated with the mount structure. 18107b6403aSDave Chinner */ 18207b6403aSDave Chinner void 18307b6403aSDave Chinner xfs_free_perag( 18407b6403aSDave Chinner struct xfs_mount *mp) 18507b6403aSDave Chinner { 18607b6403aSDave Chinner struct xfs_perag *pag; 18707b6403aSDave Chinner xfs_agnumber_t agno; 18807b6403aSDave Chinner 18907b6403aSDave Chinner for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { 19007b6403aSDave Chinner spin_lock(&mp->m_perag_lock); 19107b6403aSDave Chinner pag = radix_tree_delete(&mp->m_perag_tree, agno); 19207b6403aSDave Chinner spin_unlock(&mp->m_perag_lock); 19307b6403aSDave Chinner ASSERT(pag); 1945b55cbc2SDave Chinner XFS_IS_CORRUPT(pag->pag_mount, atomic_read(&pag->pag_ref) != 0); 19507b6403aSDave Chinner 19607b6403aSDave Chinner cancel_delayed_work_sync(&pag->pag_blockgc_work); 19707b6403aSDave Chinner xfs_iunlink_destroy(pag); 19807b6403aSDave Chinner xfs_buf_hash_destroy(pag); 19907b6403aSDave Chinner 20007b6403aSDave Chinner call_rcu(&pag->rcu_head, __xfs_free_perag); 20107b6403aSDave Chinner } 20207b6403aSDave Chinner } 20307b6403aSDave Chinner 2040800169eSDave Chinner /* Find the size of the AG, in blocks. */ 2050800169eSDave Chinner static xfs_agblock_t 2060800169eSDave Chinner __xfs_ag_block_count( 2070800169eSDave Chinner struct xfs_mount *mp, 2080800169eSDave Chinner xfs_agnumber_t agno, 2090800169eSDave Chinner xfs_agnumber_t agcount, 2100800169eSDave Chinner xfs_rfsblock_t dblocks) 2110800169eSDave Chinner { 2120800169eSDave Chinner ASSERT(agno < agcount); 2130800169eSDave Chinner 2140800169eSDave Chinner if (agno < agcount - 1) 2150800169eSDave Chinner return mp->m_sb.sb_agblocks; 2160800169eSDave Chinner return dblocks - (agno * mp->m_sb.sb_agblocks); 2170800169eSDave Chinner } 2180800169eSDave Chinner 2190800169eSDave Chinner xfs_agblock_t 2200800169eSDave Chinner xfs_ag_block_count( 2210800169eSDave Chinner struct xfs_mount *mp, 2220800169eSDave Chinner xfs_agnumber_t agno) 2230800169eSDave Chinner { 2240800169eSDave Chinner return __xfs_ag_block_count(mp, agno, mp->m_sb.sb_agcount, 2250800169eSDave Chinner mp->m_sb.sb_dblocks); 2260800169eSDave Chinner } 2270800169eSDave Chinner 228*2d6ca832SDave Chinner /* Calculate the first and last possible inode number in an AG. */ 229*2d6ca832SDave Chinner static void 230*2d6ca832SDave Chinner __xfs_agino_range( 231*2d6ca832SDave Chinner struct xfs_mount *mp, 232*2d6ca832SDave Chinner xfs_agblock_t eoag, 233*2d6ca832SDave Chinner xfs_agino_t *first, 234*2d6ca832SDave Chinner xfs_agino_t *last) 235*2d6ca832SDave Chinner { 236*2d6ca832SDave Chinner xfs_agblock_t bno; 237*2d6ca832SDave Chinner 238*2d6ca832SDave Chinner /* 239*2d6ca832SDave Chinner * Calculate the first inode, which will be in the first 240*2d6ca832SDave Chinner * cluster-aligned block after the AGFL. 241*2d6ca832SDave Chinner */ 242*2d6ca832SDave Chinner bno = round_up(XFS_AGFL_BLOCK(mp) + 1, M_IGEO(mp)->cluster_align); 243*2d6ca832SDave Chinner *first = XFS_AGB_TO_AGINO(mp, bno); 244*2d6ca832SDave Chinner 245*2d6ca832SDave Chinner /* 246*2d6ca832SDave Chinner * Calculate the last inode, which will be at the end of the 247*2d6ca832SDave Chinner * last (aligned) cluster that can be allocated in the AG. 248*2d6ca832SDave Chinner */ 249*2d6ca832SDave Chinner bno = round_down(eoag, M_IGEO(mp)->cluster_align); 250*2d6ca832SDave Chinner *last = XFS_AGB_TO_AGINO(mp, bno) - 1; 251*2d6ca832SDave Chinner } 252*2d6ca832SDave Chinner 253*2d6ca832SDave Chinner void 254*2d6ca832SDave Chinner xfs_agino_range( 255*2d6ca832SDave Chinner struct xfs_mount *mp, 256*2d6ca832SDave Chinner xfs_agnumber_t agno, 257*2d6ca832SDave Chinner xfs_agino_t *first, 258*2d6ca832SDave Chinner xfs_agino_t *last) 259*2d6ca832SDave Chinner { 260*2d6ca832SDave Chinner return __xfs_agino_range(mp, xfs_ag_block_count(mp, agno), first, last); 261*2d6ca832SDave Chinner } 262*2d6ca832SDave Chinner 26307b6403aSDave Chinner int 26407b6403aSDave Chinner xfs_initialize_perag( 26507b6403aSDave Chinner struct xfs_mount *mp, 26607b6403aSDave Chinner xfs_agnumber_t agcount, 2670800169eSDave Chinner xfs_rfsblock_t dblocks, 26807b6403aSDave Chinner xfs_agnumber_t *maxagi) 26907b6403aSDave Chinner { 27007b6403aSDave Chinner struct xfs_perag *pag; 27107b6403aSDave Chinner xfs_agnumber_t index; 27207b6403aSDave Chinner xfs_agnumber_t first_initialised = NULLAGNUMBER; 27307b6403aSDave Chinner int error; 27407b6403aSDave Chinner 27507b6403aSDave Chinner /* 27607b6403aSDave Chinner * Walk the current per-ag tree so we don't try to initialise AGs 27707b6403aSDave Chinner * that already exist (growfs case). Allocate and insert all the 27807b6403aSDave Chinner * AGs we don't find ready for initialisation. 27907b6403aSDave Chinner */ 28007b6403aSDave Chinner for (index = 0; index < agcount; index++) { 28107b6403aSDave Chinner pag = xfs_perag_get(mp, index); 28207b6403aSDave Chinner if (pag) { 28307b6403aSDave Chinner xfs_perag_put(pag); 28407b6403aSDave Chinner continue; 28507b6403aSDave Chinner } 28607b6403aSDave Chinner 28707b6403aSDave Chinner pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL); 28807b6403aSDave Chinner if (!pag) { 28907b6403aSDave Chinner error = -ENOMEM; 29007b6403aSDave Chinner goto out_unwind_new_pags; 29107b6403aSDave Chinner } 29207b6403aSDave Chinner pag->pag_agno = index; 29307b6403aSDave Chinner pag->pag_mount = mp; 29407b6403aSDave Chinner 29507b6403aSDave Chinner error = radix_tree_preload(GFP_NOFS); 29607b6403aSDave Chinner if (error) 29707b6403aSDave Chinner goto out_free_pag; 29807b6403aSDave Chinner 29907b6403aSDave Chinner spin_lock(&mp->m_perag_lock); 30007b6403aSDave Chinner if (radix_tree_insert(&mp->m_perag_tree, index, pag)) { 30107b6403aSDave Chinner WARN_ON_ONCE(1); 30207b6403aSDave Chinner spin_unlock(&mp->m_perag_lock); 30307b6403aSDave Chinner radix_tree_preload_end(); 30407b6403aSDave Chinner error = -EEXIST; 30507b6403aSDave Chinner goto out_free_pag; 30607b6403aSDave Chinner } 30707b6403aSDave Chinner spin_unlock(&mp->m_perag_lock); 30807b6403aSDave Chinner radix_tree_preload_end(); 30907b6403aSDave Chinner 31029f11fceSEric Sandeen #ifdef __KERNEL__ 31107b6403aSDave Chinner /* Place kernel structure only init below this point. */ 31207b6403aSDave Chinner spin_lock_init(&pag->pag_ici_lock); 31307b6403aSDave Chinner spin_lock_init(&pag->pagb_lock); 31407b6403aSDave Chinner spin_lock_init(&pag->pag_state_lock); 31507b6403aSDave Chinner INIT_DELAYED_WORK(&pag->pag_blockgc_work, xfs_blockgc_worker); 31607b6403aSDave Chinner INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); 31707b6403aSDave Chinner init_waitqueue_head(&pag->pagb_wait); 31807b6403aSDave Chinner pag->pagb_count = 0; 31907b6403aSDave Chinner pag->pagb_tree = RB_ROOT; 32029f11fceSEric Sandeen #endif /* __KERNEL__ */ 32107b6403aSDave Chinner 32207b6403aSDave Chinner error = xfs_buf_hash_init(pag); 32307b6403aSDave Chinner if (error) 32407b6403aSDave Chinner goto out_remove_pag; 32507b6403aSDave Chinner 32607b6403aSDave Chinner error = xfs_iunlink_init(pag); 32707b6403aSDave Chinner if (error) 32807b6403aSDave Chinner goto out_hash_destroy; 32907b6403aSDave Chinner 33007b6403aSDave Chinner /* first new pag is fully initialized */ 33107b6403aSDave Chinner if (first_initialised == NULLAGNUMBER) 33207b6403aSDave Chinner first_initialised = index; 3330800169eSDave Chinner 3340800169eSDave Chinner /* 3350800169eSDave Chinner * Pre-calculated geometry 3360800169eSDave Chinner */ 3370800169eSDave Chinner pag->block_count = __xfs_ag_block_count(mp, index, agcount, 3380800169eSDave Chinner dblocks); 3390800169eSDave Chinner pag->min_block = XFS_AGFL_BLOCK(mp); 340*2d6ca832SDave Chinner __xfs_agino_range(mp, pag->block_count, &pag->agino_min, 341*2d6ca832SDave Chinner &pag->agino_max); 34207b6403aSDave Chinner } 34307b6403aSDave Chinner 34407b6403aSDave Chinner index = xfs_set_inode_alloc(mp, agcount); 34507b6403aSDave Chinner 34607b6403aSDave Chinner if (maxagi) 34707b6403aSDave Chinner *maxagi = index; 34807b6403aSDave Chinner 34907b6403aSDave Chinner mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp); 35007b6403aSDave Chinner return 0; 35107b6403aSDave Chinner 35207b6403aSDave Chinner out_hash_destroy: 35307b6403aSDave Chinner xfs_buf_hash_destroy(pag); 35407b6403aSDave Chinner out_remove_pag: 35507b6403aSDave Chinner radix_tree_delete(&mp->m_perag_tree, index); 35607b6403aSDave Chinner out_free_pag: 35707b6403aSDave Chinner kmem_free(pag); 35807b6403aSDave Chinner out_unwind_new_pags: 35907b6403aSDave Chinner /* unwind any prior newly initialized pags */ 36007b6403aSDave Chinner for (index = first_initialised; index < agcount; index++) { 36107b6403aSDave Chinner pag = radix_tree_delete(&mp->m_perag_tree, index); 36207b6403aSDave Chinner if (!pag) 36307b6403aSDave Chinner break; 36407b6403aSDave Chinner xfs_buf_hash_destroy(pag); 36507b6403aSDave Chinner xfs_iunlink_destroy(pag); 36607b6403aSDave Chinner kmem_free(pag); 36707b6403aSDave Chinner } 36807b6403aSDave Chinner return error; 36907b6403aSDave Chinner } 370b16817b6SDave Chinner 3712842b6dbSDarrick J. Wong static int 372b16817b6SDave Chinner xfs_get_aghdr_buf( 373b16817b6SDave Chinner struct xfs_mount *mp, 374b16817b6SDave Chinner xfs_daddr_t blkno, 375b16817b6SDave Chinner size_t numblks, 3762842b6dbSDarrick J. Wong struct xfs_buf **bpp, 377b16817b6SDave Chinner const struct xfs_buf_ops *ops) 378b16817b6SDave Chinner { 379b16817b6SDave Chinner struct xfs_buf *bp; 3802842b6dbSDarrick J. Wong int error; 381b16817b6SDave Chinner 3822842b6dbSDarrick J. Wong error = xfs_buf_get_uncached(mp->m_ddev_targp, numblks, 0, &bp); 3832842b6dbSDarrick J. Wong if (error) 3842842b6dbSDarrick J. Wong return error; 385b16817b6SDave Chinner 386b16817b6SDave Chinner bp->b_maps[0].bm_bn = blkno; 387b16817b6SDave Chinner bp->b_ops = ops; 388b16817b6SDave Chinner 3892842b6dbSDarrick J. Wong *bpp = bp; 3902842b6dbSDarrick J. Wong return 0; 391b16817b6SDave Chinner } 392b16817b6SDave Chinner 393f327a007SDarrick J. Wong static inline bool is_log_ag(struct xfs_mount *mp, struct aghdr_init_data *id) 394f327a007SDarrick J. Wong { 395f327a007SDarrick J. Wong return mp->m_sb.sb_logstart > 0 && 396f327a007SDarrick J. Wong id->agno == XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart); 397f327a007SDarrick J. Wong } 398f327a007SDarrick J. Wong 399b16817b6SDave Chinner /* 400b16817b6SDave Chinner * Generic btree root block init function 401b16817b6SDave Chinner */ 402b16817b6SDave Chinner static void 403b16817b6SDave Chinner xfs_btroot_init( 404b16817b6SDave Chinner struct xfs_mount *mp, 405b16817b6SDave Chinner struct xfs_buf *bp, 406b16817b6SDave Chinner struct aghdr_init_data *id) 407b16817b6SDave Chinner { 408f5b999c0SEric Sandeen xfs_btree_init_block(mp, bp, id->type, 0, 0, id->agno); 409b16817b6SDave Chinner } 410b16817b6SDave Chinner 4118d90857cSDarrick J. Wong /* Finish initializing a free space btree. */ 4128d90857cSDarrick J. Wong static void 4138d90857cSDarrick J. Wong xfs_freesp_init_recs( 4148d90857cSDarrick J. Wong struct xfs_mount *mp, 4158d90857cSDarrick J. Wong struct xfs_buf *bp, 4168d90857cSDarrick J. Wong struct aghdr_init_data *id) 4178d90857cSDarrick J. Wong { 4188d90857cSDarrick J. Wong struct xfs_alloc_rec *arec; 419f327a007SDarrick J. Wong struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); 4208d90857cSDarrick J. Wong 4218d90857cSDarrick J. Wong arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); 4228d90857cSDarrick J. Wong arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks); 423f327a007SDarrick J. Wong 424f327a007SDarrick J. Wong if (is_log_ag(mp, id)) { 425f327a007SDarrick J. Wong struct xfs_alloc_rec *nrec; 426f327a007SDarrick J. Wong xfs_agblock_t start = XFS_FSB_TO_AGBNO(mp, 427f327a007SDarrick J. Wong mp->m_sb.sb_logstart); 428f327a007SDarrick J. Wong 429f327a007SDarrick J. Wong ASSERT(start >= mp->m_ag_prealloc_blocks); 430f327a007SDarrick J. Wong if (start != mp->m_ag_prealloc_blocks) { 431f327a007SDarrick J. Wong /* 432f327a007SDarrick J. Wong * Modify first record to pad stripe align of log 433f327a007SDarrick J. Wong */ 434f327a007SDarrick J. Wong arec->ar_blockcount = cpu_to_be32(start - 435f327a007SDarrick J. Wong mp->m_ag_prealloc_blocks); 436f327a007SDarrick J. Wong nrec = arec + 1; 437f327a007SDarrick J. Wong 438f327a007SDarrick J. Wong /* 439f327a007SDarrick J. Wong * Insert second record at start of internal log 440f327a007SDarrick J. Wong * which then gets trimmed. 441f327a007SDarrick J. Wong */ 442f327a007SDarrick J. Wong nrec->ar_startblock = cpu_to_be32( 443f327a007SDarrick J. Wong be32_to_cpu(arec->ar_startblock) + 444f327a007SDarrick J. Wong be32_to_cpu(arec->ar_blockcount)); 445f327a007SDarrick J. Wong arec = nrec; 446f327a007SDarrick J. Wong be16_add_cpu(&block->bb_numrecs, 1); 447f327a007SDarrick J. Wong } 448f327a007SDarrick J. Wong /* 449f327a007SDarrick J. Wong * Change record start to after the internal log 450f327a007SDarrick J. Wong */ 451f327a007SDarrick J. Wong be32_add_cpu(&arec->ar_startblock, mp->m_sb.sb_logblocks); 452f327a007SDarrick J. Wong } 453f327a007SDarrick J. Wong 454f327a007SDarrick J. Wong /* 455f327a007SDarrick J. Wong * Calculate the record block count and check for the case where 456f327a007SDarrick J. Wong * the log might have consumed all available space in the AG. If 457f327a007SDarrick J. Wong * so, reset the record count to 0 to avoid exposure of an invalid 458f327a007SDarrick J. Wong * record start block. 459f327a007SDarrick J. Wong */ 4608d90857cSDarrick J. Wong arec->ar_blockcount = cpu_to_be32(id->agsize - 4618d90857cSDarrick J. Wong be32_to_cpu(arec->ar_startblock)); 462f327a007SDarrick J. Wong if (!arec->ar_blockcount) 463f327a007SDarrick J. Wong block->bb_numrecs = 0; 4648d90857cSDarrick J. Wong } 4658d90857cSDarrick J. Wong 466b16817b6SDave Chinner /* 467b16817b6SDave Chinner * Alloc btree root block init functions 468b16817b6SDave Chinner */ 469b16817b6SDave Chinner static void 470b16817b6SDave Chinner xfs_bnoroot_init( 471b16817b6SDave Chinner struct xfs_mount *mp, 472b16817b6SDave Chinner struct xfs_buf *bp, 473b16817b6SDave Chinner struct aghdr_init_data *id) 474b16817b6SDave Chinner { 475f5b999c0SEric Sandeen xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, id->agno); 4768d90857cSDarrick J. Wong xfs_freesp_init_recs(mp, bp, id); 477b16817b6SDave Chinner } 478b16817b6SDave Chinner 479b16817b6SDave Chinner static void 480b16817b6SDave Chinner xfs_cntroot_init( 481b16817b6SDave Chinner struct xfs_mount *mp, 482b16817b6SDave Chinner struct xfs_buf *bp, 483b16817b6SDave Chinner struct aghdr_init_data *id) 484b16817b6SDave Chinner { 485f5b999c0SEric Sandeen xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, id->agno); 4868d90857cSDarrick J. Wong xfs_freesp_init_recs(mp, bp, id); 487b16817b6SDave Chinner } 488b16817b6SDave Chinner 489b16817b6SDave Chinner /* 490b16817b6SDave Chinner * Reverse map root block init 491b16817b6SDave Chinner */ 492b16817b6SDave Chinner static void 493b16817b6SDave Chinner xfs_rmaproot_init( 494b16817b6SDave Chinner struct xfs_mount *mp, 495b16817b6SDave Chinner struct xfs_buf *bp, 496b16817b6SDave Chinner struct aghdr_init_data *id) 497b16817b6SDave Chinner { 498b16817b6SDave Chinner struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); 499b16817b6SDave Chinner struct xfs_rmap_rec *rrec; 500b16817b6SDave Chinner 501f5b999c0SEric Sandeen xfs_btree_init_block(mp, bp, XFS_BTNUM_RMAP, 0, 4, id->agno); 502b16817b6SDave Chinner 503b16817b6SDave Chinner /* 504b16817b6SDave Chinner * mark the AG header regions as static metadata The BNO 505b16817b6SDave Chinner * btree block is the first block after the headers, so 506b16817b6SDave Chinner * it's location defines the size of region the static 507b16817b6SDave Chinner * metadata consumes. 508b16817b6SDave Chinner * 509b16817b6SDave Chinner * Note: unlike mkfs, we never have to account for log 510b16817b6SDave Chinner * space when growing the data regions 511b16817b6SDave Chinner */ 512b16817b6SDave Chinner rrec = XFS_RMAP_REC_ADDR(block, 1); 513b16817b6SDave Chinner rrec->rm_startblock = 0; 514b16817b6SDave Chinner rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp)); 515b16817b6SDave Chinner rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS); 516b16817b6SDave Chinner rrec->rm_offset = 0; 517b16817b6SDave Chinner 518b16817b6SDave Chinner /* account freespace btree root blocks */ 519b16817b6SDave Chinner rrec = XFS_RMAP_REC_ADDR(block, 2); 520b16817b6SDave Chinner rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp)); 521b16817b6SDave Chinner rrec->rm_blockcount = cpu_to_be32(2); 522b16817b6SDave Chinner rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); 523b16817b6SDave Chinner rrec->rm_offset = 0; 524b16817b6SDave Chinner 525b16817b6SDave Chinner /* account inode btree root blocks */ 526b16817b6SDave Chinner rrec = XFS_RMAP_REC_ADDR(block, 3); 527b16817b6SDave Chinner rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp)); 528b16817b6SDave Chinner rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) - 529b16817b6SDave Chinner XFS_IBT_BLOCK(mp)); 530b16817b6SDave Chinner rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT); 531b16817b6SDave Chinner rrec->rm_offset = 0; 532b16817b6SDave Chinner 533b16817b6SDave Chinner /* account for rmap btree root */ 534b16817b6SDave Chinner rrec = XFS_RMAP_REC_ADDR(block, 4); 535b16817b6SDave Chinner rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp)); 536b16817b6SDave Chinner rrec->rm_blockcount = cpu_to_be32(1); 537b16817b6SDave Chinner rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); 538b16817b6SDave Chinner rrec->rm_offset = 0; 539b16817b6SDave Chinner 540b16817b6SDave Chinner /* account for refc btree root */ 54138c26bfdSDave Chinner if (xfs_has_reflink(mp)) { 542b16817b6SDave Chinner rrec = XFS_RMAP_REC_ADDR(block, 5); 543b16817b6SDave Chinner rrec->rm_startblock = cpu_to_be32(xfs_refc_block(mp)); 544b16817b6SDave Chinner rrec->rm_blockcount = cpu_to_be32(1); 545b16817b6SDave Chinner rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC); 546b16817b6SDave Chinner rrec->rm_offset = 0; 547b16817b6SDave Chinner be16_add_cpu(&block->bb_numrecs, 1); 548b16817b6SDave Chinner } 549f327a007SDarrick J. Wong 550f327a007SDarrick J. Wong /* account for the log space */ 551f327a007SDarrick J. Wong if (is_log_ag(mp, id)) { 552f327a007SDarrick J. Wong rrec = XFS_RMAP_REC_ADDR(block, 553f327a007SDarrick J. Wong be16_to_cpu(block->bb_numrecs) + 1); 554f327a007SDarrick J. Wong rrec->rm_startblock = cpu_to_be32( 555f327a007SDarrick J. Wong XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart)); 556f327a007SDarrick J. Wong rrec->rm_blockcount = cpu_to_be32(mp->m_sb.sb_logblocks); 557f327a007SDarrick J. Wong rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_LOG); 558f327a007SDarrick J. Wong rrec->rm_offset = 0; 559f327a007SDarrick J. Wong be16_add_cpu(&block->bb_numrecs, 1); 560f327a007SDarrick J. Wong } 561b16817b6SDave Chinner } 562b16817b6SDave Chinner 563b16817b6SDave Chinner /* 564b16817b6SDave Chinner * Initialise new secondary superblocks with the pre-grow geometry, but mark 565b16817b6SDave Chinner * them as "in progress" so we know they haven't yet been activated. This will 566b16817b6SDave Chinner * get cleared when the update with the new geometry information is done after 567b16817b6SDave Chinner * changes to the primary are committed. This isn't strictly necessary, but we 568b16817b6SDave Chinner * get it for free with the delayed buffer write lists and it means we can tell 569b16817b6SDave Chinner * if a grow operation didn't complete properly after the fact. 570b16817b6SDave Chinner */ 571b16817b6SDave Chinner static void 572b16817b6SDave Chinner xfs_sbblock_init( 573b16817b6SDave Chinner struct xfs_mount *mp, 574b16817b6SDave Chinner struct xfs_buf *bp, 575b16817b6SDave Chinner struct aghdr_init_data *id) 576b16817b6SDave Chinner { 5773e6e8afdSChristoph Hellwig struct xfs_dsb *dsb = bp->b_addr; 578b16817b6SDave Chinner 579b16817b6SDave Chinner xfs_sb_to_disk(dsb, &mp->m_sb); 580b16817b6SDave Chinner dsb->sb_inprogress = 1; 581b16817b6SDave Chinner } 582b16817b6SDave Chinner 583b16817b6SDave Chinner static void 584b16817b6SDave Chinner xfs_agfblock_init( 585b16817b6SDave Chinner struct xfs_mount *mp, 586b16817b6SDave Chinner struct xfs_buf *bp, 587b16817b6SDave Chinner struct aghdr_init_data *id) 588b16817b6SDave Chinner { 5899798f615SChristoph Hellwig struct xfs_agf *agf = bp->b_addr; 590b16817b6SDave Chinner xfs_extlen_t tmpsize; 591b16817b6SDave Chinner 592b16817b6SDave Chinner agf->agf_magicnum = cpu_to_be32(XFS_AGF_MAGIC); 593b16817b6SDave Chinner agf->agf_versionnum = cpu_to_be32(XFS_AGF_VERSION); 594b16817b6SDave Chinner agf->agf_seqno = cpu_to_be32(id->agno); 595b16817b6SDave Chinner agf->agf_length = cpu_to_be32(id->agsize); 596b16817b6SDave Chinner agf->agf_roots[XFS_BTNUM_BNOi] = cpu_to_be32(XFS_BNO_BLOCK(mp)); 597b16817b6SDave Chinner agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp)); 598b16817b6SDave Chinner agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1); 599b16817b6SDave Chinner agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1); 60038c26bfdSDave Chinner if (xfs_has_rmapbt(mp)) { 601b16817b6SDave Chinner agf->agf_roots[XFS_BTNUM_RMAPi] = 602b16817b6SDave Chinner cpu_to_be32(XFS_RMAP_BLOCK(mp)); 603b16817b6SDave Chinner agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1); 604b16817b6SDave Chinner agf->agf_rmap_blocks = cpu_to_be32(1); 605b16817b6SDave Chinner } 606b16817b6SDave Chinner 607b16817b6SDave Chinner agf->agf_flfirst = cpu_to_be32(1); 608b16817b6SDave Chinner agf->agf_fllast = 0; 609b16817b6SDave Chinner agf->agf_flcount = 0; 610b16817b6SDave Chinner tmpsize = id->agsize - mp->m_ag_prealloc_blocks; 611b16817b6SDave Chinner agf->agf_freeblks = cpu_to_be32(tmpsize); 612b16817b6SDave Chinner agf->agf_longest = cpu_to_be32(tmpsize); 61338c26bfdSDave Chinner if (xfs_has_crc(mp)) 614b16817b6SDave Chinner uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid); 61538c26bfdSDave Chinner if (xfs_has_reflink(mp)) { 616b16817b6SDave Chinner agf->agf_refcount_root = cpu_to_be32( 617b16817b6SDave Chinner xfs_refc_block(mp)); 618b16817b6SDave Chinner agf->agf_refcount_level = cpu_to_be32(1); 619b16817b6SDave Chinner agf->agf_refcount_blocks = cpu_to_be32(1); 620b16817b6SDave Chinner } 621f327a007SDarrick J. Wong 622f327a007SDarrick J. Wong if (is_log_ag(mp, id)) { 623f327a007SDarrick J. Wong int64_t logblocks = mp->m_sb.sb_logblocks; 624f327a007SDarrick J. Wong 625f327a007SDarrick J. Wong be32_add_cpu(&agf->agf_freeblks, -logblocks); 626f327a007SDarrick J. Wong agf->agf_longest = cpu_to_be32(id->agsize - 627f327a007SDarrick J. Wong XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart) - logblocks); 628f327a007SDarrick J. Wong } 629b16817b6SDave Chinner } 630b16817b6SDave Chinner 631b16817b6SDave Chinner static void 632b16817b6SDave Chinner xfs_agflblock_init( 633b16817b6SDave Chinner struct xfs_mount *mp, 634b16817b6SDave Chinner struct xfs_buf *bp, 635b16817b6SDave Chinner struct aghdr_init_data *id) 636b16817b6SDave Chinner { 637b16817b6SDave Chinner struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); 638b16817b6SDave Chinner __be32 *agfl_bno; 639b16817b6SDave Chinner int bucket; 640b16817b6SDave Chinner 64138c26bfdSDave Chinner if (xfs_has_crc(mp)) { 642b16817b6SDave Chinner agfl->agfl_magicnum = cpu_to_be32(XFS_AGFL_MAGIC); 643b16817b6SDave Chinner agfl->agfl_seqno = cpu_to_be32(id->agno); 644b16817b6SDave Chinner uuid_copy(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid); 645b16817b6SDave Chinner } 646b16817b6SDave Chinner 647183606d8SChristoph Hellwig agfl_bno = xfs_buf_to_agfl_bno(bp); 648b16817b6SDave Chinner for (bucket = 0; bucket < xfs_agfl_size(mp); bucket++) 649b16817b6SDave Chinner agfl_bno[bucket] = cpu_to_be32(NULLAGBLOCK); 650b16817b6SDave Chinner } 651b16817b6SDave Chinner 652b16817b6SDave Chinner static void 653b16817b6SDave Chinner xfs_agiblock_init( 654b16817b6SDave Chinner struct xfs_mount *mp, 655b16817b6SDave Chinner struct xfs_buf *bp, 656b16817b6SDave Chinner struct aghdr_init_data *id) 657b16817b6SDave Chinner { 658370c782bSChristoph Hellwig struct xfs_agi *agi = bp->b_addr; 659b16817b6SDave Chinner int bucket; 660b16817b6SDave Chinner 661b16817b6SDave Chinner agi->agi_magicnum = cpu_to_be32(XFS_AGI_MAGIC); 662b16817b6SDave Chinner agi->agi_versionnum = cpu_to_be32(XFS_AGI_VERSION); 663b16817b6SDave Chinner agi->agi_seqno = cpu_to_be32(id->agno); 664b16817b6SDave Chinner agi->agi_length = cpu_to_be32(id->agsize); 665b16817b6SDave Chinner agi->agi_count = 0; 666b16817b6SDave Chinner agi->agi_root = cpu_to_be32(XFS_IBT_BLOCK(mp)); 667b16817b6SDave Chinner agi->agi_level = cpu_to_be32(1); 668b16817b6SDave Chinner agi->agi_freecount = 0; 669b16817b6SDave Chinner agi->agi_newino = cpu_to_be32(NULLAGINO); 670b16817b6SDave Chinner agi->agi_dirino = cpu_to_be32(NULLAGINO); 67138c26bfdSDave Chinner if (xfs_has_crc(mp)) 672b16817b6SDave Chinner uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid); 67338c26bfdSDave Chinner if (xfs_has_finobt(mp)) { 674b16817b6SDave Chinner agi->agi_free_root = cpu_to_be32(XFS_FIBT_BLOCK(mp)); 675b16817b6SDave Chinner agi->agi_free_level = cpu_to_be32(1); 676b16817b6SDave Chinner } 677b16817b6SDave Chinner for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) 678b16817b6SDave Chinner agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); 679ebd9027dSDave Chinner if (xfs_has_inobtcounts(mp)) { 6802a39946cSDarrick J. Wong agi->agi_iblocks = cpu_to_be32(1); 681ebd9027dSDave Chinner if (xfs_has_finobt(mp)) 6822a39946cSDarrick J. Wong agi->agi_fblocks = cpu_to_be32(1); 6832a39946cSDarrick J. Wong } 684b16817b6SDave Chinner } 685b16817b6SDave Chinner 686b16817b6SDave Chinner typedef void (*aghdr_init_work_f)(struct xfs_mount *mp, struct xfs_buf *bp, 687b16817b6SDave Chinner struct aghdr_init_data *id); 688b16817b6SDave Chinner static int 689b16817b6SDave Chinner xfs_ag_init_hdr( 690b16817b6SDave Chinner struct xfs_mount *mp, 691b16817b6SDave Chinner struct aghdr_init_data *id, 692b16817b6SDave Chinner aghdr_init_work_f work, 693b16817b6SDave Chinner const struct xfs_buf_ops *ops) 694b16817b6SDave Chinner { 695b16817b6SDave Chinner struct xfs_buf *bp; 6962842b6dbSDarrick J. Wong int error; 697b16817b6SDave Chinner 6982842b6dbSDarrick J. Wong error = xfs_get_aghdr_buf(mp, id->daddr, id->numblks, &bp, ops); 6992842b6dbSDarrick J. Wong if (error) 7002842b6dbSDarrick J. Wong return error; 701b16817b6SDave Chinner 702b16817b6SDave Chinner (*work)(mp, bp, id); 703b16817b6SDave Chinner 704b16817b6SDave Chinner xfs_buf_delwri_queue(bp, &id->buffer_list); 705b16817b6SDave Chinner xfs_buf_relse(bp); 706b16817b6SDave Chinner return 0; 707b16817b6SDave Chinner } 708b16817b6SDave Chinner 709b16817b6SDave Chinner struct xfs_aghdr_grow_data { 710b16817b6SDave Chinner xfs_daddr_t daddr; 711b16817b6SDave Chinner size_t numblks; 712b16817b6SDave Chinner const struct xfs_buf_ops *ops; 713b16817b6SDave Chinner aghdr_init_work_f work; 714b16817b6SDave Chinner xfs_btnum_t type; 715b16817b6SDave Chinner bool need_init; 716b16817b6SDave Chinner }; 717b16817b6SDave Chinner 718b16817b6SDave Chinner /* 719b16817b6SDave Chinner * Prepare new AG headers to be written to disk. We use uncached buffers here, 720b16817b6SDave Chinner * as it is assumed these new AG headers are currently beyond the currently 721b16817b6SDave Chinner * valid filesystem address space. Using cached buffers would trip over EOFS 722b16817b6SDave Chinner * corruption detection alogrithms in the buffer cache lookup routines. 723b16817b6SDave Chinner * 724b16817b6SDave Chinner * This is a non-transactional function, but the prepared buffers are added to a 725b16817b6SDave Chinner * delayed write buffer list supplied by the caller so they can submit them to 726b16817b6SDave Chinner * disk and wait on them as required. 727b16817b6SDave Chinner */ 728b16817b6SDave Chinner int 729b16817b6SDave Chinner xfs_ag_init_headers( 730b16817b6SDave Chinner struct xfs_mount *mp, 731b16817b6SDave Chinner struct aghdr_init_data *id) 732b16817b6SDave Chinner 733b16817b6SDave Chinner { 734b16817b6SDave Chinner struct xfs_aghdr_grow_data aghdr_data[] = { 735b16817b6SDave Chinner { /* SB */ 736b16817b6SDave Chinner .daddr = XFS_AG_DADDR(mp, id->agno, XFS_SB_DADDR), 737b16817b6SDave Chinner .numblks = XFS_FSS_TO_BB(mp, 1), 738b16817b6SDave Chinner .ops = &xfs_sb_buf_ops, 739b16817b6SDave Chinner .work = &xfs_sbblock_init, 740b16817b6SDave Chinner .need_init = true 741b16817b6SDave Chinner }, 742b16817b6SDave Chinner { /* AGF */ 743b16817b6SDave Chinner .daddr = XFS_AG_DADDR(mp, id->agno, XFS_AGF_DADDR(mp)), 744b16817b6SDave Chinner .numblks = XFS_FSS_TO_BB(mp, 1), 745b16817b6SDave Chinner .ops = &xfs_agf_buf_ops, 746b16817b6SDave Chinner .work = &xfs_agfblock_init, 747b16817b6SDave Chinner .need_init = true 748b16817b6SDave Chinner }, 749b16817b6SDave Chinner { /* AGFL */ 750b16817b6SDave Chinner .daddr = XFS_AG_DADDR(mp, id->agno, XFS_AGFL_DADDR(mp)), 751b16817b6SDave Chinner .numblks = XFS_FSS_TO_BB(mp, 1), 752b16817b6SDave Chinner .ops = &xfs_agfl_buf_ops, 753b16817b6SDave Chinner .work = &xfs_agflblock_init, 754b16817b6SDave Chinner .need_init = true 755b16817b6SDave Chinner }, 756b16817b6SDave Chinner { /* AGI */ 757b16817b6SDave Chinner .daddr = XFS_AG_DADDR(mp, id->agno, XFS_AGI_DADDR(mp)), 758b16817b6SDave Chinner .numblks = XFS_FSS_TO_BB(mp, 1), 759b16817b6SDave Chinner .ops = &xfs_agi_buf_ops, 760b16817b6SDave Chinner .work = &xfs_agiblock_init, 761b16817b6SDave Chinner .need_init = true 762b16817b6SDave Chinner }, 763b16817b6SDave Chinner { /* BNO root block */ 764b16817b6SDave Chinner .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_BNO_BLOCK(mp)), 765b16817b6SDave Chinner .numblks = BTOBB(mp->m_sb.sb_blocksize), 76627df4f50SBrian Foster .ops = &xfs_bnobt_buf_ops, 767b16817b6SDave Chinner .work = &xfs_bnoroot_init, 768b16817b6SDave Chinner .need_init = true 769b16817b6SDave Chinner }, 770b16817b6SDave Chinner { /* CNT root block */ 771b16817b6SDave Chinner .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_CNT_BLOCK(mp)), 772b16817b6SDave Chinner .numblks = BTOBB(mp->m_sb.sb_blocksize), 77327df4f50SBrian Foster .ops = &xfs_cntbt_buf_ops, 774b16817b6SDave Chinner .work = &xfs_cntroot_init, 775b16817b6SDave Chinner .need_init = true 776b16817b6SDave Chinner }, 777b16817b6SDave Chinner { /* INO root block */ 778b16817b6SDave Chinner .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_IBT_BLOCK(mp)), 779b16817b6SDave Chinner .numblks = BTOBB(mp->m_sb.sb_blocksize), 780b16817b6SDave Chinner .ops = &xfs_inobt_buf_ops, 781b16817b6SDave Chinner .work = &xfs_btroot_init, 782b16817b6SDave Chinner .type = XFS_BTNUM_INO, 783b16817b6SDave Chinner .need_init = true 784b16817b6SDave Chinner }, 785b16817b6SDave Chinner { /* FINO root block */ 786b16817b6SDave Chinner .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_FIBT_BLOCK(mp)), 787b16817b6SDave Chinner .numblks = BTOBB(mp->m_sb.sb_blocksize), 78801e68f40SBrian Foster .ops = &xfs_finobt_buf_ops, 789b16817b6SDave Chinner .work = &xfs_btroot_init, 790b16817b6SDave Chinner .type = XFS_BTNUM_FINO, 79138c26bfdSDave Chinner .need_init = xfs_has_finobt(mp) 792b16817b6SDave Chinner }, 793b16817b6SDave Chinner { /* RMAP root block */ 794b16817b6SDave Chinner .daddr = XFS_AGB_TO_DADDR(mp, id->agno, XFS_RMAP_BLOCK(mp)), 795b16817b6SDave Chinner .numblks = BTOBB(mp->m_sb.sb_blocksize), 796b16817b6SDave Chinner .ops = &xfs_rmapbt_buf_ops, 797b16817b6SDave Chinner .work = &xfs_rmaproot_init, 79838c26bfdSDave Chinner .need_init = xfs_has_rmapbt(mp) 799b16817b6SDave Chinner }, 800b16817b6SDave Chinner { /* REFC root block */ 801b16817b6SDave Chinner .daddr = XFS_AGB_TO_DADDR(mp, id->agno, xfs_refc_block(mp)), 802b16817b6SDave Chinner .numblks = BTOBB(mp->m_sb.sb_blocksize), 803b16817b6SDave Chinner .ops = &xfs_refcountbt_buf_ops, 804b16817b6SDave Chinner .work = &xfs_btroot_init, 805b16817b6SDave Chinner .type = XFS_BTNUM_REFC, 80638c26bfdSDave Chinner .need_init = xfs_has_reflink(mp) 807b16817b6SDave Chinner }, 808b16817b6SDave Chinner { /* NULL terminating block */ 809b16817b6SDave Chinner .daddr = XFS_BUF_DADDR_NULL, 810b16817b6SDave Chinner } 811b16817b6SDave Chinner }; 812b16817b6SDave Chinner struct xfs_aghdr_grow_data *dp; 813b16817b6SDave Chinner int error = 0; 814b16817b6SDave Chinner 815b16817b6SDave Chinner /* Account for AG free space in new AG */ 816b16817b6SDave Chinner id->nfree += id->agsize - mp->m_ag_prealloc_blocks; 817b16817b6SDave Chinner for (dp = &aghdr_data[0]; dp->daddr != XFS_BUF_DADDR_NULL; dp++) { 818b16817b6SDave Chinner if (!dp->need_init) 819b16817b6SDave Chinner continue; 820b16817b6SDave Chinner 821b16817b6SDave Chinner id->daddr = dp->daddr; 822b16817b6SDave Chinner id->numblks = dp->numblks; 823b16817b6SDave Chinner id->type = dp->type; 824b16817b6SDave Chinner error = xfs_ag_init_hdr(mp, id, dp->work, dp->ops); 825b16817b6SDave Chinner if (error) 826b16817b6SDave Chinner break; 827b16817b6SDave Chinner } 828b16817b6SDave Chinner return error; 829b16817b6SDave Chinner } 83049dd56f2SDave Chinner 83146141dc8SGao Xiang int 83246141dc8SGao Xiang xfs_ag_shrink_space( 833c6aee248SDave Chinner struct xfs_perag *pag, 83446141dc8SGao Xiang struct xfs_trans **tpp, 83546141dc8SGao Xiang xfs_extlen_t delta) 83646141dc8SGao Xiang { 837c6aee248SDave Chinner struct xfs_mount *mp = pag->pag_mount; 83846141dc8SGao Xiang struct xfs_alloc_arg args = { 83946141dc8SGao Xiang .tp = *tpp, 84046141dc8SGao Xiang .mp = mp, 84146141dc8SGao Xiang .type = XFS_ALLOCTYPE_THIS_BNO, 84246141dc8SGao Xiang .minlen = delta, 84346141dc8SGao Xiang .maxlen = delta, 84446141dc8SGao Xiang .oinfo = XFS_RMAP_OINFO_SKIP_UPDATE, 84546141dc8SGao Xiang .resv = XFS_AG_RESV_NONE, 84646141dc8SGao Xiang .prod = 1 84746141dc8SGao Xiang }; 84846141dc8SGao Xiang struct xfs_buf *agibp, *agfbp; 84946141dc8SGao Xiang struct xfs_agi *agi; 85046141dc8SGao Xiang struct xfs_agf *agf; 851a8f3522cSDarrick J. Wong xfs_agblock_t aglen; 85246141dc8SGao Xiang int error, err2; 85346141dc8SGao Xiang 854c6aee248SDave Chinner ASSERT(pag->pag_agno == mp->m_sb.sb_agcount - 1); 85599b13c7fSDave Chinner error = xfs_ialloc_read_agi(pag, *tpp, &agibp); 85646141dc8SGao Xiang if (error) 85746141dc8SGao Xiang return error; 85846141dc8SGao Xiang 85946141dc8SGao Xiang agi = agibp->b_addr; 86046141dc8SGao Xiang 86108d3e84fSDave Chinner error = xfs_alloc_read_agf(pag, *tpp, 0, &agfbp); 86246141dc8SGao Xiang if (error) 86346141dc8SGao Xiang return error; 86446141dc8SGao Xiang 86546141dc8SGao Xiang agf = agfbp->b_addr; 866a8f3522cSDarrick J. Wong aglen = be32_to_cpu(agi->agi_length); 86746141dc8SGao Xiang /* some extra paranoid checks before we shrink the ag */ 86846141dc8SGao Xiang if (XFS_IS_CORRUPT(mp, agf->agf_length != agi->agi_length)) 86946141dc8SGao Xiang return -EFSCORRUPTED; 870a8f3522cSDarrick J. Wong if (delta >= aglen) 87146141dc8SGao Xiang return -EINVAL; 87246141dc8SGao Xiang 873c6aee248SDave Chinner args.fsbno = XFS_AGB_TO_FSB(mp, pag->pag_agno, aglen - delta); 87446141dc8SGao Xiang 87546141dc8SGao Xiang /* 876da062d16SDarrick J. Wong * Make sure that the last inode cluster cannot overlap with the new 877da062d16SDarrick J. Wong * end of the AG, even if it's sparse. 878da062d16SDarrick J. Wong */ 879c6aee248SDave Chinner error = xfs_ialloc_check_shrink(*tpp, pag->pag_agno, agibp, 880c6aee248SDave Chinner aglen - delta); 881da062d16SDarrick J. Wong if (error) 882da062d16SDarrick J. Wong return error; 883da062d16SDarrick J. Wong 884da062d16SDarrick J. Wong /* 88546141dc8SGao Xiang * Disable perag reservations so it doesn't cause the allocation request 88646141dc8SGao Xiang * to fail. We'll reestablish reservation before we return. 88746141dc8SGao Xiang */ 88899b13c7fSDave Chinner error = xfs_ag_resv_free(pag); 88946141dc8SGao Xiang if (error) 89046141dc8SGao Xiang return error; 89146141dc8SGao Xiang 89246141dc8SGao Xiang /* internal log shouldn't also show up in the free space btrees */ 89346141dc8SGao Xiang error = xfs_alloc_vextent(&args); 89446141dc8SGao Xiang if (!error && args.agbno == NULLAGBLOCK) 89546141dc8SGao Xiang error = -ENOSPC; 89646141dc8SGao Xiang 89746141dc8SGao Xiang if (error) { 89846141dc8SGao Xiang /* 89946141dc8SGao Xiang * if extent allocation fails, need to roll the transaction to 90046141dc8SGao Xiang * ensure that the AGFL fixup has been committed anyway. 90146141dc8SGao Xiang */ 90246141dc8SGao Xiang xfs_trans_bhold(*tpp, agfbp); 90346141dc8SGao Xiang err2 = xfs_trans_roll(tpp); 90446141dc8SGao Xiang if (err2) 90546141dc8SGao Xiang return err2; 90646141dc8SGao Xiang xfs_trans_bjoin(*tpp, agfbp); 90746141dc8SGao Xiang goto resv_init_out; 90846141dc8SGao Xiang } 90946141dc8SGao Xiang 91046141dc8SGao Xiang /* 91146141dc8SGao Xiang * if successfully deleted from freespace btrees, need to confirm 91246141dc8SGao Xiang * per-AG reservation works as expected. 91346141dc8SGao Xiang */ 91446141dc8SGao Xiang be32_add_cpu(&agi->agi_length, -delta); 91546141dc8SGao Xiang be32_add_cpu(&agf->agf_length, -delta); 91646141dc8SGao Xiang 91799b13c7fSDave Chinner err2 = xfs_ag_resv_init(pag, *tpp); 91846141dc8SGao Xiang if (err2) { 91946141dc8SGao Xiang be32_add_cpu(&agi->agi_length, delta); 92046141dc8SGao Xiang be32_add_cpu(&agf->agf_length, delta); 92146141dc8SGao Xiang if (err2 != -ENOSPC) 92246141dc8SGao Xiang goto resv_err; 92346141dc8SGao Xiang 924c201d9caSDarrick J. Wong __xfs_free_extent_later(*tpp, args.fsbno, delta, NULL, true); 92546141dc8SGao Xiang 92646141dc8SGao Xiang /* 92746141dc8SGao Xiang * Roll the transaction before trying to re-init the per-ag 92846141dc8SGao Xiang * reservation. The new transaction is clean so it will cancel 92946141dc8SGao Xiang * without any side effects. 93046141dc8SGao Xiang */ 93146141dc8SGao Xiang error = xfs_defer_finish(tpp); 93246141dc8SGao Xiang if (error) 93346141dc8SGao Xiang return error; 93446141dc8SGao Xiang 93546141dc8SGao Xiang error = -ENOSPC; 93646141dc8SGao Xiang goto resv_init_out; 93746141dc8SGao Xiang } 93846141dc8SGao Xiang xfs_ialloc_log_agi(*tpp, agibp, XFS_AGI_LENGTH); 93946141dc8SGao Xiang xfs_alloc_log_agf(*tpp, agfbp, XFS_AGF_LENGTH); 94046141dc8SGao Xiang return 0; 94199b13c7fSDave Chinner 94246141dc8SGao Xiang resv_init_out: 94399b13c7fSDave Chinner err2 = xfs_ag_resv_init(pag, *tpp); 94446141dc8SGao Xiang if (!err2) 94546141dc8SGao Xiang return error; 94646141dc8SGao Xiang resv_err: 94746141dc8SGao Xiang xfs_warn(mp, "Error %d reserving per-AG metadata reserve pool.", err2); 94846141dc8SGao Xiang xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); 94946141dc8SGao Xiang return err2; 95046141dc8SGao Xiang } 95146141dc8SGao Xiang 95249dd56f2SDave Chinner /* 95349dd56f2SDave Chinner * Extent the AG indicated by the @id by the length passed in 95449dd56f2SDave Chinner */ 95549dd56f2SDave Chinner int 95649dd56f2SDave Chinner xfs_ag_extend_space( 957c6aee248SDave Chinner struct xfs_perag *pag, 95849dd56f2SDave Chinner struct xfs_trans *tp, 95949dd56f2SDave Chinner xfs_extlen_t len) 96049dd56f2SDave Chinner { 96149dd56f2SDave Chinner struct xfs_buf *bp; 96249dd56f2SDave Chinner struct xfs_agi *agi; 96349dd56f2SDave Chinner struct xfs_agf *agf; 96449dd56f2SDave Chinner int error; 96549dd56f2SDave Chinner 966c6aee248SDave Chinner ASSERT(pag->pag_agno == pag->pag_mount->m_sb.sb_agcount - 1); 967c6aee248SDave Chinner 96899b13c7fSDave Chinner error = xfs_ialloc_read_agi(pag, tp, &bp); 96949dd56f2SDave Chinner if (error) 97049dd56f2SDave Chinner return error; 97149dd56f2SDave Chinner 972370c782bSChristoph Hellwig agi = bp->b_addr; 97349dd56f2SDave Chinner be32_add_cpu(&agi->agi_length, len); 97449dd56f2SDave Chinner xfs_ialloc_log_agi(tp, bp, XFS_AGI_LENGTH); 97549dd56f2SDave Chinner 97649dd56f2SDave Chinner /* 97749dd56f2SDave Chinner * Change agf length. 97849dd56f2SDave Chinner */ 97908d3e84fSDave Chinner error = xfs_alloc_read_agf(pag, tp, 0, &bp); 98049dd56f2SDave Chinner if (error) 98149dd56f2SDave Chinner return error; 98249dd56f2SDave Chinner 9839798f615SChristoph Hellwig agf = bp->b_addr; 98449dd56f2SDave Chinner be32_add_cpu(&agf->agf_length, len); 98549dd56f2SDave Chinner ASSERT(agf->agf_length == agi->agi_length); 98649dd56f2SDave Chinner xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH); 98749dd56f2SDave Chinner 98849dd56f2SDave Chinner /* 98949dd56f2SDave Chinner * Free the new space. 99049dd56f2SDave Chinner * 9917280fedaSDarrick J. Wong * XFS_RMAP_OINFO_SKIP_UPDATE is used here to tell the rmap btree that 99249dd56f2SDave Chinner * this doesn't actually exist in the rmap btree. 99349dd56f2SDave Chinner */ 994c6aee248SDave Chinner error = xfs_rmap_free(tp, bp, pag, be32_to_cpu(agf->agf_length) - len, 9957280fedaSDarrick J. Wong len, &XFS_RMAP_OINFO_SKIP_UPDATE); 99649dd56f2SDave Chinner if (error) 99749dd56f2SDave Chinner return error; 99849dd56f2SDave Chinner 9990800169eSDave Chinner error = xfs_free_extent(tp, XFS_AGB_TO_FSB(pag->pag_mount, pag->pag_agno, 100049dd56f2SDave Chinner be32_to_cpu(agf->agf_length) - len), 10017280fedaSDarrick J. Wong len, &XFS_RMAP_OINFO_SKIP_UPDATE, 10027280fedaSDarrick J. Wong XFS_AG_RESV_NONE); 10030800169eSDave Chinner if (error) 10040800169eSDave Chinner return error; 10050800169eSDave Chinner 10060800169eSDave Chinner /* Update perag geometry */ 10070800169eSDave Chinner pag->block_count = be32_to_cpu(agf->agf_length); 1008*2d6ca832SDave Chinner __xfs_agino_range(pag->pag_mount, pag->block_count, &pag->agino_min, 1009*2d6ca832SDave Chinner &pag->agino_max); 10100800169eSDave Chinner return 0; 101149dd56f2SDave Chinner } 10127cd5006bSDarrick J. Wong 10137cd5006bSDarrick J. Wong /* Retrieve AG geometry. */ 10147cd5006bSDarrick J. Wong int 10157cd5006bSDarrick J. Wong xfs_ag_get_geometry( 1016c6aee248SDave Chinner struct xfs_perag *pag, 10177cd5006bSDarrick J. Wong struct xfs_ag_geometry *ageo) 10187cd5006bSDarrick J. Wong { 10197cd5006bSDarrick J. Wong struct xfs_buf *agi_bp; 10207cd5006bSDarrick J. Wong struct xfs_buf *agf_bp; 10217cd5006bSDarrick J. Wong struct xfs_agi *agi; 10227cd5006bSDarrick J. Wong struct xfs_agf *agf; 10237cd5006bSDarrick J. Wong unsigned int freeblks; 10247cd5006bSDarrick J. Wong int error; 10257cd5006bSDarrick J. Wong 10267cd5006bSDarrick J. Wong /* Lock the AG headers. */ 102799b13c7fSDave Chinner error = xfs_ialloc_read_agi(pag, NULL, &agi_bp); 10287cd5006bSDarrick J. Wong if (error) 10297cd5006bSDarrick J. Wong return error; 103008d3e84fSDave Chinner error = xfs_alloc_read_agf(pag, NULL, 0, &agf_bp); 10317cd5006bSDarrick J. Wong if (error) 10327cd5006bSDarrick J. Wong goto out_agi; 103392a00544SGao Xiang 10347cd5006bSDarrick J. Wong /* Fill out form. */ 10357cd5006bSDarrick J. Wong memset(ageo, 0, sizeof(*ageo)); 1036c6aee248SDave Chinner ageo->ag_number = pag->pag_agno; 10377cd5006bSDarrick J. Wong 1038370c782bSChristoph Hellwig agi = agi_bp->b_addr; 10397cd5006bSDarrick J. Wong ageo->ag_icount = be32_to_cpu(agi->agi_count); 10407cd5006bSDarrick J. Wong ageo->ag_ifree = be32_to_cpu(agi->agi_freecount); 10417cd5006bSDarrick J. Wong 10429798f615SChristoph Hellwig agf = agf_bp->b_addr; 10437cd5006bSDarrick J. Wong ageo->ag_length = be32_to_cpu(agf->agf_length); 10447cd5006bSDarrick J. Wong freeblks = pag->pagf_freeblks + 10457cd5006bSDarrick J. Wong pag->pagf_flcount + 10467cd5006bSDarrick J. Wong pag->pagf_btreeblks - 10477cd5006bSDarrick J. Wong xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE); 10487cd5006bSDarrick J. Wong ageo->ag_freeblks = freeblks; 10491302c6a2SDarrick J. Wong xfs_ag_geom_health(pag, ageo); 10507cd5006bSDarrick J. Wong 10517cd5006bSDarrick J. Wong /* Release resources. */ 10527cd5006bSDarrick J. Wong xfs_buf_relse(agf_bp); 10537cd5006bSDarrick J. Wong out_agi: 10547cd5006bSDarrick J. Wong xfs_buf_relse(agi_bp); 10557cd5006bSDarrick J. Wong return error; 10567cd5006bSDarrick J. Wong } 1057