162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 462306a36Sopenharmony_ci * All Rights Reserved. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci#include "xfs.h" 762306a36Sopenharmony_ci#include "xfs_fs.h" 862306a36Sopenharmony_ci#include "xfs_format.h" 962306a36Sopenharmony_ci#include "xfs_log_format.h" 1062306a36Sopenharmony_ci#include "xfs_shared.h" 1162306a36Sopenharmony_ci#include "xfs_trans_resv.h" 1262306a36Sopenharmony_ci#include "xfs_bit.h" 1362306a36Sopenharmony_ci#include "xfs_mount.h" 1462306a36Sopenharmony_ci#include "xfs_defer.h" 1562306a36Sopenharmony_ci#include "xfs_btree.h" 1662306a36Sopenharmony_ci#include "xfs_rmap.h" 1762306a36Sopenharmony_ci#include "xfs_alloc_btree.h" 1862306a36Sopenharmony_ci#include "xfs_alloc.h" 1962306a36Sopenharmony_ci#include "xfs_extent_busy.h" 2062306a36Sopenharmony_ci#include "xfs_errortag.h" 2162306a36Sopenharmony_ci#include "xfs_error.h" 2262306a36Sopenharmony_ci#include "xfs_trace.h" 2362306a36Sopenharmony_ci#include "xfs_trans.h" 2462306a36Sopenharmony_ci#include "xfs_buf_item.h" 2562306a36Sopenharmony_ci#include "xfs_log.h" 2662306a36Sopenharmony_ci#include "xfs_ag.h" 2762306a36Sopenharmony_ci#include "xfs_ag_resv.h" 2862306a36Sopenharmony_ci#include "xfs_bmap.h" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct kmem_cache *xfs_extfree_item_cache; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct workqueue_struct *xfs_alloc_wq; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b))) 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define XFSA_FIXUP_BNO_OK 1 3762306a36Sopenharmony_ci#define XFSA_FIXUP_CNT_OK 2 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* 4062306a36Sopenharmony_ci * Size of the AGFL. For CRC-enabled filesystes we steal a couple of slots in 4162306a36Sopenharmony_ci * the beginning of the block for a proper header with the location information 4262306a36Sopenharmony_ci * and CRC. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ciunsigned int 4562306a36Sopenharmony_cixfs_agfl_size( 4662306a36Sopenharmony_ci struct xfs_mount *mp) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci unsigned int size = mp->m_sb.sb_sectsize; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (xfs_has_crc(mp)) 5162306a36Sopenharmony_ci size -= sizeof(struct xfs_agfl); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci return size / sizeof(xfs_agblock_t); 5462306a36Sopenharmony_ci} 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ciunsigned int 5762306a36Sopenharmony_cixfs_refc_block( 5862306a36Sopenharmony_ci struct xfs_mount *mp) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci if (xfs_has_rmapbt(mp)) 6162306a36Sopenharmony_ci return XFS_RMAP_BLOCK(mp) + 1; 6262306a36Sopenharmony_ci if (xfs_has_finobt(mp)) 6362306a36Sopenharmony_ci return XFS_FIBT_BLOCK(mp) + 1; 6462306a36Sopenharmony_ci return XFS_IBT_BLOCK(mp) + 1; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cixfs_extlen_t 6862306a36Sopenharmony_cixfs_prealloc_blocks( 6962306a36Sopenharmony_ci struct xfs_mount *mp) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci if (xfs_has_reflink(mp)) 7262306a36Sopenharmony_ci return xfs_refc_block(mp) + 1; 7362306a36Sopenharmony_ci if (xfs_has_rmapbt(mp)) 7462306a36Sopenharmony_ci return XFS_RMAP_BLOCK(mp) + 1; 7562306a36Sopenharmony_ci if (xfs_has_finobt(mp)) 7662306a36Sopenharmony_ci return XFS_FIBT_BLOCK(mp) + 1; 7762306a36Sopenharmony_ci return XFS_IBT_BLOCK(mp) + 1; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* 8162306a36Sopenharmony_ci * The number of blocks per AG that we withhold from xfs_mod_fdblocks to 8262306a36Sopenharmony_ci * guarantee that we can refill the AGFL prior to allocating space in a nearly 8362306a36Sopenharmony_ci * full AG. Although the space described by the free space btrees, the 8462306a36Sopenharmony_ci * blocks used by the freesp btrees themselves, and the blocks owned by the 8562306a36Sopenharmony_ci * AGFL are counted in the ondisk fdblocks, it's a mistake to let the ondisk 8662306a36Sopenharmony_ci * free space in the AG drop so low that the free space btrees cannot refill an 8762306a36Sopenharmony_ci * empty AGFL up to the minimum level. Rather than grind through empty AGs 8862306a36Sopenharmony_ci * until the fs goes down, we subtract this many AG blocks from the incore 8962306a36Sopenharmony_ci * fdblocks to ensure user allocation does not overcommit the space the 9062306a36Sopenharmony_ci * filesystem needs for the AGFLs. The rmap btree uses a per-AG reservation to 9162306a36Sopenharmony_ci * withhold space from xfs_mod_fdblocks, so we do not account for that here. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci#define XFS_ALLOCBT_AGFL_RESERVE 4 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/* 9662306a36Sopenharmony_ci * Compute the number of blocks that we set aside to guarantee the ability to 9762306a36Sopenharmony_ci * refill the AGFL and handle a full bmap btree split. 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * In order to avoid ENOSPC-related deadlock caused by out-of-order locking of 10062306a36Sopenharmony_ci * AGF buffer (PV 947395), we place constraints on the relationship among 10162306a36Sopenharmony_ci * actual allocations for data blocks, freelist blocks, and potential file data 10262306a36Sopenharmony_ci * bmap btree blocks. However, these restrictions may result in no actual space 10362306a36Sopenharmony_ci * allocated for a delayed extent, for example, a data block in a certain AG is 10462306a36Sopenharmony_ci * allocated but there is no additional block for the additional bmap btree 10562306a36Sopenharmony_ci * block due to a split of the bmap btree of the file. The result of this may 10662306a36Sopenharmony_ci * lead to an infinite loop when the file gets flushed to disk and all delayed 10762306a36Sopenharmony_ci * extents need to be actually allocated. To get around this, we explicitly set 10862306a36Sopenharmony_ci * aside a few blocks which will not be reserved in delayed allocation. 10962306a36Sopenharmony_ci * 11062306a36Sopenharmony_ci * For each AG, we need to reserve enough blocks to replenish a totally empty 11162306a36Sopenharmony_ci * AGFL and 4 more to handle a potential split of the file's bmap btree. 11262306a36Sopenharmony_ci */ 11362306a36Sopenharmony_ciunsigned int 11462306a36Sopenharmony_cixfs_alloc_set_aside( 11562306a36Sopenharmony_ci struct xfs_mount *mp) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci return mp->m_sb.sb_agcount * (XFS_ALLOCBT_AGFL_RESERVE + 4); 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* 12162306a36Sopenharmony_ci * When deciding how much space to allocate out of an AG, we limit the 12262306a36Sopenharmony_ci * allocation maximum size to the size the AG. However, we cannot use all the 12362306a36Sopenharmony_ci * blocks in the AG - some are permanently used by metadata. These 12462306a36Sopenharmony_ci * blocks are generally: 12562306a36Sopenharmony_ci * - the AG superblock, AGF, AGI and AGFL 12662306a36Sopenharmony_ci * - the AGF (bno and cnt) and AGI btree root blocks, and optionally 12762306a36Sopenharmony_ci * the AGI free inode and rmap btree root blocks. 12862306a36Sopenharmony_ci * - blocks on the AGFL according to xfs_alloc_set_aside() limits 12962306a36Sopenharmony_ci * - the rmapbt root block 13062306a36Sopenharmony_ci * 13162306a36Sopenharmony_ci * The AG headers are sector sized, so the amount of space they take up is 13262306a36Sopenharmony_ci * dependent on filesystem geometry. The others are all single blocks. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ciunsigned int 13562306a36Sopenharmony_cixfs_alloc_ag_max_usable( 13662306a36Sopenharmony_ci struct xfs_mount *mp) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci unsigned int blocks; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci blocks = XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)); /* ag headers */ 14162306a36Sopenharmony_ci blocks += XFS_ALLOCBT_AGFL_RESERVE; 14262306a36Sopenharmony_ci blocks += 3; /* AGF, AGI btree root blocks */ 14362306a36Sopenharmony_ci if (xfs_has_finobt(mp)) 14462306a36Sopenharmony_ci blocks++; /* finobt root block */ 14562306a36Sopenharmony_ci if (xfs_has_rmapbt(mp)) 14662306a36Sopenharmony_ci blocks++; /* rmap root block */ 14762306a36Sopenharmony_ci if (xfs_has_reflink(mp)) 14862306a36Sopenharmony_ci blocks++; /* refcount root block */ 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci return mp->m_sb.sb_agblocks - blocks; 15162306a36Sopenharmony_ci} 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* 15462306a36Sopenharmony_ci * Lookup the record equal to [bno, len] in the btree given by cur. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ciSTATIC int /* error */ 15762306a36Sopenharmony_cixfs_alloc_lookup_eq( 15862306a36Sopenharmony_ci struct xfs_btree_cur *cur, /* btree cursor */ 15962306a36Sopenharmony_ci xfs_agblock_t bno, /* starting block of extent */ 16062306a36Sopenharmony_ci xfs_extlen_t len, /* length of extent */ 16162306a36Sopenharmony_ci int *stat) /* success/failure */ 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci int error; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci cur->bc_rec.a.ar_startblock = bno; 16662306a36Sopenharmony_ci cur->bc_rec.a.ar_blockcount = len; 16762306a36Sopenharmony_ci error = xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); 16862306a36Sopenharmony_ci cur->bc_ag.abt.active = (*stat == 1); 16962306a36Sopenharmony_ci return error; 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci/* 17362306a36Sopenharmony_ci * Lookup the first record greater than or equal to [bno, len] 17462306a36Sopenharmony_ci * in the btree given by cur. 17562306a36Sopenharmony_ci */ 17662306a36Sopenharmony_ciint /* error */ 17762306a36Sopenharmony_cixfs_alloc_lookup_ge( 17862306a36Sopenharmony_ci struct xfs_btree_cur *cur, /* btree cursor */ 17962306a36Sopenharmony_ci xfs_agblock_t bno, /* starting block of extent */ 18062306a36Sopenharmony_ci xfs_extlen_t len, /* length of extent */ 18162306a36Sopenharmony_ci int *stat) /* success/failure */ 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci int error; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci cur->bc_rec.a.ar_startblock = bno; 18662306a36Sopenharmony_ci cur->bc_rec.a.ar_blockcount = len; 18762306a36Sopenharmony_ci error = xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); 18862306a36Sopenharmony_ci cur->bc_ag.abt.active = (*stat == 1); 18962306a36Sopenharmony_ci return error; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci/* 19362306a36Sopenharmony_ci * Lookup the first record less than or equal to [bno, len] 19462306a36Sopenharmony_ci * in the btree given by cur. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_ciint /* error */ 19762306a36Sopenharmony_cixfs_alloc_lookup_le( 19862306a36Sopenharmony_ci struct xfs_btree_cur *cur, /* btree cursor */ 19962306a36Sopenharmony_ci xfs_agblock_t bno, /* starting block of extent */ 20062306a36Sopenharmony_ci xfs_extlen_t len, /* length of extent */ 20162306a36Sopenharmony_ci int *stat) /* success/failure */ 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci int error; 20462306a36Sopenharmony_ci cur->bc_rec.a.ar_startblock = bno; 20562306a36Sopenharmony_ci cur->bc_rec.a.ar_blockcount = len; 20662306a36Sopenharmony_ci error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); 20762306a36Sopenharmony_ci cur->bc_ag.abt.active = (*stat == 1); 20862306a36Sopenharmony_ci return error; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic inline bool 21262306a36Sopenharmony_cixfs_alloc_cur_active( 21362306a36Sopenharmony_ci struct xfs_btree_cur *cur) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci return cur && cur->bc_ag.abt.active; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/* 21962306a36Sopenharmony_ci * Update the record referred to by cur to the value given 22062306a36Sopenharmony_ci * by [bno, len]. 22162306a36Sopenharmony_ci * This either works (return 0) or gets an EFSCORRUPTED error. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ciSTATIC int /* error */ 22462306a36Sopenharmony_cixfs_alloc_update( 22562306a36Sopenharmony_ci struct xfs_btree_cur *cur, /* btree cursor */ 22662306a36Sopenharmony_ci xfs_agblock_t bno, /* starting block of extent */ 22762306a36Sopenharmony_ci xfs_extlen_t len) /* length of extent */ 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci union xfs_btree_rec rec; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci rec.alloc.ar_startblock = cpu_to_be32(bno); 23262306a36Sopenharmony_ci rec.alloc.ar_blockcount = cpu_to_be32(len); 23362306a36Sopenharmony_ci return xfs_btree_update(cur, &rec); 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci/* Convert the ondisk btree record to its incore representation. */ 23762306a36Sopenharmony_civoid 23862306a36Sopenharmony_cixfs_alloc_btrec_to_irec( 23962306a36Sopenharmony_ci const union xfs_btree_rec *rec, 24062306a36Sopenharmony_ci struct xfs_alloc_rec_incore *irec) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci irec->ar_startblock = be32_to_cpu(rec->alloc.ar_startblock); 24362306a36Sopenharmony_ci irec->ar_blockcount = be32_to_cpu(rec->alloc.ar_blockcount); 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* Simple checks for free space records. */ 24762306a36Sopenharmony_cixfs_failaddr_t 24862306a36Sopenharmony_cixfs_alloc_check_irec( 24962306a36Sopenharmony_ci struct xfs_btree_cur *cur, 25062306a36Sopenharmony_ci const struct xfs_alloc_rec_incore *irec) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci struct xfs_perag *pag = cur->bc_ag.pag; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (irec->ar_blockcount == 0) 25562306a36Sopenharmony_ci return __this_address; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci /* check for valid extent range, including overflow */ 25862306a36Sopenharmony_ci if (!xfs_verify_agbext(pag, irec->ar_startblock, irec->ar_blockcount)) 25962306a36Sopenharmony_ci return __this_address; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci return NULL; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic inline int 26562306a36Sopenharmony_cixfs_alloc_complain_bad_rec( 26662306a36Sopenharmony_ci struct xfs_btree_cur *cur, 26762306a36Sopenharmony_ci xfs_failaddr_t fa, 26862306a36Sopenharmony_ci const struct xfs_alloc_rec_incore *irec) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci struct xfs_mount *mp = cur->bc_mp; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci xfs_warn(mp, 27362306a36Sopenharmony_ci "%s Freespace BTree record corruption in AG %d detected at %pS!", 27462306a36Sopenharmony_ci cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size", 27562306a36Sopenharmony_ci cur->bc_ag.pag->pag_agno, fa); 27662306a36Sopenharmony_ci xfs_warn(mp, 27762306a36Sopenharmony_ci "start block 0x%x block count 0x%x", irec->ar_startblock, 27862306a36Sopenharmony_ci irec->ar_blockcount); 27962306a36Sopenharmony_ci return -EFSCORRUPTED; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* 28362306a36Sopenharmony_ci * Get the data from the pointed-to record. 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ciint /* error */ 28662306a36Sopenharmony_cixfs_alloc_get_rec( 28762306a36Sopenharmony_ci struct xfs_btree_cur *cur, /* btree cursor */ 28862306a36Sopenharmony_ci xfs_agblock_t *bno, /* output: starting block of extent */ 28962306a36Sopenharmony_ci xfs_extlen_t *len, /* output: length of extent */ 29062306a36Sopenharmony_ci int *stat) /* output: success/failure */ 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct xfs_alloc_rec_incore irec; 29362306a36Sopenharmony_ci union xfs_btree_rec *rec; 29462306a36Sopenharmony_ci xfs_failaddr_t fa; 29562306a36Sopenharmony_ci int error; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci error = xfs_btree_get_rec(cur, &rec, stat); 29862306a36Sopenharmony_ci if (error || !(*stat)) 29962306a36Sopenharmony_ci return error; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci xfs_alloc_btrec_to_irec(rec, &irec); 30262306a36Sopenharmony_ci fa = xfs_alloc_check_irec(cur, &irec); 30362306a36Sopenharmony_ci if (fa) 30462306a36Sopenharmony_ci return xfs_alloc_complain_bad_rec(cur, fa, &irec); 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci *bno = irec.ar_startblock; 30762306a36Sopenharmony_ci *len = irec.ar_blockcount; 30862306a36Sopenharmony_ci return 0; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/* 31262306a36Sopenharmony_ci * Compute aligned version of the found extent. 31362306a36Sopenharmony_ci * Takes alignment and min length into account. 31462306a36Sopenharmony_ci */ 31562306a36Sopenharmony_ciSTATIC bool 31662306a36Sopenharmony_cixfs_alloc_compute_aligned( 31762306a36Sopenharmony_ci xfs_alloc_arg_t *args, /* allocation argument structure */ 31862306a36Sopenharmony_ci xfs_agblock_t foundbno, /* starting block in found extent */ 31962306a36Sopenharmony_ci xfs_extlen_t foundlen, /* length in found extent */ 32062306a36Sopenharmony_ci xfs_agblock_t *resbno, /* result block number */ 32162306a36Sopenharmony_ci xfs_extlen_t *reslen, /* result length */ 32262306a36Sopenharmony_ci unsigned *busy_gen) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci xfs_agblock_t bno = foundbno; 32562306a36Sopenharmony_ci xfs_extlen_t len = foundlen; 32662306a36Sopenharmony_ci xfs_extlen_t diff; 32762306a36Sopenharmony_ci bool busy; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* Trim busy sections out of found extent */ 33062306a36Sopenharmony_ci busy = xfs_extent_busy_trim(args, &bno, &len, busy_gen); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci /* 33362306a36Sopenharmony_ci * If we have a largish extent that happens to start before min_agbno, 33462306a36Sopenharmony_ci * see if we can shift it into range... 33562306a36Sopenharmony_ci */ 33662306a36Sopenharmony_ci if (bno < args->min_agbno && bno + len > args->min_agbno) { 33762306a36Sopenharmony_ci diff = args->min_agbno - bno; 33862306a36Sopenharmony_ci if (len > diff) { 33962306a36Sopenharmony_ci bno += diff; 34062306a36Sopenharmony_ci len -= diff; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci if (args->alignment > 1 && len >= args->minlen) { 34562306a36Sopenharmony_ci xfs_agblock_t aligned_bno = roundup(bno, args->alignment); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci diff = aligned_bno - bno; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci *resbno = aligned_bno; 35062306a36Sopenharmony_ci *reslen = diff >= len ? 0 : len - diff; 35162306a36Sopenharmony_ci } else { 35262306a36Sopenharmony_ci *resbno = bno; 35362306a36Sopenharmony_ci *reslen = len; 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return busy; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci/* 36062306a36Sopenharmony_ci * Compute best start block and diff for "near" allocations. 36162306a36Sopenharmony_ci * freelen >= wantlen already checked by caller. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_ciSTATIC xfs_extlen_t /* difference value (absolute) */ 36462306a36Sopenharmony_cixfs_alloc_compute_diff( 36562306a36Sopenharmony_ci xfs_agblock_t wantbno, /* target starting block */ 36662306a36Sopenharmony_ci xfs_extlen_t wantlen, /* target length */ 36762306a36Sopenharmony_ci xfs_extlen_t alignment, /* target alignment */ 36862306a36Sopenharmony_ci int datatype, /* are we allocating data? */ 36962306a36Sopenharmony_ci xfs_agblock_t freebno, /* freespace's starting block */ 37062306a36Sopenharmony_ci xfs_extlen_t freelen, /* freespace's length */ 37162306a36Sopenharmony_ci xfs_agblock_t *newbnop) /* result: best start block from free */ 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci xfs_agblock_t freeend; /* end of freespace extent */ 37462306a36Sopenharmony_ci xfs_agblock_t newbno1; /* return block number */ 37562306a36Sopenharmony_ci xfs_agblock_t newbno2; /* other new block number */ 37662306a36Sopenharmony_ci xfs_extlen_t newlen1=0; /* length with newbno1 */ 37762306a36Sopenharmony_ci xfs_extlen_t newlen2=0; /* length with newbno2 */ 37862306a36Sopenharmony_ci xfs_agblock_t wantend; /* end of target extent */ 37962306a36Sopenharmony_ci bool userdata = datatype & XFS_ALLOC_USERDATA; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci ASSERT(freelen >= wantlen); 38262306a36Sopenharmony_ci freeend = freebno + freelen; 38362306a36Sopenharmony_ci wantend = wantbno + wantlen; 38462306a36Sopenharmony_ci /* 38562306a36Sopenharmony_ci * We want to allocate from the start of a free extent if it is past 38662306a36Sopenharmony_ci * the desired block or if we are allocating user data and the free 38762306a36Sopenharmony_ci * extent is before desired block. The second case is there to allow 38862306a36Sopenharmony_ci * for contiguous allocation from the remaining free space if the file 38962306a36Sopenharmony_ci * grows in the short term. 39062306a36Sopenharmony_ci */ 39162306a36Sopenharmony_ci if (freebno >= wantbno || (userdata && freeend < wantend)) { 39262306a36Sopenharmony_ci if ((newbno1 = roundup(freebno, alignment)) >= freeend) 39362306a36Sopenharmony_ci newbno1 = NULLAGBLOCK; 39462306a36Sopenharmony_ci } else if (freeend >= wantend && alignment > 1) { 39562306a36Sopenharmony_ci newbno1 = roundup(wantbno, alignment); 39662306a36Sopenharmony_ci newbno2 = newbno1 - alignment; 39762306a36Sopenharmony_ci if (newbno1 >= freeend) 39862306a36Sopenharmony_ci newbno1 = NULLAGBLOCK; 39962306a36Sopenharmony_ci else 40062306a36Sopenharmony_ci newlen1 = XFS_EXTLEN_MIN(wantlen, freeend - newbno1); 40162306a36Sopenharmony_ci if (newbno2 < freebno) 40262306a36Sopenharmony_ci newbno2 = NULLAGBLOCK; 40362306a36Sopenharmony_ci else 40462306a36Sopenharmony_ci newlen2 = XFS_EXTLEN_MIN(wantlen, freeend - newbno2); 40562306a36Sopenharmony_ci if (newbno1 != NULLAGBLOCK && newbno2 != NULLAGBLOCK) { 40662306a36Sopenharmony_ci if (newlen1 < newlen2 || 40762306a36Sopenharmony_ci (newlen1 == newlen2 && 40862306a36Sopenharmony_ci XFS_ABSDIFF(newbno1, wantbno) > 40962306a36Sopenharmony_ci XFS_ABSDIFF(newbno2, wantbno))) 41062306a36Sopenharmony_ci newbno1 = newbno2; 41162306a36Sopenharmony_ci } else if (newbno2 != NULLAGBLOCK) 41262306a36Sopenharmony_ci newbno1 = newbno2; 41362306a36Sopenharmony_ci } else if (freeend >= wantend) { 41462306a36Sopenharmony_ci newbno1 = wantbno; 41562306a36Sopenharmony_ci } else if (alignment > 1) { 41662306a36Sopenharmony_ci newbno1 = roundup(freeend - wantlen, alignment); 41762306a36Sopenharmony_ci if (newbno1 > freeend - wantlen && 41862306a36Sopenharmony_ci newbno1 - alignment >= freebno) 41962306a36Sopenharmony_ci newbno1 -= alignment; 42062306a36Sopenharmony_ci else if (newbno1 >= freeend) 42162306a36Sopenharmony_ci newbno1 = NULLAGBLOCK; 42262306a36Sopenharmony_ci } else 42362306a36Sopenharmony_ci newbno1 = freeend - wantlen; 42462306a36Sopenharmony_ci *newbnop = newbno1; 42562306a36Sopenharmony_ci return newbno1 == NULLAGBLOCK ? 0 : XFS_ABSDIFF(newbno1, wantbno); 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci/* 42962306a36Sopenharmony_ci * Fix up the length, based on mod and prod. 43062306a36Sopenharmony_ci * len should be k * prod + mod for some k. 43162306a36Sopenharmony_ci * If len is too small it is returned unchanged. 43262306a36Sopenharmony_ci * If len hits maxlen it is left alone. 43362306a36Sopenharmony_ci */ 43462306a36Sopenharmony_ciSTATIC void 43562306a36Sopenharmony_cixfs_alloc_fix_len( 43662306a36Sopenharmony_ci xfs_alloc_arg_t *args) /* allocation argument structure */ 43762306a36Sopenharmony_ci{ 43862306a36Sopenharmony_ci xfs_extlen_t k; 43962306a36Sopenharmony_ci xfs_extlen_t rlen; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci ASSERT(args->mod < args->prod); 44262306a36Sopenharmony_ci rlen = args->len; 44362306a36Sopenharmony_ci ASSERT(rlen >= args->minlen); 44462306a36Sopenharmony_ci ASSERT(rlen <= args->maxlen); 44562306a36Sopenharmony_ci if (args->prod <= 1 || rlen < args->mod || rlen == args->maxlen || 44662306a36Sopenharmony_ci (args->mod == 0 && rlen < args->prod)) 44762306a36Sopenharmony_ci return; 44862306a36Sopenharmony_ci k = rlen % args->prod; 44962306a36Sopenharmony_ci if (k == args->mod) 45062306a36Sopenharmony_ci return; 45162306a36Sopenharmony_ci if (k > args->mod) 45262306a36Sopenharmony_ci rlen = rlen - (k - args->mod); 45362306a36Sopenharmony_ci else 45462306a36Sopenharmony_ci rlen = rlen - args->prod + (args->mod - k); 45562306a36Sopenharmony_ci /* casts to (int) catch length underflows */ 45662306a36Sopenharmony_ci if ((int)rlen < (int)args->minlen) 45762306a36Sopenharmony_ci return; 45862306a36Sopenharmony_ci ASSERT(rlen >= args->minlen && rlen <= args->maxlen); 45962306a36Sopenharmony_ci ASSERT(rlen % args->prod == args->mod); 46062306a36Sopenharmony_ci ASSERT(args->pag->pagf_freeblks + args->pag->pagf_flcount >= 46162306a36Sopenharmony_ci rlen + args->minleft); 46262306a36Sopenharmony_ci args->len = rlen; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/* 46662306a36Sopenharmony_ci * Update the two btrees, logically removing from freespace the extent 46762306a36Sopenharmony_ci * starting at rbno, rlen blocks. The extent is contained within the 46862306a36Sopenharmony_ci * actual (current) free extent fbno for flen blocks. 46962306a36Sopenharmony_ci * Flags are passed in indicating whether the cursors are set to the 47062306a36Sopenharmony_ci * relevant records. 47162306a36Sopenharmony_ci */ 47262306a36Sopenharmony_ciSTATIC int /* error code */ 47362306a36Sopenharmony_cixfs_alloc_fixup_trees( 47462306a36Sopenharmony_ci struct xfs_btree_cur *cnt_cur, /* cursor for by-size btree */ 47562306a36Sopenharmony_ci struct xfs_btree_cur *bno_cur, /* cursor for by-block btree */ 47662306a36Sopenharmony_ci xfs_agblock_t fbno, /* starting block of free extent */ 47762306a36Sopenharmony_ci xfs_extlen_t flen, /* length of free extent */ 47862306a36Sopenharmony_ci xfs_agblock_t rbno, /* starting block of returned extent */ 47962306a36Sopenharmony_ci xfs_extlen_t rlen, /* length of returned extent */ 48062306a36Sopenharmony_ci int flags) /* flags, XFSA_FIXUP_... */ 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci int error; /* error code */ 48362306a36Sopenharmony_ci int i; /* operation results */ 48462306a36Sopenharmony_ci xfs_agblock_t nfbno1; /* first new free startblock */ 48562306a36Sopenharmony_ci xfs_agblock_t nfbno2; /* second new free startblock */ 48662306a36Sopenharmony_ci xfs_extlen_t nflen1=0; /* first new free length */ 48762306a36Sopenharmony_ci xfs_extlen_t nflen2=0; /* second new free length */ 48862306a36Sopenharmony_ci struct xfs_mount *mp; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci mp = cnt_cur->bc_mp; 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci /* 49362306a36Sopenharmony_ci * Look up the record in the by-size tree if necessary. 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_ci if (flags & XFSA_FIXUP_CNT_OK) { 49662306a36Sopenharmony_ci#ifdef DEBUG 49762306a36Sopenharmony_ci if ((error = xfs_alloc_get_rec(cnt_cur, &nfbno1, &nflen1, &i))) 49862306a36Sopenharmony_ci return error; 49962306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, 50062306a36Sopenharmony_ci i != 1 || 50162306a36Sopenharmony_ci nfbno1 != fbno || 50262306a36Sopenharmony_ci nflen1 != flen)) 50362306a36Sopenharmony_ci return -EFSCORRUPTED; 50462306a36Sopenharmony_ci#endif 50562306a36Sopenharmony_ci } else { 50662306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, fbno, flen, &i))) 50762306a36Sopenharmony_ci return error; 50862306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) 50962306a36Sopenharmony_ci return -EFSCORRUPTED; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci /* 51262306a36Sopenharmony_ci * Look up the record in the by-block tree if necessary. 51362306a36Sopenharmony_ci */ 51462306a36Sopenharmony_ci if (flags & XFSA_FIXUP_BNO_OK) { 51562306a36Sopenharmony_ci#ifdef DEBUG 51662306a36Sopenharmony_ci if ((error = xfs_alloc_get_rec(bno_cur, &nfbno1, &nflen1, &i))) 51762306a36Sopenharmony_ci return error; 51862306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, 51962306a36Sopenharmony_ci i != 1 || 52062306a36Sopenharmony_ci nfbno1 != fbno || 52162306a36Sopenharmony_ci nflen1 != flen)) 52262306a36Sopenharmony_ci return -EFSCORRUPTED; 52362306a36Sopenharmony_ci#endif 52462306a36Sopenharmony_ci } else { 52562306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(bno_cur, fbno, flen, &i))) 52662306a36Sopenharmony_ci return error; 52762306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) 52862306a36Sopenharmony_ci return -EFSCORRUPTED; 52962306a36Sopenharmony_ci } 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci#ifdef DEBUG 53262306a36Sopenharmony_ci if (bno_cur->bc_nlevels == 1 && cnt_cur->bc_nlevels == 1) { 53362306a36Sopenharmony_ci struct xfs_btree_block *bnoblock; 53462306a36Sopenharmony_ci struct xfs_btree_block *cntblock; 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci bnoblock = XFS_BUF_TO_BLOCK(bno_cur->bc_levels[0].bp); 53762306a36Sopenharmony_ci cntblock = XFS_BUF_TO_BLOCK(cnt_cur->bc_levels[0].bp); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, 54062306a36Sopenharmony_ci bnoblock->bb_numrecs != 54162306a36Sopenharmony_ci cntblock->bb_numrecs)) 54262306a36Sopenharmony_ci return -EFSCORRUPTED; 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci#endif 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci /* 54762306a36Sopenharmony_ci * Deal with all four cases: the allocated record is contained 54862306a36Sopenharmony_ci * within the freespace record, so we can have new freespace 54962306a36Sopenharmony_ci * at either (or both) end, or no freespace remaining. 55062306a36Sopenharmony_ci */ 55162306a36Sopenharmony_ci if (rbno == fbno && rlen == flen) 55262306a36Sopenharmony_ci nfbno1 = nfbno2 = NULLAGBLOCK; 55362306a36Sopenharmony_ci else if (rbno == fbno) { 55462306a36Sopenharmony_ci nfbno1 = rbno + rlen; 55562306a36Sopenharmony_ci nflen1 = flen - rlen; 55662306a36Sopenharmony_ci nfbno2 = NULLAGBLOCK; 55762306a36Sopenharmony_ci } else if (rbno + rlen == fbno + flen) { 55862306a36Sopenharmony_ci nfbno1 = fbno; 55962306a36Sopenharmony_ci nflen1 = flen - rlen; 56062306a36Sopenharmony_ci nfbno2 = NULLAGBLOCK; 56162306a36Sopenharmony_ci } else { 56262306a36Sopenharmony_ci nfbno1 = fbno; 56362306a36Sopenharmony_ci nflen1 = rbno - fbno; 56462306a36Sopenharmony_ci nfbno2 = rbno + rlen; 56562306a36Sopenharmony_ci nflen2 = (fbno + flen) - nfbno2; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci /* 56862306a36Sopenharmony_ci * Delete the entry from the by-size btree. 56962306a36Sopenharmony_ci */ 57062306a36Sopenharmony_ci if ((error = xfs_btree_delete(cnt_cur, &i))) 57162306a36Sopenharmony_ci return error; 57262306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) 57362306a36Sopenharmony_ci return -EFSCORRUPTED; 57462306a36Sopenharmony_ci /* 57562306a36Sopenharmony_ci * Add new by-size btree entry(s). 57662306a36Sopenharmony_ci */ 57762306a36Sopenharmony_ci if (nfbno1 != NULLAGBLOCK) { 57862306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno1, nflen1, &i))) 57962306a36Sopenharmony_ci return error; 58062306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 0)) 58162306a36Sopenharmony_ci return -EFSCORRUPTED; 58262306a36Sopenharmony_ci if ((error = xfs_btree_insert(cnt_cur, &i))) 58362306a36Sopenharmony_ci return error; 58462306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) 58562306a36Sopenharmony_ci return -EFSCORRUPTED; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci if (nfbno2 != NULLAGBLOCK) { 58862306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, nfbno2, nflen2, &i))) 58962306a36Sopenharmony_ci return error; 59062306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 0)) 59162306a36Sopenharmony_ci return -EFSCORRUPTED; 59262306a36Sopenharmony_ci if ((error = xfs_btree_insert(cnt_cur, &i))) 59362306a36Sopenharmony_ci return error; 59462306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) 59562306a36Sopenharmony_ci return -EFSCORRUPTED; 59662306a36Sopenharmony_ci } 59762306a36Sopenharmony_ci /* 59862306a36Sopenharmony_ci * Fix up the by-block btree entry(s). 59962306a36Sopenharmony_ci */ 60062306a36Sopenharmony_ci if (nfbno1 == NULLAGBLOCK) { 60162306a36Sopenharmony_ci /* 60262306a36Sopenharmony_ci * No remaining freespace, just delete the by-block tree entry. 60362306a36Sopenharmony_ci */ 60462306a36Sopenharmony_ci if ((error = xfs_btree_delete(bno_cur, &i))) 60562306a36Sopenharmony_ci return error; 60662306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) 60762306a36Sopenharmony_ci return -EFSCORRUPTED; 60862306a36Sopenharmony_ci } else { 60962306a36Sopenharmony_ci /* 61062306a36Sopenharmony_ci * Update the by-block entry to start later|be shorter. 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_ci if ((error = xfs_alloc_update(bno_cur, nfbno1, nflen1))) 61362306a36Sopenharmony_ci return error; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci if (nfbno2 != NULLAGBLOCK) { 61662306a36Sopenharmony_ci /* 61762306a36Sopenharmony_ci * 2 resulting free entries, need to add one. 61862306a36Sopenharmony_ci */ 61962306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(bno_cur, nfbno2, nflen2, &i))) 62062306a36Sopenharmony_ci return error; 62162306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 0)) 62262306a36Sopenharmony_ci return -EFSCORRUPTED; 62362306a36Sopenharmony_ci if ((error = xfs_btree_insert(bno_cur, &i))) 62462306a36Sopenharmony_ci return error; 62562306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) 62662306a36Sopenharmony_ci return -EFSCORRUPTED; 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci return 0; 62962306a36Sopenharmony_ci} 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci/* 63262306a36Sopenharmony_ci * We do not verify the AGFL contents against AGF-based index counters here, 63362306a36Sopenharmony_ci * even though we may have access to the perag that contains shadow copies. We 63462306a36Sopenharmony_ci * don't know if the AGF based counters have been checked, and if they have they 63562306a36Sopenharmony_ci * still may be inconsistent because they haven't yet been reset on the first 63662306a36Sopenharmony_ci * allocation after the AGF has been read in. 63762306a36Sopenharmony_ci * 63862306a36Sopenharmony_ci * This means we can only check that all agfl entries contain valid or null 63962306a36Sopenharmony_ci * values because we can't reliably determine the active range to exclude 64062306a36Sopenharmony_ci * NULLAGBNO as a valid value. 64162306a36Sopenharmony_ci * 64262306a36Sopenharmony_ci * However, we can't even do that for v4 format filesystems because there are 64362306a36Sopenharmony_ci * old versions of mkfs out there that does not initialise the AGFL to known, 64462306a36Sopenharmony_ci * verifiable values. HEnce we can't tell the difference between a AGFL block 64562306a36Sopenharmony_ci * allocated by mkfs and a corrupted AGFL block here on v4 filesystems. 64662306a36Sopenharmony_ci * 64762306a36Sopenharmony_ci * As a result, we can only fully validate AGFL block numbers when we pull them 64862306a36Sopenharmony_ci * from the freelist in xfs_alloc_get_freelist(). 64962306a36Sopenharmony_ci */ 65062306a36Sopenharmony_cistatic xfs_failaddr_t 65162306a36Sopenharmony_cixfs_agfl_verify( 65262306a36Sopenharmony_ci struct xfs_buf *bp) 65362306a36Sopenharmony_ci{ 65462306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 65562306a36Sopenharmony_ci struct xfs_agfl *agfl = XFS_BUF_TO_AGFL(bp); 65662306a36Sopenharmony_ci __be32 *agfl_bno = xfs_buf_to_agfl_bno(bp); 65762306a36Sopenharmony_ci int i; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci if (!xfs_has_crc(mp)) 66062306a36Sopenharmony_ci return NULL; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci if (!xfs_verify_magic(bp, agfl->agfl_magicnum)) 66362306a36Sopenharmony_ci return __this_address; 66462306a36Sopenharmony_ci if (!uuid_equal(&agfl->agfl_uuid, &mp->m_sb.sb_meta_uuid)) 66562306a36Sopenharmony_ci return __this_address; 66662306a36Sopenharmony_ci /* 66762306a36Sopenharmony_ci * during growfs operations, the perag is not fully initialised, 66862306a36Sopenharmony_ci * so we can't use it for any useful checking. growfs ensures we can't 66962306a36Sopenharmony_ci * use it by using uncached buffers that don't have the perag attached 67062306a36Sopenharmony_ci * so we can detect and avoid this problem. 67162306a36Sopenharmony_ci */ 67262306a36Sopenharmony_ci if (bp->b_pag && be32_to_cpu(agfl->agfl_seqno) != bp->b_pag->pag_agno) 67362306a36Sopenharmony_ci return __this_address; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci for (i = 0; i < xfs_agfl_size(mp); i++) { 67662306a36Sopenharmony_ci if (be32_to_cpu(agfl_bno[i]) != NULLAGBLOCK && 67762306a36Sopenharmony_ci be32_to_cpu(agfl_bno[i]) >= mp->m_sb.sb_agblocks) 67862306a36Sopenharmony_ci return __this_address; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci if (!xfs_log_check_lsn(mp, be64_to_cpu(XFS_BUF_TO_AGFL(bp)->agfl_lsn))) 68262306a36Sopenharmony_ci return __this_address; 68362306a36Sopenharmony_ci return NULL; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic void 68762306a36Sopenharmony_cixfs_agfl_read_verify( 68862306a36Sopenharmony_ci struct xfs_buf *bp) 68962306a36Sopenharmony_ci{ 69062306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 69162306a36Sopenharmony_ci xfs_failaddr_t fa; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* 69462306a36Sopenharmony_ci * There is no verification of non-crc AGFLs because mkfs does not 69562306a36Sopenharmony_ci * initialise the AGFL to zero or NULL. Hence the only valid part of the 69662306a36Sopenharmony_ci * AGFL is what the AGF says is active. We can't get to the AGF, so we 69762306a36Sopenharmony_ci * can't verify just those entries are valid. 69862306a36Sopenharmony_ci */ 69962306a36Sopenharmony_ci if (!xfs_has_crc(mp)) 70062306a36Sopenharmony_ci return; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci if (!xfs_buf_verify_cksum(bp, XFS_AGFL_CRC_OFF)) 70362306a36Sopenharmony_ci xfs_verifier_error(bp, -EFSBADCRC, __this_address); 70462306a36Sopenharmony_ci else { 70562306a36Sopenharmony_ci fa = xfs_agfl_verify(bp); 70662306a36Sopenharmony_ci if (fa) 70762306a36Sopenharmony_ci xfs_verifier_error(bp, -EFSCORRUPTED, fa); 70862306a36Sopenharmony_ci } 70962306a36Sopenharmony_ci} 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_cistatic void 71262306a36Sopenharmony_cixfs_agfl_write_verify( 71362306a36Sopenharmony_ci struct xfs_buf *bp) 71462306a36Sopenharmony_ci{ 71562306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 71662306a36Sopenharmony_ci struct xfs_buf_log_item *bip = bp->b_log_item; 71762306a36Sopenharmony_ci xfs_failaddr_t fa; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* no verification of non-crc AGFLs */ 72062306a36Sopenharmony_ci if (!xfs_has_crc(mp)) 72162306a36Sopenharmony_ci return; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci fa = xfs_agfl_verify(bp); 72462306a36Sopenharmony_ci if (fa) { 72562306a36Sopenharmony_ci xfs_verifier_error(bp, -EFSCORRUPTED, fa); 72662306a36Sopenharmony_ci return; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci if (bip) 73062306a36Sopenharmony_ci XFS_BUF_TO_AGFL(bp)->agfl_lsn = cpu_to_be64(bip->bli_item.li_lsn); 73162306a36Sopenharmony_ci 73262306a36Sopenharmony_ci xfs_buf_update_cksum(bp, XFS_AGFL_CRC_OFF); 73362306a36Sopenharmony_ci} 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ciconst struct xfs_buf_ops xfs_agfl_buf_ops = { 73662306a36Sopenharmony_ci .name = "xfs_agfl", 73762306a36Sopenharmony_ci .magic = { cpu_to_be32(XFS_AGFL_MAGIC), cpu_to_be32(XFS_AGFL_MAGIC) }, 73862306a36Sopenharmony_ci .verify_read = xfs_agfl_read_verify, 73962306a36Sopenharmony_ci .verify_write = xfs_agfl_write_verify, 74062306a36Sopenharmony_ci .verify_struct = xfs_agfl_verify, 74162306a36Sopenharmony_ci}; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci/* 74462306a36Sopenharmony_ci * Read in the allocation group free block array. 74562306a36Sopenharmony_ci */ 74662306a36Sopenharmony_ciint 74762306a36Sopenharmony_cixfs_alloc_read_agfl( 74862306a36Sopenharmony_ci struct xfs_perag *pag, 74962306a36Sopenharmony_ci struct xfs_trans *tp, 75062306a36Sopenharmony_ci struct xfs_buf **bpp) 75162306a36Sopenharmony_ci{ 75262306a36Sopenharmony_ci struct xfs_mount *mp = pag->pag_mount; 75362306a36Sopenharmony_ci struct xfs_buf *bp; 75462306a36Sopenharmony_ci int error; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci error = xfs_trans_read_buf( 75762306a36Sopenharmony_ci mp, tp, mp->m_ddev_targp, 75862306a36Sopenharmony_ci XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGFL_DADDR(mp)), 75962306a36Sopenharmony_ci XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_agfl_buf_ops); 76062306a36Sopenharmony_ci if (error) 76162306a36Sopenharmony_ci return error; 76262306a36Sopenharmony_ci xfs_buf_set_ref(bp, XFS_AGFL_REF); 76362306a36Sopenharmony_ci *bpp = bp; 76462306a36Sopenharmony_ci return 0; 76562306a36Sopenharmony_ci} 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ciSTATIC int 76862306a36Sopenharmony_cixfs_alloc_update_counters( 76962306a36Sopenharmony_ci struct xfs_trans *tp, 77062306a36Sopenharmony_ci struct xfs_buf *agbp, 77162306a36Sopenharmony_ci long len) 77262306a36Sopenharmony_ci{ 77362306a36Sopenharmony_ci struct xfs_agf *agf = agbp->b_addr; 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_ci agbp->b_pag->pagf_freeblks += len; 77662306a36Sopenharmony_ci be32_add_cpu(&agf->agf_freeblks, len); 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci if (unlikely(be32_to_cpu(agf->agf_freeblks) > 77962306a36Sopenharmony_ci be32_to_cpu(agf->agf_length))) { 78062306a36Sopenharmony_ci xfs_buf_mark_corrupt(agbp); 78162306a36Sopenharmony_ci return -EFSCORRUPTED; 78262306a36Sopenharmony_ci } 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); 78562306a36Sopenharmony_ci return 0; 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci/* 78962306a36Sopenharmony_ci * Block allocation algorithm and data structures. 79062306a36Sopenharmony_ci */ 79162306a36Sopenharmony_cistruct xfs_alloc_cur { 79262306a36Sopenharmony_ci struct xfs_btree_cur *cnt; /* btree cursors */ 79362306a36Sopenharmony_ci struct xfs_btree_cur *bnolt; 79462306a36Sopenharmony_ci struct xfs_btree_cur *bnogt; 79562306a36Sopenharmony_ci xfs_extlen_t cur_len;/* current search length */ 79662306a36Sopenharmony_ci xfs_agblock_t rec_bno;/* extent startblock */ 79762306a36Sopenharmony_ci xfs_extlen_t rec_len;/* extent length */ 79862306a36Sopenharmony_ci xfs_agblock_t bno; /* alloc bno */ 79962306a36Sopenharmony_ci xfs_extlen_t len; /* alloc len */ 80062306a36Sopenharmony_ci xfs_extlen_t diff; /* diff from search bno */ 80162306a36Sopenharmony_ci unsigned int busy_gen;/* busy state */ 80262306a36Sopenharmony_ci bool busy; 80362306a36Sopenharmony_ci}; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci/* 80662306a36Sopenharmony_ci * Set up cursors, etc. in the extent allocation cursor. This function can be 80762306a36Sopenharmony_ci * called multiple times to reset an initialized structure without having to 80862306a36Sopenharmony_ci * reallocate cursors. 80962306a36Sopenharmony_ci */ 81062306a36Sopenharmony_cistatic int 81162306a36Sopenharmony_cixfs_alloc_cur_setup( 81262306a36Sopenharmony_ci struct xfs_alloc_arg *args, 81362306a36Sopenharmony_ci struct xfs_alloc_cur *acur) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci int error; 81662306a36Sopenharmony_ci int i; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci acur->cur_len = args->maxlen; 81962306a36Sopenharmony_ci acur->rec_bno = 0; 82062306a36Sopenharmony_ci acur->rec_len = 0; 82162306a36Sopenharmony_ci acur->bno = 0; 82262306a36Sopenharmony_ci acur->len = 0; 82362306a36Sopenharmony_ci acur->diff = -1; 82462306a36Sopenharmony_ci acur->busy = false; 82562306a36Sopenharmony_ci acur->busy_gen = 0; 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci /* 82862306a36Sopenharmony_ci * Perform an initial cntbt lookup to check for availability of maxlen 82962306a36Sopenharmony_ci * extents. If this fails, we'll return -ENOSPC to signal the caller to 83062306a36Sopenharmony_ci * attempt a small allocation. 83162306a36Sopenharmony_ci */ 83262306a36Sopenharmony_ci if (!acur->cnt) 83362306a36Sopenharmony_ci acur->cnt = xfs_allocbt_init_cursor(args->mp, args->tp, 83462306a36Sopenharmony_ci args->agbp, args->pag, XFS_BTNUM_CNT); 83562306a36Sopenharmony_ci error = xfs_alloc_lookup_ge(acur->cnt, 0, args->maxlen, &i); 83662306a36Sopenharmony_ci if (error) 83762306a36Sopenharmony_ci return error; 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci /* 84062306a36Sopenharmony_ci * Allocate the bnobt left and right search cursors. 84162306a36Sopenharmony_ci */ 84262306a36Sopenharmony_ci if (!acur->bnolt) 84362306a36Sopenharmony_ci acur->bnolt = xfs_allocbt_init_cursor(args->mp, args->tp, 84462306a36Sopenharmony_ci args->agbp, args->pag, XFS_BTNUM_BNO); 84562306a36Sopenharmony_ci if (!acur->bnogt) 84662306a36Sopenharmony_ci acur->bnogt = xfs_allocbt_init_cursor(args->mp, args->tp, 84762306a36Sopenharmony_ci args->agbp, args->pag, XFS_BTNUM_BNO); 84862306a36Sopenharmony_ci return i == 1 ? 0 : -ENOSPC; 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_cistatic void 85262306a36Sopenharmony_cixfs_alloc_cur_close( 85362306a36Sopenharmony_ci struct xfs_alloc_cur *acur, 85462306a36Sopenharmony_ci bool error) 85562306a36Sopenharmony_ci{ 85662306a36Sopenharmony_ci int cur_error = XFS_BTREE_NOERROR; 85762306a36Sopenharmony_ci 85862306a36Sopenharmony_ci if (error) 85962306a36Sopenharmony_ci cur_error = XFS_BTREE_ERROR; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci if (acur->cnt) 86262306a36Sopenharmony_ci xfs_btree_del_cursor(acur->cnt, cur_error); 86362306a36Sopenharmony_ci if (acur->bnolt) 86462306a36Sopenharmony_ci xfs_btree_del_cursor(acur->bnolt, cur_error); 86562306a36Sopenharmony_ci if (acur->bnogt) 86662306a36Sopenharmony_ci xfs_btree_del_cursor(acur->bnogt, cur_error); 86762306a36Sopenharmony_ci acur->cnt = acur->bnolt = acur->bnogt = NULL; 86862306a36Sopenharmony_ci} 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci/* 87162306a36Sopenharmony_ci * Check an extent for allocation and track the best available candidate in the 87262306a36Sopenharmony_ci * allocation structure. The cursor is deactivated if it has entered an out of 87362306a36Sopenharmony_ci * range state based on allocation arguments. Optionally return the extent 87462306a36Sopenharmony_ci * extent geometry and allocation status if requested by the caller. 87562306a36Sopenharmony_ci */ 87662306a36Sopenharmony_cistatic int 87762306a36Sopenharmony_cixfs_alloc_cur_check( 87862306a36Sopenharmony_ci struct xfs_alloc_arg *args, 87962306a36Sopenharmony_ci struct xfs_alloc_cur *acur, 88062306a36Sopenharmony_ci struct xfs_btree_cur *cur, 88162306a36Sopenharmony_ci int *new) 88262306a36Sopenharmony_ci{ 88362306a36Sopenharmony_ci int error, i; 88462306a36Sopenharmony_ci xfs_agblock_t bno, bnoa, bnew; 88562306a36Sopenharmony_ci xfs_extlen_t len, lena, diff = -1; 88662306a36Sopenharmony_ci bool busy; 88762306a36Sopenharmony_ci unsigned busy_gen = 0; 88862306a36Sopenharmony_ci bool deactivate = false; 88962306a36Sopenharmony_ci bool isbnobt = cur->bc_btnum == XFS_BTNUM_BNO; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci *new = 0; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci error = xfs_alloc_get_rec(cur, &bno, &len, &i); 89462306a36Sopenharmony_ci if (error) 89562306a36Sopenharmony_ci return error; 89662306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, i != 1)) 89762306a36Sopenharmony_ci return -EFSCORRUPTED; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci /* 90062306a36Sopenharmony_ci * Check minlen and deactivate a cntbt cursor if out of acceptable size 90162306a36Sopenharmony_ci * range (i.e., walking backwards looking for a minlen extent). 90262306a36Sopenharmony_ci */ 90362306a36Sopenharmony_ci if (len < args->minlen) { 90462306a36Sopenharmony_ci deactivate = !isbnobt; 90562306a36Sopenharmony_ci goto out; 90662306a36Sopenharmony_ci } 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci busy = xfs_alloc_compute_aligned(args, bno, len, &bnoa, &lena, 90962306a36Sopenharmony_ci &busy_gen); 91062306a36Sopenharmony_ci acur->busy |= busy; 91162306a36Sopenharmony_ci if (busy) 91262306a36Sopenharmony_ci acur->busy_gen = busy_gen; 91362306a36Sopenharmony_ci /* deactivate a bnobt cursor outside of locality range */ 91462306a36Sopenharmony_ci if (bnoa < args->min_agbno || bnoa > args->max_agbno) { 91562306a36Sopenharmony_ci deactivate = isbnobt; 91662306a36Sopenharmony_ci goto out; 91762306a36Sopenharmony_ci } 91862306a36Sopenharmony_ci if (lena < args->minlen) 91962306a36Sopenharmony_ci goto out; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci args->len = XFS_EXTLEN_MIN(lena, args->maxlen); 92262306a36Sopenharmony_ci xfs_alloc_fix_len(args); 92362306a36Sopenharmony_ci ASSERT(args->len >= args->minlen); 92462306a36Sopenharmony_ci if (args->len < acur->len) 92562306a36Sopenharmony_ci goto out; 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci /* 92862306a36Sopenharmony_ci * We have an aligned record that satisfies minlen and beats or matches 92962306a36Sopenharmony_ci * the candidate extent size. Compare locality for near allocation mode. 93062306a36Sopenharmony_ci */ 93162306a36Sopenharmony_ci diff = xfs_alloc_compute_diff(args->agbno, args->len, 93262306a36Sopenharmony_ci args->alignment, args->datatype, 93362306a36Sopenharmony_ci bnoa, lena, &bnew); 93462306a36Sopenharmony_ci if (bnew == NULLAGBLOCK) 93562306a36Sopenharmony_ci goto out; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci /* 93862306a36Sopenharmony_ci * Deactivate a bnobt cursor with worse locality than the current best. 93962306a36Sopenharmony_ci */ 94062306a36Sopenharmony_ci if (diff > acur->diff) { 94162306a36Sopenharmony_ci deactivate = isbnobt; 94262306a36Sopenharmony_ci goto out; 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci ASSERT(args->len > acur->len || 94662306a36Sopenharmony_ci (args->len == acur->len && diff <= acur->diff)); 94762306a36Sopenharmony_ci acur->rec_bno = bno; 94862306a36Sopenharmony_ci acur->rec_len = len; 94962306a36Sopenharmony_ci acur->bno = bnew; 95062306a36Sopenharmony_ci acur->len = args->len; 95162306a36Sopenharmony_ci acur->diff = diff; 95262306a36Sopenharmony_ci *new = 1; 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci /* 95562306a36Sopenharmony_ci * We're done if we found a perfect allocation. This only deactivates 95662306a36Sopenharmony_ci * the current cursor, but this is just an optimization to terminate a 95762306a36Sopenharmony_ci * cntbt search that otherwise runs to the edge of the tree. 95862306a36Sopenharmony_ci */ 95962306a36Sopenharmony_ci if (acur->diff == 0 && acur->len == args->maxlen) 96062306a36Sopenharmony_ci deactivate = true; 96162306a36Sopenharmony_ciout: 96262306a36Sopenharmony_ci if (deactivate) 96362306a36Sopenharmony_ci cur->bc_ag.abt.active = false; 96462306a36Sopenharmony_ci trace_xfs_alloc_cur_check(args->mp, cur->bc_btnum, bno, len, diff, 96562306a36Sopenharmony_ci *new); 96662306a36Sopenharmony_ci return 0; 96762306a36Sopenharmony_ci} 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci/* 97062306a36Sopenharmony_ci * Complete an allocation of a candidate extent. Remove the extent from both 97162306a36Sopenharmony_ci * trees and update the args structure. 97262306a36Sopenharmony_ci */ 97362306a36Sopenharmony_ciSTATIC int 97462306a36Sopenharmony_cixfs_alloc_cur_finish( 97562306a36Sopenharmony_ci struct xfs_alloc_arg *args, 97662306a36Sopenharmony_ci struct xfs_alloc_cur *acur) 97762306a36Sopenharmony_ci{ 97862306a36Sopenharmony_ci struct xfs_agf __maybe_unused *agf = args->agbp->b_addr; 97962306a36Sopenharmony_ci int error; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci ASSERT(acur->cnt && acur->bnolt); 98262306a36Sopenharmony_ci ASSERT(acur->bno >= acur->rec_bno); 98362306a36Sopenharmony_ci ASSERT(acur->bno + acur->len <= acur->rec_bno + acur->rec_len); 98462306a36Sopenharmony_ci ASSERT(acur->rec_bno + acur->rec_len <= be32_to_cpu(agf->agf_length)); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci error = xfs_alloc_fixup_trees(acur->cnt, acur->bnolt, acur->rec_bno, 98762306a36Sopenharmony_ci acur->rec_len, acur->bno, acur->len, 0); 98862306a36Sopenharmony_ci if (error) 98962306a36Sopenharmony_ci return error; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci args->agbno = acur->bno; 99262306a36Sopenharmony_ci args->len = acur->len; 99362306a36Sopenharmony_ci args->wasfromfl = 0; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci trace_xfs_alloc_cur(args); 99662306a36Sopenharmony_ci return 0; 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci/* 100062306a36Sopenharmony_ci * Locality allocation lookup algorithm. This expects a cntbt cursor and uses 100162306a36Sopenharmony_ci * bno optimized lookup to search for extents with ideal size and locality. 100262306a36Sopenharmony_ci */ 100362306a36Sopenharmony_ciSTATIC int 100462306a36Sopenharmony_cixfs_alloc_cntbt_iter( 100562306a36Sopenharmony_ci struct xfs_alloc_arg *args, 100662306a36Sopenharmony_ci struct xfs_alloc_cur *acur) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci struct xfs_btree_cur *cur = acur->cnt; 100962306a36Sopenharmony_ci xfs_agblock_t bno; 101062306a36Sopenharmony_ci xfs_extlen_t len, cur_len; 101162306a36Sopenharmony_ci int error; 101262306a36Sopenharmony_ci int i; 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci if (!xfs_alloc_cur_active(cur)) 101562306a36Sopenharmony_ci return 0; 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci /* locality optimized lookup */ 101862306a36Sopenharmony_ci cur_len = acur->cur_len; 101962306a36Sopenharmony_ci error = xfs_alloc_lookup_ge(cur, args->agbno, cur_len, &i); 102062306a36Sopenharmony_ci if (error) 102162306a36Sopenharmony_ci return error; 102262306a36Sopenharmony_ci if (i == 0) 102362306a36Sopenharmony_ci return 0; 102462306a36Sopenharmony_ci error = xfs_alloc_get_rec(cur, &bno, &len, &i); 102562306a36Sopenharmony_ci if (error) 102662306a36Sopenharmony_ci return error; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci /* check the current record and update search length from it */ 102962306a36Sopenharmony_ci error = xfs_alloc_cur_check(args, acur, cur, &i); 103062306a36Sopenharmony_ci if (error) 103162306a36Sopenharmony_ci return error; 103262306a36Sopenharmony_ci ASSERT(len >= acur->cur_len); 103362306a36Sopenharmony_ci acur->cur_len = len; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci /* 103662306a36Sopenharmony_ci * We looked up the first record >= [agbno, len] above. The agbno is a 103762306a36Sopenharmony_ci * secondary key and so the current record may lie just before or after 103862306a36Sopenharmony_ci * agbno. If it is past agbno, check the previous record too so long as 103962306a36Sopenharmony_ci * the length matches as it may be closer. Don't check a smaller record 104062306a36Sopenharmony_ci * because that could deactivate our cursor. 104162306a36Sopenharmony_ci */ 104262306a36Sopenharmony_ci if (bno > args->agbno) { 104362306a36Sopenharmony_ci error = xfs_btree_decrement(cur, 0, &i); 104462306a36Sopenharmony_ci if (!error && i) { 104562306a36Sopenharmony_ci error = xfs_alloc_get_rec(cur, &bno, &len, &i); 104662306a36Sopenharmony_ci if (!error && i && len == acur->cur_len) 104762306a36Sopenharmony_ci error = xfs_alloc_cur_check(args, acur, cur, 104862306a36Sopenharmony_ci &i); 104962306a36Sopenharmony_ci } 105062306a36Sopenharmony_ci if (error) 105162306a36Sopenharmony_ci return error; 105262306a36Sopenharmony_ci } 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci /* 105562306a36Sopenharmony_ci * Increment the search key until we find at least one allocation 105662306a36Sopenharmony_ci * candidate or if the extent we found was larger. Otherwise, double the 105762306a36Sopenharmony_ci * search key to optimize the search. Efficiency is more important here 105862306a36Sopenharmony_ci * than absolute best locality. 105962306a36Sopenharmony_ci */ 106062306a36Sopenharmony_ci cur_len <<= 1; 106162306a36Sopenharmony_ci if (!acur->len || acur->cur_len >= cur_len) 106262306a36Sopenharmony_ci acur->cur_len++; 106362306a36Sopenharmony_ci else 106462306a36Sopenharmony_ci acur->cur_len = cur_len; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci return error; 106762306a36Sopenharmony_ci} 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci/* 107062306a36Sopenharmony_ci * Deal with the case where only small freespaces remain. Either return the 107162306a36Sopenharmony_ci * contents of the last freespace record, or allocate space from the freelist if 107262306a36Sopenharmony_ci * there is nothing in the tree. 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_ciSTATIC int /* error */ 107562306a36Sopenharmony_cixfs_alloc_ag_vextent_small( 107662306a36Sopenharmony_ci struct xfs_alloc_arg *args, /* allocation argument structure */ 107762306a36Sopenharmony_ci struct xfs_btree_cur *ccur, /* optional by-size cursor */ 107862306a36Sopenharmony_ci xfs_agblock_t *fbnop, /* result block number */ 107962306a36Sopenharmony_ci xfs_extlen_t *flenp, /* result length */ 108062306a36Sopenharmony_ci int *stat) /* status: 0-freelist, 1-normal/none */ 108162306a36Sopenharmony_ci{ 108262306a36Sopenharmony_ci struct xfs_agf *agf = args->agbp->b_addr; 108362306a36Sopenharmony_ci int error = 0; 108462306a36Sopenharmony_ci xfs_agblock_t fbno = NULLAGBLOCK; 108562306a36Sopenharmony_ci xfs_extlen_t flen = 0; 108662306a36Sopenharmony_ci int i = 0; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci /* 108962306a36Sopenharmony_ci * If a cntbt cursor is provided, try to allocate the largest record in 109062306a36Sopenharmony_ci * the tree. Try the AGFL if the cntbt is empty, otherwise fail the 109162306a36Sopenharmony_ci * allocation. Make sure to respect minleft even when pulling from the 109262306a36Sopenharmony_ci * freelist. 109362306a36Sopenharmony_ci */ 109462306a36Sopenharmony_ci if (ccur) 109562306a36Sopenharmony_ci error = xfs_btree_decrement(ccur, 0, &i); 109662306a36Sopenharmony_ci if (error) 109762306a36Sopenharmony_ci goto error; 109862306a36Sopenharmony_ci if (i) { 109962306a36Sopenharmony_ci error = xfs_alloc_get_rec(ccur, &fbno, &flen, &i); 110062306a36Sopenharmony_ci if (error) 110162306a36Sopenharmony_ci goto error; 110262306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, i != 1)) { 110362306a36Sopenharmony_ci error = -EFSCORRUPTED; 110462306a36Sopenharmony_ci goto error; 110562306a36Sopenharmony_ci } 110662306a36Sopenharmony_ci goto out; 110762306a36Sopenharmony_ci } 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci if (args->minlen != 1 || args->alignment != 1 || 111062306a36Sopenharmony_ci args->resv == XFS_AG_RESV_AGFL || 111162306a36Sopenharmony_ci be32_to_cpu(agf->agf_flcount) <= args->minleft) 111262306a36Sopenharmony_ci goto out; 111362306a36Sopenharmony_ci 111462306a36Sopenharmony_ci error = xfs_alloc_get_freelist(args->pag, args->tp, args->agbp, 111562306a36Sopenharmony_ci &fbno, 0); 111662306a36Sopenharmony_ci if (error) 111762306a36Sopenharmony_ci goto error; 111862306a36Sopenharmony_ci if (fbno == NULLAGBLOCK) 111962306a36Sopenharmony_ci goto out; 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci xfs_extent_busy_reuse(args->mp, args->pag, fbno, 1, 112262306a36Sopenharmony_ci (args->datatype & XFS_ALLOC_NOBUSY)); 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci if (args->datatype & XFS_ALLOC_USERDATA) { 112562306a36Sopenharmony_ci struct xfs_buf *bp; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci error = xfs_trans_get_buf(args->tp, args->mp->m_ddev_targp, 112862306a36Sopenharmony_ci XFS_AGB_TO_DADDR(args->mp, args->agno, fbno), 112962306a36Sopenharmony_ci args->mp->m_bsize, 0, &bp); 113062306a36Sopenharmony_ci if (error) 113162306a36Sopenharmony_ci goto error; 113262306a36Sopenharmony_ci xfs_trans_binval(args->tp, bp); 113362306a36Sopenharmony_ci } 113462306a36Sopenharmony_ci *fbnop = args->agbno = fbno; 113562306a36Sopenharmony_ci *flenp = args->len = 1; 113662306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, fbno >= be32_to_cpu(agf->agf_length))) { 113762306a36Sopenharmony_ci error = -EFSCORRUPTED; 113862306a36Sopenharmony_ci goto error; 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci args->wasfromfl = 1; 114162306a36Sopenharmony_ci trace_xfs_alloc_small_freelist(args); 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci /* 114462306a36Sopenharmony_ci * If we're feeding an AGFL block to something that doesn't live in the 114562306a36Sopenharmony_ci * free space, we need to clear out the OWN_AG rmap. 114662306a36Sopenharmony_ci */ 114762306a36Sopenharmony_ci error = xfs_rmap_free(args->tp, args->agbp, args->pag, fbno, 1, 114862306a36Sopenharmony_ci &XFS_RMAP_OINFO_AG); 114962306a36Sopenharmony_ci if (error) 115062306a36Sopenharmony_ci goto error; 115162306a36Sopenharmony_ci 115262306a36Sopenharmony_ci *stat = 0; 115362306a36Sopenharmony_ci return 0; 115462306a36Sopenharmony_ci 115562306a36Sopenharmony_ciout: 115662306a36Sopenharmony_ci /* 115762306a36Sopenharmony_ci * Can't do the allocation, give up. 115862306a36Sopenharmony_ci */ 115962306a36Sopenharmony_ci if (flen < args->minlen) { 116062306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 116162306a36Sopenharmony_ci trace_xfs_alloc_small_notenough(args); 116262306a36Sopenharmony_ci flen = 0; 116362306a36Sopenharmony_ci } 116462306a36Sopenharmony_ci *fbnop = fbno; 116562306a36Sopenharmony_ci *flenp = flen; 116662306a36Sopenharmony_ci *stat = 1; 116762306a36Sopenharmony_ci trace_xfs_alloc_small_done(args); 116862306a36Sopenharmony_ci return 0; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_cierror: 117162306a36Sopenharmony_ci trace_xfs_alloc_small_error(args); 117262306a36Sopenharmony_ci return error; 117362306a36Sopenharmony_ci} 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci/* 117662306a36Sopenharmony_ci * Allocate a variable extent at exactly agno/bno. 117762306a36Sopenharmony_ci * Extent's length (returned in *len) will be between minlen and maxlen, 117862306a36Sopenharmony_ci * and of the form k * prod + mod unless there's nothing that large. 117962306a36Sopenharmony_ci * Return the starting a.g. block (bno), or NULLAGBLOCK if we can't do it. 118062306a36Sopenharmony_ci */ 118162306a36Sopenharmony_ciSTATIC int /* error */ 118262306a36Sopenharmony_cixfs_alloc_ag_vextent_exact( 118362306a36Sopenharmony_ci xfs_alloc_arg_t *args) /* allocation argument structure */ 118462306a36Sopenharmony_ci{ 118562306a36Sopenharmony_ci struct xfs_agf __maybe_unused *agf = args->agbp->b_addr; 118662306a36Sopenharmony_ci struct xfs_btree_cur *bno_cur;/* by block-number btree cursor */ 118762306a36Sopenharmony_ci struct xfs_btree_cur *cnt_cur;/* by count btree cursor */ 118862306a36Sopenharmony_ci int error; 118962306a36Sopenharmony_ci xfs_agblock_t fbno; /* start block of found extent */ 119062306a36Sopenharmony_ci xfs_extlen_t flen; /* length of found extent */ 119162306a36Sopenharmony_ci xfs_agblock_t tbno; /* start block of busy extent */ 119262306a36Sopenharmony_ci xfs_extlen_t tlen; /* length of busy extent */ 119362306a36Sopenharmony_ci xfs_agblock_t tend; /* end block of busy extent */ 119462306a36Sopenharmony_ci int i; /* success/failure of operation */ 119562306a36Sopenharmony_ci unsigned busy_gen; 119662306a36Sopenharmony_ci 119762306a36Sopenharmony_ci ASSERT(args->alignment == 1); 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci /* 120062306a36Sopenharmony_ci * Allocate/initialize a cursor for the by-number freespace btree. 120162306a36Sopenharmony_ci */ 120262306a36Sopenharmony_ci bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, 120362306a36Sopenharmony_ci args->pag, XFS_BTNUM_BNO); 120462306a36Sopenharmony_ci 120562306a36Sopenharmony_ci /* 120662306a36Sopenharmony_ci * Lookup bno and minlen in the btree (minlen is irrelevant, really). 120762306a36Sopenharmony_ci * Look for the closest free block <= bno, it must contain bno 120862306a36Sopenharmony_ci * if any free block does. 120962306a36Sopenharmony_ci */ 121062306a36Sopenharmony_ci error = xfs_alloc_lookup_le(bno_cur, args->agbno, args->minlen, &i); 121162306a36Sopenharmony_ci if (error) 121262306a36Sopenharmony_ci goto error0; 121362306a36Sopenharmony_ci if (!i) 121462306a36Sopenharmony_ci goto not_found; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci /* 121762306a36Sopenharmony_ci * Grab the freespace record. 121862306a36Sopenharmony_ci */ 121962306a36Sopenharmony_ci error = xfs_alloc_get_rec(bno_cur, &fbno, &flen, &i); 122062306a36Sopenharmony_ci if (error) 122162306a36Sopenharmony_ci goto error0; 122262306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, i != 1)) { 122362306a36Sopenharmony_ci error = -EFSCORRUPTED; 122462306a36Sopenharmony_ci goto error0; 122562306a36Sopenharmony_ci } 122662306a36Sopenharmony_ci ASSERT(fbno <= args->agbno); 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci /* 122962306a36Sopenharmony_ci * Check for overlapping busy extents. 123062306a36Sopenharmony_ci */ 123162306a36Sopenharmony_ci tbno = fbno; 123262306a36Sopenharmony_ci tlen = flen; 123362306a36Sopenharmony_ci xfs_extent_busy_trim(args, &tbno, &tlen, &busy_gen); 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci /* 123662306a36Sopenharmony_ci * Give up if the start of the extent is busy, or the freespace isn't 123762306a36Sopenharmony_ci * long enough for the minimum request. 123862306a36Sopenharmony_ci */ 123962306a36Sopenharmony_ci if (tbno > args->agbno) 124062306a36Sopenharmony_ci goto not_found; 124162306a36Sopenharmony_ci if (tlen < args->minlen) 124262306a36Sopenharmony_ci goto not_found; 124362306a36Sopenharmony_ci tend = tbno + tlen; 124462306a36Sopenharmony_ci if (tend < args->agbno + args->minlen) 124562306a36Sopenharmony_ci goto not_found; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci /* 124862306a36Sopenharmony_ci * End of extent will be smaller of the freespace end and the 124962306a36Sopenharmony_ci * maximal requested end. 125062306a36Sopenharmony_ci * 125162306a36Sopenharmony_ci * Fix the length according to mod and prod if given. 125262306a36Sopenharmony_ci */ 125362306a36Sopenharmony_ci args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen) 125462306a36Sopenharmony_ci - args->agbno; 125562306a36Sopenharmony_ci xfs_alloc_fix_len(args); 125662306a36Sopenharmony_ci ASSERT(args->agbno + args->len <= tend); 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci /* 125962306a36Sopenharmony_ci * We are allocating agbno for args->len 126062306a36Sopenharmony_ci * Allocate/initialize a cursor for the by-size btree. 126162306a36Sopenharmony_ci */ 126262306a36Sopenharmony_ci cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, 126362306a36Sopenharmony_ci args->pag, XFS_BTNUM_CNT); 126462306a36Sopenharmony_ci ASSERT(args->agbno + args->len <= be32_to_cpu(agf->agf_length)); 126562306a36Sopenharmony_ci error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, args->agbno, 126662306a36Sopenharmony_ci args->len, XFSA_FIXUP_BNO_OK); 126762306a36Sopenharmony_ci if (error) { 126862306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); 126962306a36Sopenharmony_ci goto error0; 127062306a36Sopenharmony_ci } 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); 127362306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci args->wasfromfl = 0; 127662306a36Sopenharmony_ci trace_xfs_alloc_exact_done(args); 127762306a36Sopenharmony_ci return 0; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_cinot_found: 128062306a36Sopenharmony_ci /* Didn't find it, return null. */ 128162306a36Sopenharmony_ci xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); 128262306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 128362306a36Sopenharmony_ci trace_xfs_alloc_exact_notfound(args); 128462306a36Sopenharmony_ci return 0; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cierror0: 128762306a36Sopenharmony_ci xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); 128862306a36Sopenharmony_ci trace_xfs_alloc_exact_error(args); 128962306a36Sopenharmony_ci return error; 129062306a36Sopenharmony_ci} 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_ci/* 129362306a36Sopenharmony_ci * Search a given number of btree records in a given direction. Check each 129462306a36Sopenharmony_ci * record against the good extent we've already found. 129562306a36Sopenharmony_ci */ 129662306a36Sopenharmony_ciSTATIC int 129762306a36Sopenharmony_cixfs_alloc_walk_iter( 129862306a36Sopenharmony_ci struct xfs_alloc_arg *args, 129962306a36Sopenharmony_ci struct xfs_alloc_cur *acur, 130062306a36Sopenharmony_ci struct xfs_btree_cur *cur, 130162306a36Sopenharmony_ci bool increment, 130262306a36Sopenharmony_ci bool find_one, /* quit on first candidate */ 130362306a36Sopenharmony_ci int count, /* rec count (-1 for infinite) */ 130462306a36Sopenharmony_ci int *stat) 130562306a36Sopenharmony_ci{ 130662306a36Sopenharmony_ci int error; 130762306a36Sopenharmony_ci int i; 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci *stat = 0; 131062306a36Sopenharmony_ci 131162306a36Sopenharmony_ci /* 131262306a36Sopenharmony_ci * Search so long as the cursor is active or we find a better extent. 131362306a36Sopenharmony_ci * The cursor is deactivated if it extends beyond the range of the 131462306a36Sopenharmony_ci * current allocation candidate. 131562306a36Sopenharmony_ci */ 131662306a36Sopenharmony_ci while (xfs_alloc_cur_active(cur) && count) { 131762306a36Sopenharmony_ci error = xfs_alloc_cur_check(args, acur, cur, &i); 131862306a36Sopenharmony_ci if (error) 131962306a36Sopenharmony_ci return error; 132062306a36Sopenharmony_ci if (i == 1) { 132162306a36Sopenharmony_ci *stat = 1; 132262306a36Sopenharmony_ci if (find_one) 132362306a36Sopenharmony_ci break; 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci if (!xfs_alloc_cur_active(cur)) 132662306a36Sopenharmony_ci break; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci if (increment) 132962306a36Sopenharmony_ci error = xfs_btree_increment(cur, 0, &i); 133062306a36Sopenharmony_ci else 133162306a36Sopenharmony_ci error = xfs_btree_decrement(cur, 0, &i); 133262306a36Sopenharmony_ci if (error) 133362306a36Sopenharmony_ci return error; 133462306a36Sopenharmony_ci if (i == 0) 133562306a36Sopenharmony_ci cur->bc_ag.abt.active = false; 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci if (count > 0) 133862306a36Sopenharmony_ci count--; 133962306a36Sopenharmony_ci } 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci return 0; 134262306a36Sopenharmony_ci} 134362306a36Sopenharmony_ci 134462306a36Sopenharmony_ci/* 134562306a36Sopenharmony_ci * Search the by-bno and by-size btrees in parallel in search of an extent with 134662306a36Sopenharmony_ci * ideal locality based on the NEAR mode ->agbno locality hint. 134762306a36Sopenharmony_ci */ 134862306a36Sopenharmony_ciSTATIC int 134962306a36Sopenharmony_cixfs_alloc_ag_vextent_locality( 135062306a36Sopenharmony_ci struct xfs_alloc_arg *args, 135162306a36Sopenharmony_ci struct xfs_alloc_cur *acur, 135262306a36Sopenharmony_ci int *stat) 135362306a36Sopenharmony_ci{ 135462306a36Sopenharmony_ci struct xfs_btree_cur *fbcur = NULL; 135562306a36Sopenharmony_ci int error; 135662306a36Sopenharmony_ci int i; 135762306a36Sopenharmony_ci bool fbinc; 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci ASSERT(acur->len == 0); 136062306a36Sopenharmony_ci 136162306a36Sopenharmony_ci *stat = 0; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci error = xfs_alloc_lookup_ge(acur->cnt, args->agbno, acur->cur_len, &i); 136462306a36Sopenharmony_ci if (error) 136562306a36Sopenharmony_ci return error; 136662306a36Sopenharmony_ci error = xfs_alloc_lookup_le(acur->bnolt, args->agbno, 0, &i); 136762306a36Sopenharmony_ci if (error) 136862306a36Sopenharmony_ci return error; 136962306a36Sopenharmony_ci error = xfs_alloc_lookup_ge(acur->bnogt, args->agbno, 0, &i); 137062306a36Sopenharmony_ci if (error) 137162306a36Sopenharmony_ci return error; 137262306a36Sopenharmony_ci 137362306a36Sopenharmony_ci /* 137462306a36Sopenharmony_ci * Search the bnobt and cntbt in parallel. Search the bnobt left and 137562306a36Sopenharmony_ci * right and lookup the closest extent to the locality hint for each 137662306a36Sopenharmony_ci * extent size key in the cntbt. The entire search terminates 137762306a36Sopenharmony_ci * immediately on a bnobt hit because that means we've found best case 137862306a36Sopenharmony_ci * locality. Otherwise the search continues until the cntbt cursor runs 137962306a36Sopenharmony_ci * off the end of the tree. If no allocation candidate is found at this 138062306a36Sopenharmony_ci * point, give up on locality, walk backwards from the end of the cntbt 138162306a36Sopenharmony_ci * and take the first available extent. 138262306a36Sopenharmony_ci * 138362306a36Sopenharmony_ci * The parallel tree searches balance each other out to provide fairly 138462306a36Sopenharmony_ci * consistent performance for various situations. The bnobt search can 138562306a36Sopenharmony_ci * have pathological behavior in the worst case scenario of larger 138662306a36Sopenharmony_ci * allocation requests and fragmented free space. On the other hand, the 138762306a36Sopenharmony_ci * bnobt is able to satisfy most smaller allocation requests much more 138862306a36Sopenharmony_ci * quickly than the cntbt. The cntbt search can sift through fragmented 138962306a36Sopenharmony_ci * free space and sets of free extents for larger allocation requests 139062306a36Sopenharmony_ci * more quickly than the bnobt. Since the locality hint is just a hint 139162306a36Sopenharmony_ci * and we don't want to scan the entire bnobt for perfect locality, the 139262306a36Sopenharmony_ci * cntbt search essentially bounds the bnobt search such that we can 139362306a36Sopenharmony_ci * find good enough locality at reasonable performance in most cases. 139462306a36Sopenharmony_ci */ 139562306a36Sopenharmony_ci while (xfs_alloc_cur_active(acur->bnolt) || 139662306a36Sopenharmony_ci xfs_alloc_cur_active(acur->bnogt) || 139762306a36Sopenharmony_ci xfs_alloc_cur_active(acur->cnt)) { 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci trace_xfs_alloc_cur_lookup(args); 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci /* 140262306a36Sopenharmony_ci * Search the bnobt left and right. In the case of a hit, finish 140362306a36Sopenharmony_ci * the search in the opposite direction and we're done. 140462306a36Sopenharmony_ci */ 140562306a36Sopenharmony_ci error = xfs_alloc_walk_iter(args, acur, acur->bnolt, false, 140662306a36Sopenharmony_ci true, 1, &i); 140762306a36Sopenharmony_ci if (error) 140862306a36Sopenharmony_ci return error; 140962306a36Sopenharmony_ci if (i == 1) { 141062306a36Sopenharmony_ci trace_xfs_alloc_cur_left(args); 141162306a36Sopenharmony_ci fbcur = acur->bnogt; 141262306a36Sopenharmony_ci fbinc = true; 141362306a36Sopenharmony_ci break; 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci error = xfs_alloc_walk_iter(args, acur, acur->bnogt, true, true, 141662306a36Sopenharmony_ci 1, &i); 141762306a36Sopenharmony_ci if (error) 141862306a36Sopenharmony_ci return error; 141962306a36Sopenharmony_ci if (i == 1) { 142062306a36Sopenharmony_ci trace_xfs_alloc_cur_right(args); 142162306a36Sopenharmony_ci fbcur = acur->bnolt; 142262306a36Sopenharmony_ci fbinc = false; 142362306a36Sopenharmony_ci break; 142462306a36Sopenharmony_ci } 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci /* 142762306a36Sopenharmony_ci * Check the extent with best locality based on the current 142862306a36Sopenharmony_ci * extent size search key and keep track of the best candidate. 142962306a36Sopenharmony_ci */ 143062306a36Sopenharmony_ci error = xfs_alloc_cntbt_iter(args, acur); 143162306a36Sopenharmony_ci if (error) 143262306a36Sopenharmony_ci return error; 143362306a36Sopenharmony_ci if (!xfs_alloc_cur_active(acur->cnt)) { 143462306a36Sopenharmony_ci trace_xfs_alloc_cur_lookup_done(args); 143562306a36Sopenharmony_ci break; 143662306a36Sopenharmony_ci } 143762306a36Sopenharmony_ci } 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci /* 144062306a36Sopenharmony_ci * If we failed to find anything due to busy extents, return empty 144162306a36Sopenharmony_ci * handed so the caller can flush and retry. If no busy extents were 144262306a36Sopenharmony_ci * found, walk backwards from the end of the cntbt as a last resort. 144362306a36Sopenharmony_ci */ 144462306a36Sopenharmony_ci if (!xfs_alloc_cur_active(acur->cnt) && !acur->len && !acur->busy) { 144562306a36Sopenharmony_ci error = xfs_btree_decrement(acur->cnt, 0, &i); 144662306a36Sopenharmony_ci if (error) 144762306a36Sopenharmony_ci return error; 144862306a36Sopenharmony_ci if (i) { 144962306a36Sopenharmony_ci acur->cnt->bc_ag.abt.active = true; 145062306a36Sopenharmony_ci fbcur = acur->cnt; 145162306a36Sopenharmony_ci fbinc = false; 145262306a36Sopenharmony_ci } 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci /* 145662306a36Sopenharmony_ci * Search in the opposite direction for a better entry in the case of 145762306a36Sopenharmony_ci * a bnobt hit or walk backwards from the end of the cntbt. 145862306a36Sopenharmony_ci */ 145962306a36Sopenharmony_ci if (fbcur) { 146062306a36Sopenharmony_ci error = xfs_alloc_walk_iter(args, acur, fbcur, fbinc, true, -1, 146162306a36Sopenharmony_ci &i); 146262306a36Sopenharmony_ci if (error) 146362306a36Sopenharmony_ci return error; 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci 146662306a36Sopenharmony_ci if (acur->len) 146762306a36Sopenharmony_ci *stat = 1; 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci return 0; 147062306a36Sopenharmony_ci} 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci/* Check the last block of the cnt btree for allocations. */ 147362306a36Sopenharmony_cistatic int 147462306a36Sopenharmony_cixfs_alloc_ag_vextent_lastblock( 147562306a36Sopenharmony_ci struct xfs_alloc_arg *args, 147662306a36Sopenharmony_ci struct xfs_alloc_cur *acur, 147762306a36Sopenharmony_ci xfs_agblock_t *bno, 147862306a36Sopenharmony_ci xfs_extlen_t *len, 147962306a36Sopenharmony_ci bool *allocated) 148062306a36Sopenharmony_ci{ 148162306a36Sopenharmony_ci int error; 148262306a36Sopenharmony_ci int i; 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci#ifdef DEBUG 148562306a36Sopenharmony_ci /* Randomly don't execute the first algorithm. */ 148662306a36Sopenharmony_ci if (get_random_u32_below(2)) 148762306a36Sopenharmony_ci return 0; 148862306a36Sopenharmony_ci#endif 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci /* 149162306a36Sopenharmony_ci * Start from the entry that lookup found, sequence through all larger 149262306a36Sopenharmony_ci * free blocks. If we're actually pointing at a record smaller than 149362306a36Sopenharmony_ci * maxlen, go to the start of this block, and skip all those smaller 149462306a36Sopenharmony_ci * than minlen. 149562306a36Sopenharmony_ci */ 149662306a36Sopenharmony_ci if (*len || args->alignment > 1) { 149762306a36Sopenharmony_ci acur->cnt->bc_levels[0].ptr = 1; 149862306a36Sopenharmony_ci do { 149962306a36Sopenharmony_ci error = xfs_alloc_get_rec(acur->cnt, bno, len, &i); 150062306a36Sopenharmony_ci if (error) 150162306a36Sopenharmony_ci return error; 150262306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, i != 1)) 150362306a36Sopenharmony_ci return -EFSCORRUPTED; 150462306a36Sopenharmony_ci if (*len >= args->minlen) 150562306a36Sopenharmony_ci break; 150662306a36Sopenharmony_ci error = xfs_btree_increment(acur->cnt, 0, &i); 150762306a36Sopenharmony_ci if (error) 150862306a36Sopenharmony_ci return error; 150962306a36Sopenharmony_ci } while (i); 151062306a36Sopenharmony_ci ASSERT(*len >= args->minlen); 151162306a36Sopenharmony_ci if (!i) 151262306a36Sopenharmony_ci return 0; 151362306a36Sopenharmony_ci } 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_ci error = xfs_alloc_walk_iter(args, acur, acur->cnt, true, false, -1, &i); 151662306a36Sopenharmony_ci if (error) 151762306a36Sopenharmony_ci return error; 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci /* 152062306a36Sopenharmony_ci * It didn't work. We COULD be in a case where there's a good record 152162306a36Sopenharmony_ci * somewhere, so try again. 152262306a36Sopenharmony_ci */ 152362306a36Sopenharmony_ci if (acur->len == 0) 152462306a36Sopenharmony_ci return 0; 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci trace_xfs_alloc_near_first(args); 152762306a36Sopenharmony_ci *allocated = true; 152862306a36Sopenharmony_ci return 0; 152962306a36Sopenharmony_ci} 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci/* 153262306a36Sopenharmony_ci * Allocate a variable extent near bno in the allocation group agno. 153362306a36Sopenharmony_ci * Extent's length (returned in len) will be between minlen and maxlen, 153462306a36Sopenharmony_ci * and of the form k * prod + mod unless there's nothing that large. 153562306a36Sopenharmony_ci * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. 153662306a36Sopenharmony_ci */ 153762306a36Sopenharmony_ciSTATIC int 153862306a36Sopenharmony_cixfs_alloc_ag_vextent_near( 153962306a36Sopenharmony_ci struct xfs_alloc_arg *args, 154062306a36Sopenharmony_ci uint32_t alloc_flags) 154162306a36Sopenharmony_ci{ 154262306a36Sopenharmony_ci struct xfs_alloc_cur acur = {}; 154362306a36Sopenharmony_ci int error; /* error code */ 154462306a36Sopenharmony_ci int i; /* result code, temporary */ 154562306a36Sopenharmony_ci xfs_agblock_t bno; 154662306a36Sopenharmony_ci xfs_extlen_t len; 154762306a36Sopenharmony_ci 154862306a36Sopenharmony_ci /* handle uninitialized agbno range so caller doesn't have to */ 154962306a36Sopenharmony_ci if (!args->min_agbno && !args->max_agbno) 155062306a36Sopenharmony_ci args->max_agbno = args->mp->m_sb.sb_agblocks - 1; 155162306a36Sopenharmony_ci ASSERT(args->min_agbno <= args->max_agbno); 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci /* clamp agbno to the range if it's outside */ 155462306a36Sopenharmony_ci if (args->agbno < args->min_agbno) 155562306a36Sopenharmony_ci args->agbno = args->min_agbno; 155662306a36Sopenharmony_ci if (args->agbno > args->max_agbno) 155762306a36Sopenharmony_ci args->agbno = args->max_agbno; 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci /* Retry once quickly if we find busy extents before blocking. */ 156062306a36Sopenharmony_ci alloc_flags |= XFS_ALLOC_FLAG_TRYFLUSH; 156162306a36Sopenharmony_cirestart: 156262306a36Sopenharmony_ci len = 0; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci /* 156562306a36Sopenharmony_ci * Set up cursors and see if there are any free extents as big as 156662306a36Sopenharmony_ci * maxlen. If not, pick the last entry in the tree unless the tree is 156762306a36Sopenharmony_ci * empty. 156862306a36Sopenharmony_ci */ 156962306a36Sopenharmony_ci error = xfs_alloc_cur_setup(args, &acur); 157062306a36Sopenharmony_ci if (error == -ENOSPC) { 157162306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_small(args, acur.cnt, &bno, 157262306a36Sopenharmony_ci &len, &i); 157362306a36Sopenharmony_ci if (error) 157462306a36Sopenharmony_ci goto out; 157562306a36Sopenharmony_ci if (i == 0 || len == 0) { 157662306a36Sopenharmony_ci trace_xfs_alloc_near_noentry(args); 157762306a36Sopenharmony_ci goto out; 157862306a36Sopenharmony_ci } 157962306a36Sopenharmony_ci ASSERT(i == 1); 158062306a36Sopenharmony_ci } else if (error) { 158162306a36Sopenharmony_ci goto out; 158262306a36Sopenharmony_ci } 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci /* 158562306a36Sopenharmony_ci * First algorithm. 158662306a36Sopenharmony_ci * If the requested extent is large wrt the freespaces available 158762306a36Sopenharmony_ci * in this a.g., then the cursor will be pointing to a btree entry 158862306a36Sopenharmony_ci * near the right edge of the tree. If it's in the last btree leaf 158962306a36Sopenharmony_ci * block, then we just examine all the entries in that block 159062306a36Sopenharmony_ci * that are big enough, and pick the best one. 159162306a36Sopenharmony_ci */ 159262306a36Sopenharmony_ci if (xfs_btree_islastblock(acur.cnt, 0)) { 159362306a36Sopenharmony_ci bool allocated = false; 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_lastblock(args, &acur, &bno, &len, 159662306a36Sopenharmony_ci &allocated); 159762306a36Sopenharmony_ci if (error) 159862306a36Sopenharmony_ci goto out; 159962306a36Sopenharmony_ci if (allocated) 160062306a36Sopenharmony_ci goto alloc_finish; 160162306a36Sopenharmony_ci } 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci /* 160462306a36Sopenharmony_ci * Second algorithm. Combined cntbt and bnobt search to find ideal 160562306a36Sopenharmony_ci * locality. 160662306a36Sopenharmony_ci */ 160762306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_locality(args, &acur, &i); 160862306a36Sopenharmony_ci if (error) 160962306a36Sopenharmony_ci goto out; 161062306a36Sopenharmony_ci 161162306a36Sopenharmony_ci /* 161262306a36Sopenharmony_ci * If we couldn't get anything, give up. 161362306a36Sopenharmony_ci */ 161462306a36Sopenharmony_ci if (!acur.len) { 161562306a36Sopenharmony_ci if (acur.busy) { 161662306a36Sopenharmony_ci /* 161762306a36Sopenharmony_ci * Our only valid extents must have been busy. Flush and 161862306a36Sopenharmony_ci * retry the allocation again. If we get an -EAGAIN 161962306a36Sopenharmony_ci * error, we're being told that a deadlock was avoided 162062306a36Sopenharmony_ci * and the current transaction needs committing before 162162306a36Sopenharmony_ci * the allocation can be retried. 162262306a36Sopenharmony_ci */ 162362306a36Sopenharmony_ci trace_xfs_alloc_near_busy(args); 162462306a36Sopenharmony_ci error = xfs_extent_busy_flush(args->tp, args->pag, 162562306a36Sopenharmony_ci acur.busy_gen, alloc_flags); 162662306a36Sopenharmony_ci if (error) 162762306a36Sopenharmony_ci goto out; 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci alloc_flags &= ~XFS_ALLOC_FLAG_TRYFLUSH; 163062306a36Sopenharmony_ci goto restart; 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci trace_xfs_alloc_size_neither(args); 163362306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 163462306a36Sopenharmony_ci goto out; 163562306a36Sopenharmony_ci } 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_cialloc_finish: 163862306a36Sopenharmony_ci /* fix up btrees on a successful allocation */ 163962306a36Sopenharmony_ci error = xfs_alloc_cur_finish(args, &acur); 164062306a36Sopenharmony_ci 164162306a36Sopenharmony_ciout: 164262306a36Sopenharmony_ci xfs_alloc_cur_close(&acur, error); 164362306a36Sopenharmony_ci return error; 164462306a36Sopenharmony_ci} 164562306a36Sopenharmony_ci 164662306a36Sopenharmony_ci/* 164762306a36Sopenharmony_ci * Allocate a variable extent anywhere in the allocation group agno. 164862306a36Sopenharmony_ci * Extent's length (returned in len) will be between minlen and maxlen, 164962306a36Sopenharmony_ci * and of the form k * prod + mod unless there's nothing that large. 165062306a36Sopenharmony_ci * Return the starting a.g. block, or NULLAGBLOCK if we can't do it. 165162306a36Sopenharmony_ci */ 165262306a36Sopenharmony_cistatic int 165362306a36Sopenharmony_cixfs_alloc_ag_vextent_size( 165462306a36Sopenharmony_ci struct xfs_alloc_arg *args, 165562306a36Sopenharmony_ci uint32_t alloc_flags) 165662306a36Sopenharmony_ci{ 165762306a36Sopenharmony_ci struct xfs_agf *agf = args->agbp->b_addr; 165862306a36Sopenharmony_ci struct xfs_btree_cur *bno_cur; 165962306a36Sopenharmony_ci struct xfs_btree_cur *cnt_cur; 166062306a36Sopenharmony_ci xfs_agblock_t fbno; /* start of found freespace */ 166162306a36Sopenharmony_ci xfs_extlen_t flen; /* length of found freespace */ 166262306a36Sopenharmony_ci xfs_agblock_t rbno; /* returned block number */ 166362306a36Sopenharmony_ci xfs_extlen_t rlen; /* length of returned extent */ 166462306a36Sopenharmony_ci bool busy; 166562306a36Sopenharmony_ci unsigned busy_gen; 166662306a36Sopenharmony_ci int error; 166762306a36Sopenharmony_ci int i; 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci /* Retry once quickly if we find busy extents before blocking. */ 167062306a36Sopenharmony_ci alloc_flags |= XFS_ALLOC_FLAG_TRYFLUSH; 167162306a36Sopenharmony_cirestart: 167262306a36Sopenharmony_ci /* 167362306a36Sopenharmony_ci * Allocate and initialize a cursor for the by-size btree. 167462306a36Sopenharmony_ci */ 167562306a36Sopenharmony_ci cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, 167662306a36Sopenharmony_ci args->pag, XFS_BTNUM_CNT); 167762306a36Sopenharmony_ci bno_cur = NULL; 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci /* 168062306a36Sopenharmony_ci * Look for an entry >= maxlen+alignment-1 blocks. 168162306a36Sopenharmony_ci */ 168262306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_ge(cnt_cur, 0, 168362306a36Sopenharmony_ci args->maxlen + args->alignment - 1, &i))) 168462306a36Sopenharmony_ci goto error0; 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci /* 168762306a36Sopenharmony_ci * If none then we have to settle for a smaller extent. In the case that 168862306a36Sopenharmony_ci * there are no large extents, this will return the last entry in the 168962306a36Sopenharmony_ci * tree unless the tree is empty. In the case that there are only busy 169062306a36Sopenharmony_ci * large extents, this will return the largest small extent unless there 169162306a36Sopenharmony_ci * are no smaller extents available. 169262306a36Sopenharmony_ci */ 169362306a36Sopenharmony_ci if (!i) { 169462306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_small(args, cnt_cur, 169562306a36Sopenharmony_ci &fbno, &flen, &i); 169662306a36Sopenharmony_ci if (error) 169762306a36Sopenharmony_ci goto error0; 169862306a36Sopenharmony_ci if (i == 0 || flen == 0) { 169962306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); 170062306a36Sopenharmony_ci trace_xfs_alloc_size_noentry(args); 170162306a36Sopenharmony_ci return 0; 170262306a36Sopenharmony_ci } 170362306a36Sopenharmony_ci ASSERT(i == 1); 170462306a36Sopenharmony_ci busy = xfs_alloc_compute_aligned(args, fbno, flen, &rbno, 170562306a36Sopenharmony_ci &rlen, &busy_gen); 170662306a36Sopenharmony_ci } else { 170762306a36Sopenharmony_ci /* 170862306a36Sopenharmony_ci * Search for a non-busy extent that is large enough. 170962306a36Sopenharmony_ci */ 171062306a36Sopenharmony_ci for (;;) { 171162306a36Sopenharmony_ci error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, &i); 171262306a36Sopenharmony_ci if (error) 171362306a36Sopenharmony_ci goto error0; 171462306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, i != 1)) { 171562306a36Sopenharmony_ci error = -EFSCORRUPTED; 171662306a36Sopenharmony_ci goto error0; 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_ci busy = xfs_alloc_compute_aligned(args, fbno, flen, 172062306a36Sopenharmony_ci &rbno, &rlen, &busy_gen); 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_ci if (rlen >= args->maxlen) 172362306a36Sopenharmony_ci break; 172462306a36Sopenharmony_ci 172562306a36Sopenharmony_ci error = xfs_btree_increment(cnt_cur, 0, &i); 172662306a36Sopenharmony_ci if (error) 172762306a36Sopenharmony_ci goto error0; 172862306a36Sopenharmony_ci if (i) 172962306a36Sopenharmony_ci continue; 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci /* 173262306a36Sopenharmony_ci * Our only valid extents must have been busy. Flush and 173362306a36Sopenharmony_ci * retry the allocation again. If we get an -EAGAIN 173462306a36Sopenharmony_ci * error, we're being told that a deadlock was avoided 173562306a36Sopenharmony_ci * and the current transaction needs committing before 173662306a36Sopenharmony_ci * the allocation can be retried. 173762306a36Sopenharmony_ci */ 173862306a36Sopenharmony_ci trace_xfs_alloc_size_busy(args); 173962306a36Sopenharmony_ci error = xfs_extent_busy_flush(args->tp, args->pag, 174062306a36Sopenharmony_ci busy_gen, alloc_flags); 174162306a36Sopenharmony_ci if (error) 174262306a36Sopenharmony_ci goto error0; 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_ci alloc_flags &= ~XFS_ALLOC_FLAG_TRYFLUSH; 174562306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); 174662306a36Sopenharmony_ci goto restart; 174762306a36Sopenharmony_ci } 174862306a36Sopenharmony_ci } 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci /* 175162306a36Sopenharmony_ci * In the first case above, we got the last entry in the 175262306a36Sopenharmony_ci * by-size btree. Now we check to see if the space hits maxlen 175362306a36Sopenharmony_ci * once aligned; if not, we search left for something better. 175462306a36Sopenharmony_ci * This can't happen in the second case above. 175562306a36Sopenharmony_ci */ 175662306a36Sopenharmony_ci rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); 175762306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, 175862306a36Sopenharmony_ci rlen != 0 && 175962306a36Sopenharmony_ci (rlen > flen || 176062306a36Sopenharmony_ci rbno + rlen > fbno + flen))) { 176162306a36Sopenharmony_ci error = -EFSCORRUPTED; 176262306a36Sopenharmony_ci goto error0; 176362306a36Sopenharmony_ci } 176462306a36Sopenharmony_ci if (rlen < args->maxlen) { 176562306a36Sopenharmony_ci xfs_agblock_t bestfbno; 176662306a36Sopenharmony_ci xfs_extlen_t bestflen; 176762306a36Sopenharmony_ci xfs_agblock_t bestrbno; 176862306a36Sopenharmony_ci xfs_extlen_t bestrlen; 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci bestrlen = rlen; 177162306a36Sopenharmony_ci bestrbno = rbno; 177262306a36Sopenharmony_ci bestflen = flen; 177362306a36Sopenharmony_ci bestfbno = fbno; 177462306a36Sopenharmony_ci for (;;) { 177562306a36Sopenharmony_ci if ((error = xfs_btree_decrement(cnt_cur, 0, &i))) 177662306a36Sopenharmony_ci goto error0; 177762306a36Sopenharmony_ci if (i == 0) 177862306a36Sopenharmony_ci break; 177962306a36Sopenharmony_ci if ((error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, 178062306a36Sopenharmony_ci &i))) 178162306a36Sopenharmony_ci goto error0; 178262306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, i != 1)) { 178362306a36Sopenharmony_ci error = -EFSCORRUPTED; 178462306a36Sopenharmony_ci goto error0; 178562306a36Sopenharmony_ci } 178662306a36Sopenharmony_ci if (flen < bestrlen) 178762306a36Sopenharmony_ci break; 178862306a36Sopenharmony_ci busy = xfs_alloc_compute_aligned(args, fbno, flen, 178962306a36Sopenharmony_ci &rbno, &rlen, &busy_gen); 179062306a36Sopenharmony_ci rlen = XFS_EXTLEN_MIN(args->maxlen, rlen); 179162306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, 179262306a36Sopenharmony_ci rlen != 0 && 179362306a36Sopenharmony_ci (rlen > flen || 179462306a36Sopenharmony_ci rbno + rlen > fbno + flen))) { 179562306a36Sopenharmony_ci error = -EFSCORRUPTED; 179662306a36Sopenharmony_ci goto error0; 179762306a36Sopenharmony_ci } 179862306a36Sopenharmony_ci if (rlen > bestrlen) { 179962306a36Sopenharmony_ci bestrlen = rlen; 180062306a36Sopenharmony_ci bestrbno = rbno; 180162306a36Sopenharmony_ci bestflen = flen; 180262306a36Sopenharmony_ci bestfbno = fbno; 180362306a36Sopenharmony_ci if (rlen == args->maxlen) 180462306a36Sopenharmony_ci break; 180562306a36Sopenharmony_ci } 180662306a36Sopenharmony_ci } 180762306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, bestfbno, bestflen, 180862306a36Sopenharmony_ci &i))) 180962306a36Sopenharmony_ci goto error0; 181062306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, i != 1)) { 181162306a36Sopenharmony_ci error = -EFSCORRUPTED; 181262306a36Sopenharmony_ci goto error0; 181362306a36Sopenharmony_ci } 181462306a36Sopenharmony_ci rlen = bestrlen; 181562306a36Sopenharmony_ci rbno = bestrbno; 181662306a36Sopenharmony_ci flen = bestflen; 181762306a36Sopenharmony_ci fbno = bestfbno; 181862306a36Sopenharmony_ci } 181962306a36Sopenharmony_ci args->wasfromfl = 0; 182062306a36Sopenharmony_ci /* 182162306a36Sopenharmony_ci * Fix up the length. 182262306a36Sopenharmony_ci */ 182362306a36Sopenharmony_ci args->len = rlen; 182462306a36Sopenharmony_ci if (rlen < args->minlen) { 182562306a36Sopenharmony_ci if (busy) { 182662306a36Sopenharmony_ci /* 182762306a36Sopenharmony_ci * Our only valid extents must have been busy. Flush and 182862306a36Sopenharmony_ci * retry the allocation again. If we get an -EAGAIN 182962306a36Sopenharmony_ci * error, we're being told that a deadlock was avoided 183062306a36Sopenharmony_ci * and the current transaction needs committing before 183162306a36Sopenharmony_ci * the allocation can be retried. 183262306a36Sopenharmony_ci */ 183362306a36Sopenharmony_ci trace_xfs_alloc_size_busy(args); 183462306a36Sopenharmony_ci error = xfs_extent_busy_flush(args->tp, args->pag, 183562306a36Sopenharmony_ci busy_gen, alloc_flags); 183662306a36Sopenharmony_ci if (error) 183762306a36Sopenharmony_ci goto error0; 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_ci alloc_flags &= ~XFS_ALLOC_FLAG_TRYFLUSH; 184062306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); 184162306a36Sopenharmony_ci goto restart; 184262306a36Sopenharmony_ci } 184362306a36Sopenharmony_ci goto out_nominleft; 184462306a36Sopenharmony_ci } 184562306a36Sopenharmony_ci xfs_alloc_fix_len(args); 184662306a36Sopenharmony_ci 184762306a36Sopenharmony_ci rlen = args->len; 184862306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, rlen > flen)) { 184962306a36Sopenharmony_ci error = -EFSCORRUPTED; 185062306a36Sopenharmony_ci goto error0; 185162306a36Sopenharmony_ci } 185262306a36Sopenharmony_ci /* 185362306a36Sopenharmony_ci * Allocate and initialize a cursor for the by-block tree. 185462306a36Sopenharmony_ci */ 185562306a36Sopenharmony_ci bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp, 185662306a36Sopenharmony_ci args->pag, XFS_BTNUM_BNO); 185762306a36Sopenharmony_ci if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, 185862306a36Sopenharmony_ci rbno, rlen, XFSA_FIXUP_CNT_OK))) 185962306a36Sopenharmony_ci goto error0; 186062306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); 186162306a36Sopenharmony_ci xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); 186262306a36Sopenharmony_ci cnt_cur = bno_cur = NULL; 186362306a36Sopenharmony_ci args->len = rlen; 186462306a36Sopenharmony_ci args->agbno = rbno; 186562306a36Sopenharmony_ci if (XFS_IS_CORRUPT(args->mp, 186662306a36Sopenharmony_ci args->agbno + args->len > 186762306a36Sopenharmony_ci be32_to_cpu(agf->agf_length))) { 186862306a36Sopenharmony_ci error = -EFSCORRUPTED; 186962306a36Sopenharmony_ci goto error0; 187062306a36Sopenharmony_ci } 187162306a36Sopenharmony_ci trace_xfs_alloc_size_done(args); 187262306a36Sopenharmony_ci return 0; 187362306a36Sopenharmony_ci 187462306a36Sopenharmony_cierror0: 187562306a36Sopenharmony_ci trace_xfs_alloc_size_error(args); 187662306a36Sopenharmony_ci if (cnt_cur) 187762306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); 187862306a36Sopenharmony_ci if (bno_cur) 187962306a36Sopenharmony_ci xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); 188062306a36Sopenharmony_ci return error; 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ciout_nominleft: 188362306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); 188462306a36Sopenharmony_ci trace_xfs_alloc_size_nominleft(args); 188562306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 188662306a36Sopenharmony_ci return 0; 188762306a36Sopenharmony_ci} 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci/* 189062306a36Sopenharmony_ci * Free the extent starting at agno/bno for length. 189162306a36Sopenharmony_ci */ 189262306a36Sopenharmony_ciSTATIC int 189362306a36Sopenharmony_cixfs_free_ag_extent( 189462306a36Sopenharmony_ci struct xfs_trans *tp, 189562306a36Sopenharmony_ci struct xfs_buf *agbp, 189662306a36Sopenharmony_ci xfs_agnumber_t agno, 189762306a36Sopenharmony_ci xfs_agblock_t bno, 189862306a36Sopenharmony_ci xfs_extlen_t len, 189962306a36Sopenharmony_ci const struct xfs_owner_info *oinfo, 190062306a36Sopenharmony_ci enum xfs_ag_resv_type type) 190162306a36Sopenharmony_ci{ 190262306a36Sopenharmony_ci struct xfs_mount *mp; 190362306a36Sopenharmony_ci struct xfs_btree_cur *bno_cur; 190462306a36Sopenharmony_ci struct xfs_btree_cur *cnt_cur; 190562306a36Sopenharmony_ci xfs_agblock_t gtbno; /* start of right neighbor */ 190662306a36Sopenharmony_ci xfs_extlen_t gtlen; /* length of right neighbor */ 190762306a36Sopenharmony_ci xfs_agblock_t ltbno; /* start of left neighbor */ 190862306a36Sopenharmony_ci xfs_extlen_t ltlen; /* length of left neighbor */ 190962306a36Sopenharmony_ci xfs_agblock_t nbno; /* new starting block of freesp */ 191062306a36Sopenharmony_ci xfs_extlen_t nlen; /* new length of freespace */ 191162306a36Sopenharmony_ci int haveleft; /* have a left neighbor */ 191262306a36Sopenharmony_ci int haveright; /* have a right neighbor */ 191362306a36Sopenharmony_ci int i; 191462306a36Sopenharmony_ci int error; 191562306a36Sopenharmony_ci struct xfs_perag *pag = agbp->b_pag; 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci bno_cur = cnt_cur = NULL; 191862306a36Sopenharmony_ci mp = tp->t_mountp; 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_ci if (!xfs_rmap_should_skip_owner_update(oinfo)) { 192162306a36Sopenharmony_ci error = xfs_rmap_free(tp, agbp, pag, bno, len, oinfo); 192262306a36Sopenharmony_ci if (error) 192362306a36Sopenharmony_ci goto error0; 192462306a36Sopenharmony_ci } 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci /* 192762306a36Sopenharmony_ci * Allocate and initialize a cursor for the by-block btree. 192862306a36Sopenharmony_ci */ 192962306a36Sopenharmony_ci bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_BNO); 193062306a36Sopenharmony_ci /* 193162306a36Sopenharmony_ci * Look for a neighboring block on the left (lower block numbers) 193262306a36Sopenharmony_ci * that is contiguous with this space. 193362306a36Sopenharmony_ci */ 193462306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_le(bno_cur, bno, len, &haveleft))) 193562306a36Sopenharmony_ci goto error0; 193662306a36Sopenharmony_ci if (haveleft) { 193762306a36Sopenharmony_ci /* 193862306a36Sopenharmony_ci * There is a block to our left. 193962306a36Sopenharmony_ci */ 194062306a36Sopenharmony_ci if ((error = xfs_alloc_get_rec(bno_cur, <bno, <len, &i))) 194162306a36Sopenharmony_ci goto error0; 194262306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 194362306a36Sopenharmony_ci error = -EFSCORRUPTED; 194462306a36Sopenharmony_ci goto error0; 194562306a36Sopenharmony_ci } 194662306a36Sopenharmony_ci /* 194762306a36Sopenharmony_ci * It's not contiguous, though. 194862306a36Sopenharmony_ci */ 194962306a36Sopenharmony_ci if (ltbno + ltlen < bno) 195062306a36Sopenharmony_ci haveleft = 0; 195162306a36Sopenharmony_ci else { 195262306a36Sopenharmony_ci /* 195362306a36Sopenharmony_ci * If this failure happens the request to free this 195462306a36Sopenharmony_ci * space was invalid, it's (partly) already free. 195562306a36Sopenharmony_ci * Very bad. 195662306a36Sopenharmony_ci */ 195762306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, ltbno + ltlen > bno)) { 195862306a36Sopenharmony_ci error = -EFSCORRUPTED; 195962306a36Sopenharmony_ci goto error0; 196062306a36Sopenharmony_ci } 196162306a36Sopenharmony_ci } 196262306a36Sopenharmony_ci } 196362306a36Sopenharmony_ci /* 196462306a36Sopenharmony_ci * Look for a neighboring block on the right (higher block numbers) 196562306a36Sopenharmony_ci * that is contiguous with this space. 196662306a36Sopenharmony_ci */ 196762306a36Sopenharmony_ci if ((error = xfs_btree_increment(bno_cur, 0, &haveright))) 196862306a36Sopenharmony_ci goto error0; 196962306a36Sopenharmony_ci if (haveright) { 197062306a36Sopenharmony_ci /* 197162306a36Sopenharmony_ci * There is a block to our right. 197262306a36Sopenharmony_ci */ 197362306a36Sopenharmony_ci if ((error = xfs_alloc_get_rec(bno_cur, >bno, >len, &i))) 197462306a36Sopenharmony_ci goto error0; 197562306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 197662306a36Sopenharmony_ci error = -EFSCORRUPTED; 197762306a36Sopenharmony_ci goto error0; 197862306a36Sopenharmony_ci } 197962306a36Sopenharmony_ci /* 198062306a36Sopenharmony_ci * It's not contiguous, though. 198162306a36Sopenharmony_ci */ 198262306a36Sopenharmony_ci if (bno + len < gtbno) 198362306a36Sopenharmony_ci haveright = 0; 198462306a36Sopenharmony_ci else { 198562306a36Sopenharmony_ci /* 198662306a36Sopenharmony_ci * If this failure happens the request to free this 198762306a36Sopenharmony_ci * space was invalid, it's (partly) already free. 198862306a36Sopenharmony_ci * Very bad. 198962306a36Sopenharmony_ci */ 199062306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, bno + len > gtbno)) { 199162306a36Sopenharmony_ci error = -EFSCORRUPTED; 199262306a36Sopenharmony_ci goto error0; 199362306a36Sopenharmony_ci } 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_ci } 199662306a36Sopenharmony_ci /* 199762306a36Sopenharmony_ci * Now allocate and initialize a cursor for the by-size tree. 199862306a36Sopenharmony_ci */ 199962306a36Sopenharmony_ci cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, pag, XFS_BTNUM_CNT); 200062306a36Sopenharmony_ci /* 200162306a36Sopenharmony_ci * Have both left and right contiguous neighbors. 200262306a36Sopenharmony_ci * Merge all three into a single free block. 200362306a36Sopenharmony_ci */ 200462306a36Sopenharmony_ci if (haveleft && haveright) { 200562306a36Sopenharmony_ci /* 200662306a36Sopenharmony_ci * Delete the old by-size entry on the left. 200762306a36Sopenharmony_ci */ 200862306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) 200962306a36Sopenharmony_ci goto error0; 201062306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 201162306a36Sopenharmony_ci error = -EFSCORRUPTED; 201262306a36Sopenharmony_ci goto error0; 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci if ((error = xfs_btree_delete(cnt_cur, &i))) 201562306a36Sopenharmony_ci goto error0; 201662306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 201762306a36Sopenharmony_ci error = -EFSCORRUPTED; 201862306a36Sopenharmony_ci goto error0; 201962306a36Sopenharmony_ci } 202062306a36Sopenharmony_ci /* 202162306a36Sopenharmony_ci * Delete the old by-size entry on the right. 202262306a36Sopenharmony_ci */ 202362306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) 202462306a36Sopenharmony_ci goto error0; 202562306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 202662306a36Sopenharmony_ci error = -EFSCORRUPTED; 202762306a36Sopenharmony_ci goto error0; 202862306a36Sopenharmony_ci } 202962306a36Sopenharmony_ci if ((error = xfs_btree_delete(cnt_cur, &i))) 203062306a36Sopenharmony_ci goto error0; 203162306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 203262306a36Sopenharmony_ci error = -EFSCORRUPTED; 203362306a36Sopenharmony_ci goto error0; 203462306a36Sopenharmony_ci } 203562306a36Sopenharmony_ci /* 203662306a36Sopenharmony_ci * Delete the old by-block entry for the right block. 203762306a36Sopenharmony_ci */ 203862306a36Sopenharmony_ci if ((error = xfs_btree_delete(bno_cur, &i))) 203962306a36Sopenharmony_ci goto error0; 204062306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 204162306a36Sopenharmony_ci error = -EFSCORRUPTED; 204262306a36Sopenharmony_ci goto error0; 204362306a36Sopenharmony_ci } 204462306a36Sopenharmony_ci /* 204562306a36Sopenharmony_ci * Move the by-block cursor back to the left neighbor. 204662306a36Sopenharmony_ci */ 204762306a36Sopenharmony_ci if ((error = xfs_btree_decrement(bno_cur, 0, &i))) 204862306a36Sopenharmony_ci goto error0; 204962306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 205062306a36Sopenharmony_ci error = -EFSCORRUPTED; 205162306a36Sopenharmony_ci goto error0; 205262306a36Sopenharmony_ci } 205362306a36Sopenharmony_ci#ifdef DEBUG 205462306a36Sopenharmony_ci /* 205562306a36Sopenharmony_ci * Check that this is the right record: delete didn't 205662306a36Sopenharmony_ci * mangle the cursor. 205762306a36Sopenharmony_ci */ 205862306a36Sopenharmony_ci { 205962306a36Sopenharmony_ci xfs_agblock_t xxbno; 206062306a36Sopenharmony_ci xfs_extlen_t xxlen; 206162306a36Sopenharmony_ci 206262306a36Sopenharmony_ci if ((error = xfs_alloc_get_rec(bno_cur, &xxbno, &xxlen, 206362306a36Sopenharmony_ci &i))) 206462306a36Sopenharmony_ci goto error0; 206562306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, 206662306a36Sopenharmony_ci i != 1 || 206762306a36Sopenharmony_ci xxbno != ltbno || 206862306a36Sopenharmony_ci xxlen != ltlen)) { 206962306a36Sopenharmony_ci error = -EFSCORRUPTED; 207062306a36Sopenharmony_ci goto error0; 207162306a36Sopenharmony_ci } 207262306a36Sopenharmony_ci } 207362306a36Sopenharmony_ci#endif 207462306a36Sopenharmony_ci /* 207562306a36Sopenharmony_ci * Update remaining by-block entry to the new, joined block. 207662306a36Sopenharmony_ci */ 207762306a36Sopenharmony_ci nbno = ltbno; 207862306a36Sopenharmony_ci nlen = len + ltlen + gtlen; 207962306a36Sopenharmony_ci if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) 208062306a36Sopenharmony_ci goto error0; 208162306a36Sopenharmony_ci } 208262306a36Sopenharmony_ci /* 208362306a36Sopenharmony_ci * Have only a left contiguous neighbor. 208462306a36Sopenharmony_ci * Merge it together with the new freespace. 208562306a36Sopenharmony_ci */ 208662306a36Sopenharmony_ci else if (haveleft) { 208762306a36Sopenharmony_ci /* 208862306a36Sopenharmony_ci * Delete the old by-size entry on the left. 208962306a36Sopenharmony_ci */ 209062306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, ltbno, ltlen, &i))) 209162306a36Sopenharmony_ci goto error0; 209262306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 209362306a36Sopenharmony_ci error = -EFSCORRUPTED; 209462306a36Sopenharmony_ci goto error0; 209562306a36Sopenharmony_ci } 209662306a36Sopenharmony_ci if ((error = xfs_btree_delete(cnt_cur, &i))) 209762306a36Sopenharmony_ci goto error0; 209862306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 209962306a36Sopenharmony_ci error = -EFSCORRUPTED; 210062306a36Sopenharmony_ci goto error0; 210162306a36Sopenharmony_ci } 210262306a36Sopenharmony_ci /* 210362306a36Sopenharmony_ci * Back up the by-block cursor to the left neighbor, and 210462306a36Sopenharmony_ci * update its length. 210562306a36Sopenharmony_ci */ 210662306a36Sopenharmony_ci if ((error = xfs_btree_decrement(bno_cur, 0, &i))) 210762306a36Sopenharmony_ci goto error0; 210862306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 210962306a36Sopenharmony_ci error = -EFSCORRUPTED; 211062306a36Sopenharmony_ci goto error0; 211162306a36Sopenharmony_ci } 211262306a36Sopenharmony_ci nbno = ltbno; 211362306a36Sopenharmony_ci nlen = len + ltlen; 211462306a36Sopenharmony_ci if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) 211562306a36Sopenharmony_ci goto error0; 211662306a36Sopenharmony_ci } 211762306a36Sopenharmony_ci /* 211862306a36Sopenharmony_ci * Have only a right contiguous neighbor. 211962306a36Sopenharmony_ci * Merge it together with the new freespace. 212062306a36Sopenharmony_ci */ 212162306a36Sopenharmony_ci else if (haveright) { 212262306a36Sopenharmony_ci /* 212362306a36Sopenharmony_ci * Delete the old by-size entry on the right. 212462306a36Sopenharmony_ci */ 212562306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, gtbno, gtlen, &i))) 212662306a36Sopenharmony_ci goto error0; 212762306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 212862306a36Sopenharmony_ci error = -EFSCORRUPTED; 212962306a36Sopenharmony_ci goto error0; 213062306a36Sopenharmony_ci } 213162306a36Sopenharmony_ci if ((error = xfs_btree_delete(cnt_cur, &i))) 213262306a36Sopenharmony_ci goto error0; 213362306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 213462306a36Sopenharmony_ci error = -EFSCORRUPTED; 213562306a36Sopenharmony_ci goto error0; 213662306a36Sopenharmony_ci } 213762306a36Sopenharmony_ci /* 213862306a36Sopenharmony_ci * Update the starting block and length of the right 213962306a36Sopenharmony_ci * neighbor in the by-block tree. 214062306a36Sopenharmony_ci */ 214162306a36Sopenharmony_ci nbno = bno; 214262306a36Sopenharmony_ci nlen = len + gtlen; 214362306a36Sopenharmony_ci if ((error = xfs_alloc_update(bno_cur, nbno, nlen))) 214462306a36Sopenharmony_ci goto error0; 214562306a36Sopenharmony_ci } 214662306a36Sopenharmony_ci /* 214762306a36Sopenharmony_ci * No contiguous neighbors. 214862306a36Sopenharmony_ci * Insert the new freespace into the by-block tree. 214962306a36Sopenharmony_ci */ 215062306a36Sopenharmony_ci else { 215162306a36Sopenharmony_ci nbno = bno; 215262306a36Sopenharmony_ci nlen = len; 215362306a36Sopenharmony_ci if ((error = xfs_btree_insert(bno_cur, &i))) 215462306a36Sopenharmony_ci goto error0; 215562306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 215662306a36Sopenharmony_ci error = -EFSCORRUPTED; 215762306a36Sopenharmony_ci goto error0; 215862306a36Sopenharmony_ci } 215962306a36Sopenharmony_ci } 216062306a36Sopenharmony_ci xfs_btree_del_cursor(bno_cur, XFS_BTREE_NOERROR); 216162306a36Sopenharmony_ci bno_cur = NULL; 216262306a36Sopenharmony_ci /* 216362306a36Sopenharmony_ci * In all cases we need to insert the new freespace in the by-size tree. 216462306a36Sopenharmony_ci */ 216562306a36Sopenharmony_ci if ((error = xfs_alloc_lookup_eq(cnt_cur, nbno, nlen, &i))) 216662306a36Sopenharmony_ci goto error0; 216762306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 0)) { 216862306a36Sopenharmony_ci error = -EFSCORRUPTED; 216962306a36Sopenharmony_ci goto error0; 217062306a36Sopenharmony_ci } 217162306a36Sopenharmony_ci if ((error = xfs_btree_insert(cnt_cur, &i))) 217262306a36Sopenharmony_ci goto error0; 217362306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, i != 1)) { 217462306a36Sopenharmony_ci error = -EFSCORRUPTED; 217562306a36Sopenharmony_ci goto error0; 217662306a36Sopenharmony_ci } 217762306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); 217862306a36Sopenharmony_ci cnt_cur = NULL; 217962306a36Sopenharmony_ci 218062306a36Sopenharmony_ci /* 218162306a36Sopenharmony_ci * Update the freespace totals in the ag and superblock. 218262306a36Sopenharmony_ci */ 218362306a36Sopenharmony_ci error = xfs_alloc_update_counters(tp, agbp, len); 218462306a36Sopenharmony_ci xfs_ag_resv_free_extent(agbp->b_pag, type, tp, len); 218562306a36Sopenharmony_ci if (error) 218662306a36Sopenharmony_ci goto error0; 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci XFS_STATS_INC(mp, xs_freex); 218962306a36Sopenharmony_ci XFS_STATS_ADD(mp, xs_freeb, len); 219062306a36Sopenharmony_ci 219162306a36Sopenharmony_ci trace_xfs_free_extent(mp, agno, bno, len, type, haveleft, haveright); 219262306a36Sopenharmony_ci 219362306a36Sopenharmony_ci return 0; 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci error0: 219662306a36Sopenharmony_ci trace_xfs_free_extent(mp, agno, bno, len, type, -1, -1); 219762306a36Sopenharmony_ci if (bno_cur) 219862306a36Sopenharmony_ci xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); 219962306a36Sopenharmony_ci if (cnt_cur) 220062306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, XFS_BTREE_ERROR); 220162306a36Sopenharmony_ci return error; 220262306a36Sopenharmony_ci} 220362306a36Sopenharmony_ci 220462306a36Sopenharmony_ci/* 220562306a36Sopenharmony_ci * Visible (exported) allocation/free functions. 220662306a36Sopenharmony_ci * Some of these are used just by xfs_alloc_btree.c and this file. 220762306a36Sopenharmony_ci */ 220862306a36Sopenharmony_ci 220962306a36Sopenharmony_ci/* 221062306a36Sopenharmony_ci * Compute and fill in value of m_alloc_maxlevels. 221162306a36Sopenharmony_ci */ 221262306a36Sopenharmony_civoid 221362306a36Sopenharmony_cixfs_alloc_compute_maxlevels( 221462306a36Sopenharmony_ci xfs_mount_t *mp) /* file system mount structure */ 221562306a36Sopenharmony_ci{ 221662306a36Sopenharmony_ci mp->m_alloc_maxlevels = xfs_btree_compute_maxlevels(mp->m_alloc_mnr, 221762306a36Sopenharmony_ci (mp->m_sb.sb_agblocks + 1) / 2); 221862306a36Sopenharmony_ci ASSERT(mp->m_alloc_maxlevels <= xfs_allocbt_maxlevels_ondisk()); 221962306a36Sopenharmony_ci} 222062306a36Sopenharmony_ci 222162306a36Sopenharmony_ci/* 222262306a36Sopenharmony_ci * Find the length of the longest extent in an AG. The 'need' parameter 222362306a36Sopenharmony_ci * specifies how much space we're going to need for the AGFL and the 222462306a36Sopenharmony_ci * 'reserved' parameter tells us how many blocks in this AG are reserved for 222562306a36Sopenharmony_ci * other callers. 222662306a36Sopenharmony_ci */ 222762306a36Sopenharmony_cixfs_extlen_t 222862306a36Sopenharmony_cixfs_alloc_longest_free_extent( 222962306a36Sopenharmony_ci struct xfs_perag *pag, 223062306a36Sopenharmony_ci xfs_extlen_t need, 223162306a36Sopenharmony_ci xfs_extlen_t reserved) 223262306a36Sopenharmony_ci{ 223362306a36Sopenharmony_ci xfs_extlen_t delta = 0; 223462306a36Sopenharmony_ci 223562306a36Sopenharmony_ci /* 223662306a36Sopenharmony_ci * If the AGFL needs a recharge, we'll have to subtract that from the 223762306a36Sopenharmony_ci * longest extent. 223862306a36Sopenharmony_ci */ 223962306a36Sopenharmony_ci if (need > pag->pagf_flcount) 224062306a36Sopenharmony_ci delta = need - pag->pagf_flcount; 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_ci /* 224362306a36Sopenharmony_ci * If we cannot maintain others' reservations with space from the 224462306a36Sopenharmony_ci * not-longest freesp extents, we'll have to subtract /that/ from 224562306a36Sopenharmony_ci * the longest extent too. 224662306a36Sopenharmony_ci */ 224762306a36Sopenharmony_ci if (pag->pagf_freeblks - pag->pagf_longest < reserved) 224862306a36Sopenharmony_ci delta += reserved - (pag->pagf_freeblks - pag->pagf_longest); 224962306a36Sopenharmony_ci 225062306a36Sopenharmony_ci /* 225162306a36Sopenharmony_ci * If the longest extent is long enough to satisfy all the 225262306a36Sopenharmony_ci * reservations and AGFL rules in place, we can return this extent. 225362306a36Sopenharmony_ci */ 225462306a36Sopenharmony_ci if (pag->pagf_longest > delta) 225562306a36Sopenharmony_ci return min_t(xfs_extlen_t, pag->pag_mount->m_ag_max_usable, 225662306a36Sopenharmony_ci pag->pagf_longest - delta); 225762306a36Sopenharmony_ci 225862306a36Sopenharmony_ci /* Otherwise, let the caller try for 1 block if there's space. */ 225962306a36Sopenharmony_ci return pag->pagf_flcount > 0 || pag->pagf_longest > 0; 226062306a36Sopenharmony_ci} 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci/* 226362306a36Sopenharmony_ci * Compute the minimum length of the AGFL in the given AG. If @pag is NULL, 226462306a36Sopenharmony_ci * return the largest possible minimum length. 226562306a36Sopenharmony_ci */ 226662306a36Sopenharmony_ciunsigned int 226762306a36Sopenharmony_cixfs_alloc_min_freelist( 226862306a36Sopenharmony_ci struct xfs_mount *mp, 226962306a36Sopenharmony_ci struct xfs_perag *pag) 227062306a36Sopenharmony_ci{ 227162306a36Sopenharmony_ci /* AG btrees have at least 1 level. */ 227262306a36Sopenharmony_ci static const uint8_t fake_levels[XFS_BTNUM_AGF] = {1, 1, 1}; 227362306a36Sopenharmony_ci const uint8_t *levels = pag ? pag->pagf_levels : fake_levels; 227462306a36Sopenharmony_ci unsigned int min_free; 227562306a36Sopenharmony_ci 227662306a36Sopenharmony_ci ASSERT(mp->m_alloc_maxlevels > 0); 227762306a36Sopenharmony_ci 227862306a36Sopenharmony_ci /* 227962306a36Sopenharmony_ci * For a btree shorter than the maximum height, the worst case is that 228062306a36Sopenharmony_ci * every level gets split and a new level is added, then while inserting 228162306a36Sopenharmony_ci * another entry to refill the AGFL, every level under the old root gets 228262306a36Sopenharmony_ci * split again. This is: 228362306a36Sopenharmony_ci * 228462306a36Sopenharmony_ci * (full height split reservation) + (AGFL refill split height) 228562306a36Sopenharmony_ci * = (current height + 1) + (current height - 1) 228662306a36Sopenharmony_ci * = (new height) + (new height - 2) 228762306a36Sopenharmony_ci * = 2 * new height - 2 228862306a36Sopenharmony_ci * 228962306a36Sopenharmony_ci * For a btree of maximum height, the worst case is that every level 229062306a36Sopenharmony_ci * under the root gets split, then while inserting another entry to 229162306a36Sopenharmony_ci * refill the AGFL, every level under the root gets split again. This is 229262306a36Sopenharmony_ci * also: 229362306a36Sopenharmony_ci * 229462306a36Sopenharmony_ci * 2 * (current height - 1) 229562306a36Sopenharmony_ci * = 2 * (new height - 1) 229662306a36Sopenharmony_ci * = 2 * new height - 2 229762306a36Sopenharmony_ci */ 229862306a36Sopenharmony_ci 229962306a36Sopenharmony_ci /* space needed by-bno freespace btree */ 230062306a36Sopenharmony_ci min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1, 230162306a36Sopenharmony_ci mp->m_alloc_maxlevels) * 2 - 2; 230262306a36Sopenharmony_ci /* space needed by-size freespace btree */ 230362306a36Sopenharmony_ci min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1, 230462306a36Sopenharmony_ci mp->m_alloc_maxlevels) * 2 - 2; 230562306a36Sopenharmony_ci /* space needed reverse mapping used space btree */ 230662306a36Sopenharmony_ci if (xfs_has_rmapbt(mp)) 230762306a36Sopenharmony_ci min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1, 230862306a36Sopenharmony_ci mp->m_rmap_maxlevels) * 2 - 2; 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_ci return min_free; 231162306a36Sopenharmony_ci} 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_ci/* 231462306a36Sopenharmony_ci * Check if the operation we are fixing up the freelist for should go ahead or 231562306a36Sopenharmony_ci * not. If we are freeing blocks, we always allow it, otherwise the allocation 231662306a36Sopenharmony_ci * is dependent on whether the size and shape of free space available will 231762306a36Sopenharmony_ci * permit the requested allocation to take place. 231862306a36Sopenharmony_ci */ 231962306a36Sopenharmony_cistatic bool 232062306a36Sopenharmony_cixfs_alloc_space_available( 232162306a36Sopenharmony_ci struct xfs_alloc_arg *args, 232262306a36Sopenharmony_ci xfs_extlen_t min_free, 232362306a36Sopenharmony_ci int flags) 232462306a36Sopenharmony_ci{ 232562306a36Sopenharmony_ci struct xfs_perag *pag = args->pag; 232662306a36Sopenharmony_ci xfs_extlen_t alloc_len, longest; 232762306a36Sopenharmony_ci xfs_extlen_t reservation; /* blocks that are still reserved */ 232862306a36Sopenharmony_ci int available; 232962306a36Sopenharmony_ci xfs_extlen_t agflcount; 233062306a36Sopenharmony_ci 233162306a36Sopenharmony_ci if (flags & XFS_ALLOC_FLAG_FREEING) 233262306a36Sopenharmony_ci return true; 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_ci reservation = xfs_ag_resv_needed(pag, args->resv); 233562306a36Sopenharmony_ci 233662306a36Sopenharmony_ci /* do we have enough contiguous free space for the allocation? */ 233762306a36Sopenharmony_ci alloc_len = args->minlen + (args->alignment - 1) + args->minalignslop; 233862306a36Sopenharmony_ci longest = xfs_alloc_longest_free_extent(pag, min_free, reservation); 233962306a36Sopenharmony_ci if (longest < alloc_len) 234062306a36Sopenharmony_ci return false; 234162306a36Sopenharmony_ci 234262306a36Sopenharmony_ci /* 234362306a36Sopenharmony_ci * Do we have enough free space remaining for the allocation? Don't 234462306a36Sopenharmony_ci * account extra agfl blocks because we are about to defer free them, 234562306a36Sopenharmony_ci * making them unavailable until the current transaction commits. 234662306a36Sopenharmony_ci */ 234762306a36Sopenharmony_ci agflcount = min_t(xfs_extlen_t, pag->pagf_flcount, min_free); 234862306a36Sopenharmony_ci available = (int)(pag->pagf_freeblks + agflcount - 234962306a36Sopenharmony_ci reservation - min_free - args->minleft); 235062306a36Sopenharmony_ci if (available < (int)max(args->total, alloc_len)) 235162306a36Sopenharmony_ci return false; 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci /* 235462306a36Sopenharmony_ci * Clamp maxlen to the amount of free space available for the actual 235562306a36Sopenharmony_ci * extent allocation. 235662306a36Sopenharmony_ci */ 235762306a36Sopenharmony_ci if (available < (int)args->maxlen && !(flags & XFS_ALLOC_FLAG_CHECK)) { 235862306a36Sopenharmony_ci args->maxlen = available; 235962306a36Sopenharmony_ci ASSERT(args->maxlen > 0); 236062306a36Sopenharmony_ci ASSERT(args->maxlen >= args->minlen); 236162306a36Sopenharmony_ci } 236262306a36Sopenharmony_ci 236362306a36Sopenharmony_ci return true; 236462306a36Sopenharmony_ci} 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_ciint 236762306a36Sopenharmony_cixfs_free_agfl_block( 236862306a36Sopenharmony_ci struct xfs_trans *tp, 236962306a36Sopenharmony_ci xfs_agnumber_t agno, 237062306a36Sopenharmony_ci xfs_agblock_t agbno, 237162306a36Sopenharmony_ci struct xfs_buf *agbp, 237262306a36Sopenharmony_ci struct xfs_owner_info *oinfo) 237362306a36Sopenharmony_ci{ 237462306a36Sopenharmony_ci int error; 237562306a36Sopenharmony_ci struct xfs_buf *bp; 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci error = xfs_free_ag_extent(tp, agbp, agno, agbno, 1, oinfo, 237862306a36Sopenharmony_ci XFS_AG_RESV_AGFL); 237962306a36Sopenharmony_ci if (error) 238062306a36Sopenharmony_ci return error; 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci error = xfs_trans_get_buf(tp, tp->t_mountp->m_ddev_targp, 238362306a36Sopenharmony_ci XFS_AGB_TO_DADDR(tp->t_mountp, agno, agbno), 238462306a36Sopenharmony_ci tp->t_mountp->m_bsize, 0, &bp); 238562306a36Sopenharmony_ci if (error) 238662306a36Sopenharmony_ci return error; 238762306a36Sopenharmony_ci xfs_trans_binval(tp, bp); 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci return 0; 239062306a36Sopenharmony_ci} 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci/* 239362306a36Sopenharmony_ci * Check the agfl fields of the agf for inconsistency or corruption. 239462306a36Sopenharmony_ci * 239562306a36Sopenharmony_ci * The original purpose was to detect an agfl header padding mismatch between 239662306a36Sopenharmony_ci * current and early v5 kernels. This problem manifests as a 1-slot size 239762306a36Sopenharmony_ci * difference between the on-disk flcount and the active [first, last] range of 239862306a36Sopenharmony_ci * a wrapped agfl. 239962306a36Sopenharmony_ci * 240062306a36Sopenharmony_ci * However, we need to use these same checks to catch agfl count corruptions 240162306a36Sopenharmony_ci * unrelated to padding. This could occur on any v4 or v5 filesystem, so either 240262306a36Sopenharmony_ci * way, we need to reset the agfl and warn the user. 240362306a36Sopenharmony_ci * 240462306a36Sopenharmony_ci * Return true if a reset is required before the agfl can be used, false 240562306a36Sopenharmony_ci * otherwise. 240662306a36Sopenharmony_ci */ 240762306a36Sopenharmony_cistatic bool 240862306a36Sopenharmony_cixfs_agfl_needs_reset( 240962306a36Sopenharmony_ci struct xfs_mount *mp, 241062306a36Sopenharmony_ci struct xfs_agf *agf) 241162306a36Sopenharmony_ci{ 241262306a36Sopenharmony_ci uint32_t f = be32_to_cpu(agf->agf_flfirst); 241362306a36Sopenharmony_ci uint32_t l = be32_to_cpu(agf->agf_fllast); 241462306a36Sopenharmony_ci uint32_t c = be32_to_cpu(agf->agf_flcount); 241562306a36Sopenharmony_ci int agfl_size = xfs_agfl_size(mp); 241662306a36Sopenharmony_ci int active; 241762306a36Sopenharmony_ci 241862306a36Sopenharmony_ci /* 241962306a36Sopenharmony_ci * The agf read verifier catches severe corruption of these fields. 242062306a36Sopenharmony_ci * Repeat some sanity checks to cover a packed -> unpacked mismatch if 242162306a36Sopenharmony_ci * the verifier allows it. 242262306a36Sopenharmony_ci */ 242362306a36Sopenharmony_ci if (f >= agfl_size || l >= agfl_size) 242462306a36Sopenharmony_ci return true; 242562306a36Sopenharmony_ci if (c > agfl_size) 242662306a36Sopenharmony_ci return true; 242762306a36Sopenharmony_ci 242862306a36Sopenharmony_ci /* 242962306a36Sopenharmony_ci * Check consistency between the on-disk count and the active range. An 243062306a36Sopenharmony_ci * agfl padding mismatch manifests as an inconsistent flcount. 243162306a36Sopenharmony_ci */ 243262306a36Sopenharmony_ci if (c && l >= f) 243362306a36Sopenharmony_ci active = l - f + 1; 243462306a36Sopenharmony_ci else if (c) 243562306a36Sopenharmony_ci active = agfl_size - f + l + 1; 243662306a36Sopenharmony_ci else 243762306a36Sopenharmony_ci active = 0; 243862306a36Sopenharmony_ci 243962306a36Sopenharmony_ci return active != c; 244062306a36Sopenharmony_ci} 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci/* 244362306a36Sopenharmony_ci * Reset the agfl to an empty state. Ignore/drop any existing blocks since the 244462306a36Sopenharmony_ci * agfl content cannot be trusted. Warn the user that a repair is required to 244562306a36Sopenharmony_ci * recover leaked blocks. 244662306a36Sopenharmony_ci * 244762306a36Sopenharmony_ci * The purpose of this mechanism is to handle filesystems affected by the agfl 244862306a36Sopenharmony_ci * header padding mismatch problem. A reset keeps the filesystem online with a 244962306a36Sopenharmony_ci * relatively minor free space accounting inconsistency rather than suffer the 245062306a36Sopenharmony_ci * inevitable crash from use of an invalid agfl block. 245162306a36Sopenharmony_ci */ 245262306a36Sopenharmony_cistatic void 245362306a36Sopenharmony_cixfs_agfl_reset( 245462306a36Sopenharmony_ci struct xfs_trans *tp, 245562306a36Sopenharmony_ci struct xfs_buf *agbp, 245662306a36Sopenharmony_ci struct xfs_perag *pag) 245762306a36Sopenharmony_ci{ 245862306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 245962306a36Sopenharmony_ci struct xfs_agf *agf = agbp->b_addr; 246062306a36Sopenharmony_ci 246162306a36Sopenharmony_ci ASSERT(xfs_perag_agfl_needs_reset(pag)); 246262306a36Sopenharmony_ci trace_xfs_agfl_reset(mp, agf, 0, _RET_IP_); 246362306a36Sopenharmony_ci 246462306a36Sopenharmony_ci xfs_warn(mp, 246562306a36Sopenharmony_ci "WARNING: Reset corrupted AGFL on AG %u. %d blocks leaked. " 246662306a36Sopenharmony_ci "Please unmount and run xfs_repair.", 246762306a36Sopenharmony_ci pag->pag_agno, pag->pagf_flcount); 246862306a36Sopenharmony_ci 246962306a36Sopenharmony_ci agf->agf_flfirst = 0; 247062306a36Sopenharmony_ci agf->agf_fllast = cpu_to_be32(xfs_agfl_size(mp) - 1); 247162306a36Sopenharmony_ci agf->agf_flcount = 0; 247262306a36Sopenharmony_ci xfs_alloc_log_agf(tp, agbp, XFS_AGF_FLFIRST | XFS_AGF_FLLAST | 247362306a36Sopenharmony_ci XFS_AGF_FLCOUNT); 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci pag->pagf_flcount = 0; 247662306a36Sopenharmony_ci clear_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate); 247762306a36Sopenharmony_ci} 247862306a36Sopenharmony_ci 247962306a36Sopenharmony_ci/* 248062306a36Sopenharmony_ci * Defer an AGFL block free. This is effectively equivalent to 248162306a36Sopenharmony_ci * xfs_free_extent_later() with some special handling particular to AGFL blocks. 248262306a36Sopenharmony_ci * 248362306a36Sopenharmony_ci * Deferring AGFL frees helps prevent log reservation overruns due to too many 248462306a36Sopenharmony_ci * allocation operations in a transaction. AGFL frees are prone to this problem 248562306a36Sopenharmony_ci * because for one they are always freed one at a time. Further, an immediate 248662306a36Sopenharmony_ci * AGFL block free can cause a btree join and require another block free before 248762306a36Sopenharmony_ci * the real allocation can proceed. Deferring the free disconnects freeing up 248862306a36Sopenharmony_ci * the AGFL slot from freeing the block. 248962306a36Sopenharmony_ci */ 249062306a36Sopenharmony_cistatic int 249162306a36Sopenharmony_cixfs_defer_agfl_block( 249262306a36Sopenharmony_ci struct xfs_trans *tp, 249362306a36Sopenharmony_ci xfs_agnumber_t agno, 249462306a36Sopenharmony_ci xfs_agblock_t agbno, 249562306a36Sopenharmony_ci struct xfs_owner_info *oinfo) 249662306a36Sopenharmony_ci{ 249762306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 249862306a36Sopenharmony_ci struct xfs_extent_free_item *xefi; 249962306a36Sopenharmony_ci xfs_fsblock_t fsbno = XFS_AGB_TO_FSB(mp, agno, agbno); 250062306a36Sopenharmony_ci 250162306a36Sopenharmony_ci ASSERT(xfs_extfree_item_cache != NULL); 250262306a36Sopenharmony_ci ASSERT(oinfo != NULL); 250362306a36Sopenharmony_ci 250462306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbno(mp, fsbno))) 250562306a36Sopenharmony_ci return -EFSCORRUPTED; 250662306a36Sopenharmony_ci 250762306a36Sopenharmony_ci xefi = kmem_cache_zalloc(xfs_extfree_item_cache, 250862306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOFAIL); 250962306a36Sopenharmony_ci xefi->xefi_startblock = fsbno; 251062306a36Sopenharmony_ci xefi->xefi_blockcount = 1; 251162306a36Sopenharmony_ci xefi->xefi_owner = oinfo->oi_owner; 251262306a36Sopenharmony_ci xefi->xefi_agresv = XFS_AG_RESV_AGFL; 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_ci trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1); 251562306a36Sopenharmony_ci 251662306a36Sopenharmony_ci xfs_extent_free_get_group(mp, xefi); 251762306a36Sopenharmony_ci xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_AGFL_FREE, &xefi->xefi_list); 251862306a36Sopenharmony_ci return 0; 251962306a36Sopenharmony_ci} 252062306a36Sopenharmony_ci 252162306a36Sopenharmony_ci/* 252262306a36Sopenharmony_ci * Add the extent to the list of extents to be free at transaction end. 252362306a36Sopenharmony_ci * The list is maintained sorted (by block number). 252462306a36Sopenharmony_ci */ 252562306a36Sopenharmony_ciint 252662306a36Sopenharmony_ci__xfs_free_extent_later( 252762306a36Sopenharmony_ci struct xfs_trans *tp, 252862306a36Sopenharmony_ci xfs_fsblock_t bno, 252962306a36Sopenharmony_ci xfs_filblks_t len, 253062306a36Sopenharmony_ci const struct xfs_owner_info *oinfo, 253162306a36Sopenharmony_ci enum xfs_ag_resv_type type, 253262306a36Sopenharmony_ci bool skip_discard) 253362306a36Sopenharmony_ci{ 253462306a36Sopenharmony_ci struct xfs_extent_free_item *xefi; 253562306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 253662306a36Sopenharmony_ci#ifdef DEBUG 253762306a36Sopenharmony_ci xfs_agnumber_t agno; 253862306a36Sopenharmony_ci xfs_agblock_t agbno; 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_ci ASSERT(bno != NULLFSBLOCK); 254162306a36Sopenharmony_ci ASSERT(len > 0); 254262306a36Sopenharmony_ci ASSERT(len <= XFS_MAX_BMBT_EXTLEN); 254362306a36Sopenharmony_ci ASSERT(!isnullstartblock(bno)); 254462306a36Sopenharmony_ci agno = XFS_FSB_TO_AGNO(mp, bno); 254562306a36Sopenharmony_ci agbno = XFS_FSB_TO_AGBNO(mp, bno); 254662306a36Sopenharmony_ci ASSERT(agno < mp->m_sb.sb_agcount); 254762306a36Sopenharmony_ci ASSERT(agbno < mp->m_sb.sb_agblocks); 254862306a36Sopenharmony_ci ASSERT(len < mp->m_sb.sb_agblocks); 254962306a36Sopenharmony_ci ASSERT(agbno + len <= mp->m_sb.sb_agblocks); 255062306a36Sopenharmony_ci#endif 255162306a36Sopenharmony_ci ASSERT(xfs_extfree_item_cache != NULL); 255262306a36Sopenharmony_ci ASSERT(type != XFS_AG_RESV_AGFL); 255362306a36Sopenharmony_ci 255462306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbext(mp, bno, len))) 255562306a36Sopenharmony_ci return -EFSCORRUPTED; 255662306a36Sopenharmony_ci 255762306a36Sopenharmony_ci xefi = kmem_cache_zalloc(xfs_extfree_item_cache, 255862306a36Sopenharmony_ci GFP_KERNEL | __GFP_NOFAIL); 255962306a36Sopenharmony_ci xefi->xefi_startblock = bno; 256062306a36Sopenharmony_ci xefi->xefi_blockcount = (xfs_extlen_t)len; 256162306a36Sopenharmony_ci xefi->xefi_agresv = type; 256262306a36Sopenharmony_ci if (skip_discard) 256362306a36Sopenharmony_ci xefi->xefi_flags |= XFS_EFI_SKIP_DISCARD; 256462306a36Sopenharmony_ci if (oinfo) { 256562306a36Sopenharmony_ci ASSERT(oinfo->oi_offset == 0); 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_ci if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK) 256862306a36Sopenharmony_ci xefi->xefi_flags |= XFS_EFI_ATTR_FORK; 256962306a36Sopenharmony_ci if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK) 257062306a36Sopenharmony_ci xefi->xefi_flags |= XFS_EFI_BMBT_BLOCK; 257162306a36Sopenharmony_ci xefi->xefi_owner = oinfo->oi_owner; 257262306a36Sopenharmony_ci } else { 257362306a36Sopenharmony_ci xefi->xefi_owner = XFS_RMAP_OWN_NULL; 257462306a36Sopenharmony_ci } 257562306a36Sopenharmony_ci trace_xfs_bmap_free_defer(mp, 257662306a36Sopenharmony_ci XFS_FSB_TO_AGNO(tp->t_mountp, bno), 0, 257762306a36Sopenharmony_ci XFS_FSB_TO_AGBNO(tp->t_mountp, bno), len); 257862306a36Sopenharmony_ci 257962306a36Sopenharmony_ci xfs_extent_free_get_group(mp, xefi); 258062306a36Sopenharmony_ci xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_FREE, &xefi->xefi_list); 258162306a36Sopenharmony_ci return 0; 258262306a36Sopenharmony_ci} 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_ci#ifdef DEBUG 258562306a36Sopenharmony_ci/* 258662306a36Sopenharmony_ci * Check if an AGF has a free extent record whose length is equal to 258762306a36Sopenharmony_ci * args->minlen. 258862306a36Sopenharmony_ci */ 258962306a36Sopenharmony_ciSTATIC int 259062306a36Sopenharmony_cixfs_exact_minlen_extent_available( 259162306a36Sopenharmony_ci struct xfs_alloc_arg *args, 259262306a36Sopenharmony_ci struct xfs_buf *agbp, 259362306a36Sopenharmony_ci int *stat) 259462306a36Sopenharmony_ci{ 259562306a36Sopenharmony_ci struct xfs_btree_cur *cnt_cur; 259662306a36Sopenharmony_ci xfs_agblock_t fbno; 259762306a36Sopenharmony_ci xfs_extlen_t flen; 259862306a36Sopenharmony_ci int error = 0; 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, agbp, 260162306a36Sopenharmony_ci args->pag, XFS_BTNUM_CNT); 260262306a36Sopenharmony_ci error = xfs_alloc_lookup_ge(cnt_cur, 0, args->minlen, stat); 260362306a36Sopenharmony_ci if (error) 260462306a36Sopenharmony_ci goto out; 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci if (*stat == 0) { 260762306a36Sopenharmony_ci error = -EFSCORRUPTED; 260862306a36Sopenharmony_ci goto out; 260962306a36Sopenharmony_ci } 261062306a36Sopenharmony_ci 261162306a36Sopenharmony_ci error = xfs_alloc_get_rec(cnt_cur, &fbno, &flen, stat); 261262306a36Sopenharmony_ci if (error) 261362306a36Sopenharmony_ci goto out; 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_ci if (*stat == 1 && flen != args->minlen) 261662306a36Sopenharmony_ci *stat = 0; 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ciout: 261962306a36Sopenharmony_ci xfs_btree_del_cursor(cnt_cur, error); 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci return error; 262262306a36Sopenharmony_ci} 262362306a36Sopenharmony_ci#endif 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci/* 262662306a36Sopenharmony_ci * Decide whether to use this allocation group for this allocation. 262762306a36Sopenharmony_ci * If so, fix up the btree freelist's size. 262862306a36Sopenharmony_ci */ 262962306a36Sopenharmony_ciint /* error */ 263062306a36Sopenharmony_cixfs_alloc_fix_freelist( 263162306a36Sopenharmony_ci struct xfs_alloc_arg *args, /* allocation argument structure */ 263262306a36Sopenharmony_ci uint32_t alloc_flags) 263362306a36Sopenharmony_ci{ 263462306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 263562306a36Sopenharmony_ci struct xfs_perag *pag = args->pag; 263662306a36Sopenharmony_ci struct xfs_trans *tp = args->tp; 263762306a36Sopenharmony_ci struct xfs_buf *agbp = NULL; 263862306a36Sopenharmony_ci struct xfs_buf *agflbp = NULL; 263962306a36Sopenharmony_ci struct xfs_alloc_arg targs; /* local allocation arguments */ 264062306a36Sopenharmony_ci xfs_agblock_t bno; /* freelist block */ 264162306a36Sopenharmony_ci xfs_extlen_t need; /* total blocks needed in freelist */ 264262306a36Sopenharmony_ci int error = 0; 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_ci /* deferred ops (AGFL block frees) require permanent transactions */ 264562306a36Sopenharmony_ci ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 264662306a36Sopenharmony_ci 264762306a36Sopenharmony_ci if (!xfs_perag_initialised_agf(pag)) { 264862306a36Sopenharmony_ci error = xfs_alloc_read_agf(pag, tp, alloc_flags, &agbp); 264962306a36Sopenharmony_ci if (error) { 265062306a36Sopenharmony_ci /* Couldn't lock the AGF so skip this AG. */ 265162306a36Sopenharmony_ci if (error == -EAGAIN) 265262306a36Sopenharmony_ci error = 0; 265362306a36Sopenharmony_ci goto out_no_agbp; 265462306a36Sopenharmony_ci } 265562306a36Sopenharmony_ci } 265662306a36Sopenharmony_ci 265762306a36Sopenharmony_ci /* 265862306a36Sopenharmony_ci * If this is a metadata preferred pag and we are user data then try 265962306a36Sopenharmony_ci * somewhere else if we are not being asked to try harder at this 266062306a36Sopenharmony_ci * point 266162306a36Sopenharmony_ci */ 266262306a36Sopenharmony_ci if (xfs_perag_prefers_metadata(pag) && 266362306a36Sopenharmony_ci (args->datatype & XFS_ALLOC_USERDATA) && 266462306a36Sopenharmony_ci (alloc_flags & XFS_ALLOC_FLAG_TRYLOCK)) { 266562306a36Sopenharmony_ci ASSERT(!(alloc_flags & XFS_ALLOC_FLAG_FREEING)); 266662306a36Sopenharmony_ci goto out_agbp_relse; 266762306a36Sopenharmony_ci } 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci need = xfs_alloc_min_freelist(mp, pag); 267062306a36Sopenharmony_ci if (!xfs_alloc_space_available(args, need, alloc_flags | 267162306a36Sopenharmony_ci XFS_ALLOC_FLAG_CHECK)) 267262306a36Sopenharmony_ci goto out_agbp_relse; 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci /* 267562306a36Sopenharmony_ci * Get the a.g. freespace buffer. 267662306a36Sopenharmony_ci * Can fail if we're not blocking on locks, and it's held. 267762306a36Sopenharmony_ci */ 267862306a36Sopenharmony_ci if (!agbp) { 267962306a36Sopenharmony_ci error = xfs_alloc_read_agf(pag, tp, alloc_flags, &agbp); 268062306a36Sopenharmony_ci if (error) { 268162306a36Sopenharmony_ci /* Couldn't lock the AGF so skip this AG. */ 268262306a36Sopenharmony_ci if (error == -EAGAIN) 268362306a36Sopenharmony_ci error = 0; 268462306a36Sopenharmony_ci goto out_no_agbp; 268562306a36Sopenharmony_ci } 268662306a36Sopenharmony_ci } 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_ci /* reset a padding mismatched agfl before final free space check */ 268962306a36Sopenharmony_ci if (xfs_perag_agfl_needs_reset(pag)) 269062306a36Sopenharmony_ci xfs_agfl_reset(tp, agbp, pag); 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci /* If there isn't enough total space or single-extent, reject it. */ 269362306a36Sopenharmony_ci need = xfs_alloc_min_freelist(mp, pag); 269462306a36Sopenharmony_ci if (!xfs_alloc_space_available(args, need, alloc_flags)) 269562306a36Sopenharmony_ci goto out_agbp_relse; 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci#ifdef DEBUG 269862306a36Sopenharmony_ci if (args->alloc_minlen_only) { 269962306a36Sopenharmony_ci int stat; 270062306a36Sopenharmony_ci 270162306a36Sopenharmony_ci error = xfs_exact_minlen_extent_available(args, agbp, &stat); 270262306a36Sopenharmony_ci if (error || !stat) 270362306a36Sopenharmony_ci goto out_agbp_relse; 270462306a36Sopenharmony_ci } 270562306a36Sopenharmony_ci#endif 270662306a36Sopenharmony_ci /* 270762306a36Sopenharmony_ci * Make the freelist shorter if it's too long. 270862306a36Sopenharmony_ci * 270962306a36Sopenharmony_ci * Note that from this point onwards, we will always release the agf and 271062306a36Sopenharmony_ci * agfl buffers on error. This handles the case where we error out and 271162306a36Sopenharmony_ci * the buffers are clean or may not have been joined to the transaction 271262306a36Sopenharmony_ci * and hence need to be released manually. If they have been joined to 271362306a36Sopenharmony_ci * the transaction, then xfs_trans_brelse() will handle them 271462306a36Sopenharmony_ci * appropriately based on the recursion count and dirty state of the 271562306a36Sopenharmony_ci * buffer. 271662306a36Sopenharmony_ci * 271762306a36Sopenharmony_ci * XXX (dgc): When we have lots of free space, does this buy us 271862306a36Sopenharmony_ci * anything other than extra overhead when we need to put more blocks 271962306a36Sopenharmony_ci * back on the free list? Maybe we should only do this when space is 272062306a36Sopenharmony_ci * getting low or the AGFL is more than half full? 272162306a36Sopenharmony_ci * 272262306a36Sopenharmony_ci * The NOSHRINK flag prevents the AGFL from being shrunk if it's too 272362306a36Sopenharmony_ci * big; the NORMAP flag prevents AGFL expand/shrink operations from 272462306a36Sopenharmony_ci * updating the rmapbt. Both flags are used in xfs_repair while we're 272562306a36Sopenharmony_ci * rebuilding the rmapbt, and neither are used by the kernel. They're 272662306a36Sopenharmony_ci * both required to ensure that rmaps are correctly recorded for the 272762306a36Sopenharmony_ci * regenerated AGFL, bnobt, and cntbt. See repair/phase5.c and 272862306a36Sopenharmony_ci * repair/rmap.c in xfsprogs for details. 272962306a36Sopenharmony_ci */ 273062306a36Sopenharmony_ci memset(&targs, 0, sizeof(targs)); 273162306a36Sopenharmony_ci /* struct copy below */ 273262306a36Sopenharmony_ci if (alloc_flags & XFS_ALLOC_FLAG_NORMAP) 273362306a36Sopenharmony_ci targs.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE; 273462306a36Sopenharmony_ci else 273562306a36Sopenharmony_ci targs.oinfo = XFS_RMAP_OINFO_AG; 273662306a36Sopenharmony_ci while (!(alloc_flags & XFS_ALLOC_FLAG_NOSHRINK) && 273762306a36Sopenharmony_ci pag->pagf_flcount > need) { 273862306a36Sopenharmony_ci error = xfs_alloc_get_freelist(pag, tp, agbp, &bno, 0); 273962306a36Sopenharmony_ci if (error) 274062306a36Sopenharmony_ci goto out_agbp_relse; 274162306a36Sopenharmony_ci 274262306a36Sopenharmony_ci /* defer agfl frees */ 274362306a36Sopenharmony_ci error = xfs_defer_agfl_block(tp, args->agno, bno, &targs.oinfo); 274462306a36Sopenharmony_ci if (error) 274562306a36Sopenharmony_ci goto out_agbp_relse; 274662306a36Sopenharmony_ci } 274762306a36Sopenharmony_ci 274862306a36Sopenharmony_ci targs.tp = tp; 274962306a36Sopenharmony_ci targs.mp = mp; 275062306a36Sopenharmony_ci targs.agbp = agbp; 275162306a36Sopenharmony_ci targs.agno = args->agno; 275262306a36Sopenharmony_ci targs.alignment = targs.minlen = targs.prod = 1; 275362306a36Sopenharmony_ci targs.pag = pag; 275462306a36Sopenharmony_ci error = xfs_alloc_read_agfl(pag, tp, &agflbp); 275562306a36Sopenharmony_ci if (error) 275662306a36Sopenharmony_ci goto out_agbp_relse; 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci /* Make the freelist longer if it's too short. */ 275962306a36Sopenharmony_ci while (pag->pagf_flcount < need) { 276062306a36Sopenharmony_ci targs.agbno = 0; 276162306a36Sopenharmony_ci targs.maxlen = need - pag->pagf_flcount; 276262306a36Sopenharmony_ci targs.resv = XFS_AG_RESV_AGFL; 276362306a36Sopenharmony_ci 276462306a36Sopenharmony_ci /* Allocate as many blocks as possible at once. */ 276562306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_size(&targs, alloc_flags); 276662306a36Sopenharmony_ci if (error) 276762306a36Sopenharmony_ci goto out_agflbp_relse; 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_ci /* 277062306a36Sopenharmony_ci * Stop if we run out. Won't happen if callers are obeying 277162306a36Sopenharmony_ci * the restrictions correctly. Can happen for free calls 277262306a36Sopenharmony_ci * on a completely full ag. 277362306a36Sopenharmony_ci */ 277462306a36Sopenharmony_ci if (targs.agbno == NULLAGBLOCK) { 277562306a36Sopenharmony_ci if (alloc_flags & XFS_ALLOC_FLAG_FREEING) 277662306a36Sopenharmony_ci break; 277762306a36Sopenharmony_ci goto out_agflbp_relse; 277862306a36Sopenharmony_ci } 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_ci if (!xfs_rmap_should_skip_owner_update(&targs.oinfo)) { 278162306a36Sopenharmony_ci error = xfs_rmap_alloc(tp, agbp, pag, 278262306a36Sopenharmony_ci targs.agbno, targs.len, &targs.oinfo); 278362306a36Sopenharmony_ci if (error) 278462306a36Sopenharmony_ci goto out_agflbp_relse; 278562306a36Sopenharmony_ci } 278662306a36Sopenharmony_ci error = xfs_alloc_update_counters(tp, agbp, 278762306a36Sopenharmony_ci -((long)(targs.len))); 278862306a36Sopenharmony_ci if (error) 278962306a36Sopenharmony_ci goto out_agflbp_relse; 279062306a36Sopenharmony_ci 279162306a36Sopenharmony_ci /* 279262306a36Sopenharmony_ci * Put each allocated block on the list. 279362306a36Sopenharmony_ci */ 279462306a36Sopenharmony_ci for (bno = targs.agbno; bno < targs.agbno + targs.len; bno++) { 279562306a36Sopenharmony_ci error = xfs_alloc_put_freelist(pag, tp, agbp, 279662306a36Sopenharmony_ci agflbp, bno, 0); 279762306a36Sopenharmony_ci if (error) 279862306a36Sopenharmony_ci goto out_agflbp_relse; 279962306a36Sopenharmony_ci } 280062306a36Sopenharmony_ci } 280162306a36Sopenharmony_ci xfs_trans_brelse(tp, agflbp); 280262306a36Sopenharmony_ci args->agbp = agbp; 280362306a36Sopenharmony_ci return 0; 280462306a36Sopenharmony_ci 280562306a36Sopenharmony_ciout_agflbp_relse: 280662306a36Sopenharmony_ci xfs_trans_brelse(tp, agflbp); 280762306a36Sopenharmony_ciout_agbp_relse: 280862306a36Sopenharmony_ci if (agbp) 280962306a36Sopenharmony_ci xfs_trans_brelse(tp, agbp); 281062306a36Sopenharmony_ciout_no_agbp: 281162306a36Sopenharmony_ci args->agbp = NULL; 281262306a36Sopenharmony_ci return error; 281362306a36Sopenharmony_ci} 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_ci/* 281662306a36Sopenharmony_ci * Get a block from the freelist. 281762306a36Sopenharmony_ci * Returns with the buffer for the block gotten. 281862306a36Sopenharmony_ci */ 281962306a36Sopenharmony_ciint 282062306a36Sopenharmony_cixfs_alloc_get_freelist( 282162306a36Sopenharmony_ci struct xfs_perag *pag, 282262306a36Sopenharmony_ci struct xfs_trans *tp, 282362306a36Sopenharmony_ci struct xfs_buf *agbp, 282462306a36Sopenharmony_ci xfs_agblock_t *bnop, 282562306a36Sopenharmony_ci int btreeblk) 282662306a36Sopenharmony_ci{ 282762306a36Sopenharmony_ci struct xfs_agf *agf = agbp->b_addr; 282862306a36Sopenharmony_ci struct xfs_buf *agflbp; 282962306a36Sopenharmony_ci xfs_agblock_t bno; 283062306a36Sopenharmony_ci __be32 *agfl_bno; 283162306a36Sopenharmony_ci int error; 283262306a36Sopenharmony_ci uint32_t logflags; 283362306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 283462306a36Sopenharmony_ci 283562306a36Sopenharmony_ci /* 283662306a36Sopenharmony_ci * Freelist is empty, give up. 283762306a36Sopenharmony_ci */ 283862306a36Sopenharmony_ci if (!agf->agf_flcount) { 283962306a36Sopenharmony_ci *bnop = NULLAGBLOCK; 284062306a36Sopenharmony_ci return 0; 284162306a36Sopenharmony_ci } 284262306a36Sopenharmony_ci /* 284362306a36Sopenharmony_ci * Read the array of free blocks. 284462306a36Sopenharmony_ci */ 284562306a36Sopenharmony_ci error = xfs_alloc_read_agfl(pag, tp, &agflbp); 284662306a36Sopenharmony_ci if (error) 284762306a36Sopenharmony_ci return error; 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_ci 285062306a36Sopenharmony_ci /* 285162306a36Sopenharmony_ci * Get the block number and update the data structures. 285262306a36Sopenharmony_ci */ 285362306a36Sopenharmony_ci agfl_bno = xfs_buf_to_agfl_bno(agflbp); 285462306a36Sopenharmony_ci bno = be32_to_cpu(agfl_bno[be32_to_cpu(agf->agf_flfirst)]); 285562306a36Sopenharmony_ci if (XFS_IS_CORRUPT(tp->t_mountp, !xfs_verify_agbno(pag, bno))) 285662306a36Sopenharmony_ci return -EFSCORRUPTED; 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci be32_add_cpu(&agf->agf_flfirst, 1); 285962306a36Sopenharmony_ci xfs_trans_brelse(tp, agflbp); 286062306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_flfirst) == xfs_agfl_size(mp)) 286162306a36Sopenharmony_ci agf->agf_flfirst = 0; 286262306a36Sopenharmony_ci 286362306a36Sopenharmony_ci ASSERT(!xfs_perag_agfl_needs_reset(pag)); 286462306a36Sopenharmony_ci be32_add_cpu(&agf->agf_flcount, -1); 286562306a36Sopenharmony_ci pag->pagf_flcount--; 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_ci logflags = XFS_AGF_FLFIRST | XFS_AGF_FLCOUNT; 286862306a36Sopenharmony_ci if (btreeblk) { 286962306a36Sopenharmony_ci be32_add_cpu(&agf->agf_btreeblks, 1); 287062306a36Sopenharmony_ci pag->pagf_btreeblks++; 287162306a36Sopenharmony_ci logflags |= XFS_AGF_BTREEBLKS; 287262306a36Sopenharmony_ci } 287362306a36Sopenharmony_ci 287462306a36Sopenharmony_ci xfs_alloc_log_agf(tp, agbp, logflags); 287562306a36Sopenharmony_ci *bnop = bno; 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ci return 0; 287862306a36Sopenharmony_ci} 287962306a36Sopenharmony_ci 288062306a36Sopenharmony_ci/* 288162306a36Sopenharmony_ci * Log the given fields from the agf structure. 288262306a36Sopenharmony_ci */ 288362306a36Sopenharmony_civoid 288462306a36Sopenharmony_cixfs_alloc_log_agf( 288562306a36Sopenharmony_ci struct xfs_trans *tp, 288662306a36Sopenharmony_ci struct xfs_buf *bp, 288762306a36Sopenharmony_ci uint32_t fields) 288862306a36Sopenharmony_ci{ 288962306a36Sopenharmony_ci int first; /* first byte offset */ 289062306a36Sopenharmony_ci int last; /* last byte offset */ 289162306a36Sopenharmony_ci static const short offsets[] = { 289262306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_magicnum), 289362306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_versionnum), 289462306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_seqno), 289562306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_length), 289662306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_roots[0]), 289762306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_levels[0]), 289862306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_flfirst), 289962306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_fllast), 290062306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_flcount), 290162306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_freeblks), 290262306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_longest), 290362306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_btreeblks), 290462306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_uuid), 290562306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_rmap_blocks), 290662306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_refcount_blocks), 290762306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_refcount_root), 290862306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_refcount_level), 290962306a36Sopenharmony_ci /* needed so that we don't log the whole rest of the structure: */ 291062306a36Sopenharmony_ci offsetof(xfs_agf_t, agf_spare64), 291162306a36Sopenharmony_ci sizeof(xfs_agf_t) 291262306a36Sopenharmony_ci }; 291362306a36Sopenharmony_ci 291462306a36Sopenharmony_ci trace_xfs_agf(tp->t_mountp, bp->b_addr, fields, _RET_IP_); 291562306a36Sopenharmony_ci 291662306a36Sopenharmony_ci xfs_trans_buf_set_type(tp, bp, XFS_BLFT_AGF_BUF); 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci xfs_btree_offsets(fields, offsets, XFS_AGF_NUM_BITS, &first, &last); 291962306a36Sopenharmony_ci xfs_trans_log_buf(tp, bp, (uint)first, (uint)last); 292062306a36Sopenharmony_ci} 292162306a36Sopenharmony_ci 292262306a36Sopenharmony_ci/* 292362306a36Sopenharmony_ci * Put the block on the freelist for the allocation group. 292462306a36Sopenharmony_ci */ 292562306a36Sopenharmony_ciint 292662306a36Sopenharmony_cixfs_alloc_put_freelist( 292762306a36Sopenharmony_ci struct xfs_perag *pag, 292862306a36Sopenharmony_ci struct xfs_trans *tp, 292962306a36Sopenharmony_ci struct xfs_buf *agbp, 293062306a36Sopenharmony_ci struct xfs_buf *agflbp, 293162306a36Sopenharmony_ci xfs_agblock_t bno, 293262306a36Sopenharmony_ci int btreeblk) 293362306a36Sopenharmony_ci{ 293462306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 293562306a36Sopenharmony_ci struct xfs_agf *agf = agbp->b_addr; 293662306a36Sopenharmony_ci __be32 *blockp; 293762306a36Sopenharmony_ci int error; 293862306a36Sopenharmony_ci uint32_t logflags; 293962306a36Sopenharmony_ci __be32 *agfl_bno; 294062306a36Sopenharmony_ci int startoff; 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_ci if (!agflbp) { 294362306a36Sopenharmony_ci error = xfs_alloc_read_agfl(pag, tp, &agflbp); 294462306a36Sopenharmony_ci if (error) 294562306a36Sopenharmony_ci return error; 294662306a36Sopenharmony_ci } 294762306a36Sopenharmony_ci 294862306a36Sopenharmony_ci be32_add_cpu(&agf->agf_fllast, 1); 294962306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_fllast) == xfs_agfl_size(mp)) 295062306a36Sopenharmony_ci agf->agf_fllast = 0; 295162306a36Sopenharmony_ci 295262306a36Sopenharmony_ci ASSERT(!xfs_perag_agfl_needs_reset(pag)); 295362306a36Sopenharmony_ci be32_add_cpu(&agf->agf_flcount, 1); 295462306a36Sopenharmony_ci pag->pagf_flcount++; 295562306a36Sopenharmony_ci 295662306a36Sopenharmony_ci logflags = XFS_AGF_FLLAST | XFS_AGF_FLCOUNT; 295762306a36Sopenharmony_ci if (btreeblk) { 295862306a36Sopenharmony_ci be32_add_cpu(&agf->agf_btreeblks, -1); 295962306a36Sopenharmony_ci pag->pagf_btreeblks--; 296062306a36Sopenharmony_ci logflags |= XFS_AGF_BTREEBLKS; 296162306a36Sopenharmony_ci } 296262306a36Sopenharmony_ci 296362306a36Sopenharmony_ci xfs_alloc_log_agf(tp, agbp, logflags); 296462306a36Sopenharmony_ci 296562306a36Sopenharmony_ci ASSERT(be32_to_cpu(agf->agf_flcount) <= xfs_agfl_size(mp)); 296662306a36Sopenharmony_ci 296762306a36Sopenharmony_ci agfl_bno = xfs_buf_to_agfl_bno(agflbp); 296862306a36Sopenharmony_ci blockp = &agfl_bno[be32_to_cpu(agf->agf_fllast)]; 296962306a36Sopenharmony_ci *blockp = cpu_to_be32(bno); 297062306a36Sopenharmony_ci startoff = (char *)blockp - (char *)agflbp->b_addr; 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci xfs_alloc_log_agf(tp, agbp, logflags); 297362306a36Sopenharmony_ci 297462306a36Sopenharmony_ci xfs_trans_buf_set_type(tp, agflbp, XFS_BLFT_AGFL_BUF); 297562306a36Sopenharmony_ci xfs_trans_log_buf(tp, agflbp, startoff, 297662306a36Sopenharmony_ci startoff + sizeof(xfs_agblock_t) - 1); 297762306a36Sopenharmony_ci return 0; 297862306a36Sopenharmony_ci} 297962306a36Sopenharmony_ci 298062306a36Sopenharmony_ci/* 298162306a36Sopenharmony_ci * Check that this AGF/AGI header's sequence number and length matches the AG 298262306a36Sopenharmony_ci * number and size in fsblocks. 298362306a36Sopenharmony_ci */ 298462306a36Sopenharmony_cixfs_failaddr_t 298562306a36Sopenharmony_cixfs_validate_ag_length( 298662306a36Sopenharmony_ci struct xfs_buf *bp, 298762306a36Sopenharmony_ci uint32_t seqno, 298862306a36Sopenharmony_ci uint32_t length) 298962306a36Sopenharmony_ci{ 299062306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 299162306a36Sopenharmony_ci /* 299262306a36Sopenharmony_ci * During growfs operations, the perag is not fully initialised, 299362306a36Sopenharmony_ci * so we can't use it for any useful checking. growfs ensures we can't 299462306a36Sopenharmony_ci * use it by using uncached buffers that don't have the perag attached 299562306a36Sopenharmony_ci * so we can detect and avoid this problem. 299662306a36Sopenharmony_ci */ 299762306a36Sopenharmony_ci if (bp->b_pag && seqno != bp->b_pag->pag_agno) 299862306a36Sopenharmony_ci return __this_address; 299962306a36Sopenharmony_ci 300062306a36Sopenharmony_ci /* 300162306a36Sopenharmony_ci * Only the last AG in the filesystem is allowed to be shorter 300262306a36Sopenharmony_ci * than the AG size recorded in the superblock. 300362306a36Sopenharmony_ci */ 300462306a36Sopenharmony_ci if (length != mp->m_sb.sb_agblocks) { 300562306a36Sopenharmony_ci /* 300662306a36Sopenharmony_ci * During growfs, the new last AG can get here before we 300762306a36Sopenharmony_ci * have updated the superblock. Give it a pass on the seqno 300862306a36Sopenharmony_ci * check. 300962306a36Sopenharmony_ci */ 301062306a36Sopenharmony_ci if (bp->b_pag && seqno != mp->m_sb.sb_agcount - 1) 301162306a36Sopenharmony_ci return __this_address; 301262306a36Sopenharmony_ci if (length < XFS_MIN_AG_BLOCKS) 301362306a36Sopenharmony_ci return __this_address; 301462306a36Sopenharmony_ci if (length > mp->m_sb.sb_agblocks) 301562306a36Sopenharmony_ci return __this_address; 301662306a36Sopenharmony_ci } 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_ci return NULL; 301962306a36Sopenharmony_ci} 302062306a36Sopenharmony_ci 302162306a36Sopenharmony_ci/* 302262306a36Sopenharmony_ci * Verify the AGF is consistent. 302362306a36Sopenharmony_ci * 302462306a36Sopenharmony_ci * We do not verify the AGFL indexes in the AGF are fully consistent here 302562306a36Sopenharmony_ci * because of issues with variable on-disk structure sizes. Instead, we check 302662306a36Sopenharmony_ci * the agfl indexes for consistency when we initialise the perag from the AGF 302762306a36Sopenharmony_ci * information after a read completes. 302862306a36Sopenharmony_ci * 302962306a36Sopenharmony_ci * If the index is inconsistent, then we mark the perag as needing an AGFL 303062306a36Sopenharmony_ci * reset. The first AGFL update performed then resets the AGFL indexes and 303162306a36Sopenharmony_ci * refills the AGFL with known good free blocks, allowing the filesystem to 303262306a36Sopenharmony_ci * continue operating normally at the cost of a few leaked free space blocks. 303362306a36Sopenharmony_ci */ 303462306a36Sopenharmony_cistatic xfs_failaddr_t 303562306a36Sopenharmony_cixfs_agf_verify( 303662306a36Sopenharmony_ci struct xfs_buf *bp) 303762306a36Sopenharmony_ci{ 303862306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 303962306a36Sopenharmony_ci struct xfs_agf *agf = bp->b_addr; 304062306a36Sopenharmony_ci xfs_failaddr_t fa; 304162306a36Sopenharmony_ci uint32_t agf_seqno = be32_to_cpu(agf->agf_seqno); 304262306a36Sopenharmony_ci uint32_t agf_length = be32_to_cpu(agf->agf_length); 304362306a36Sopenharmony_ci 304462306a36Sopenharmony_ci if (xfs_has_crc(mp)) { 304562306a36Sopenharmony_ci if (!uuid_equal(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid)) 304662306a36Sopenharmony_ci return __this_address; 304762306a36Sopenharmony_ci if (!xfs_log_check_lsn(mp, be64_to_cpu(agf->agf_lsn))) 304862306a36Sopenharmony_ci return __this_address; 304962306a36Sopenharmony_ci } 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_ci if (!xfs_verify_magic(bp, agf->agf_magicnum)) 305262306a36Sopenharmony_ci return __this_address; 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci if (!XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum))) 305562306a36Sopenharmony_ci return __this_address; 305662306a36Sopenharmony_ci 305762306a36Sopenharmony_ci /* 305862306a36Sopenharmony_ci * Both agf_seqno and agf_length need to validated before anything else 305962306a36Sopenharmony_ci * block number related in the AGF or AGFL can be checked. 306062306a36Sopenharmony_ci */ 306162306a36Sopenharmony_ci fa = xfs_validate_ag_length(bp, agf_seqno, agf_length); 306262306a36Sopenharmony_ci if (fa) 306362306a36Sopenharmony_ci return fa; 306462306a36Sopenharmony_ci 306562306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_flfirst) >= xfs_agfl_size(mp)) 306662306a36Sopenharmony_ci return __this_address; 306762306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_fllast) >= xfs_agfl_size(mp)) 306862306a36Sopenharmony_ci return __this_address; 306962306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_flcount) > xfs_agfl_size(mp)) 307062306a36Sopenharmony_ci return __this_address; 307162306a36Sopenharmony_ci 307262306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_freeblks) < be32_to_cpu(agf->agf_longest) || 307362306a36Sopenharmony_ci be32_to_cpu(agf->agf_freeblks) > agf_length) 307462306a36Sopenharmony_ci return __this_address; 307562306a36Sopenharmony_ci 307662306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) < 1 || 307762306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) < 1 || 307862306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]) > 307962306a36Sopenharmony_ci mp->m_alloc_maxlevels || 308062306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > 308162306a36Sopenharmony_ci mp->m_alloc_maxlevels) 308262306a36Sopenharmony_ci return __this_address; 308362306a36Sopenharmony_ci 308462306a36Sopenharmony_ci if (xfs_has_lazysbcount(mp) && 308562306a36Sopenharmony_ci be32_to_cpu(agf->agf_btreeblks) > agf_length) 308662306a36Sopenharmony_ci return __this_address; 308762306a36Sopenharmony_ci 308862306a36Sopenharmony_ci if (xfs_has_rmapbt(mp)) { 308962306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_rmap_blocks) > agf_length) 309062306a36Sopenharmony_ci return __this_address; 309162306a36Sopenharmony_ci 309262306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) < 1 || 309362306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > 309462306a36Sopenharmony_ci mp->m_rmap_maxlevels) 309562306a36Sopenharmony_ci return __this_address; 309662306a36Sopenharmony_ci } 309762306a36Sopenharmony_ci 309862306a36Sopenharmony_ci if (xfs_has_reflink(mp)) { 309962306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_refcount_blocks) > agf_length) 310062306a36Sopenharmony_ci return __this_address; 310162306a36Sopenharmony_ci 310262306a36Sopenharmony_ci if (be32_to_cpu(agf->agf_refcount_level) < 1 || 310362306a36Sopenharmony_ci be32_to_cpu(agf->agf_refcount_level) > mp->m_refc_maxlevels) 310462306a36Sopenharmony_ci return __this_address; 310562306a36Sopenharmony_ci } 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_ci return NULL; 310862306a36Sopenharmony_ci} 310962306a36Sopenharmony_ci 311062306a36Sopenharmony_cistatic void 311162306a36Sopenharmony_cixfs_agf_read_verify( 311262306a36Sopenharmony_ci struct xfs_buf *bp) 311362306a36Sopenharmony_ci{ 311462306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 311562306a36Sopenharmony_ci xfs_failaddr_t fa; 311662306a36Sopenharmony_ci 311762306a36Sopenharmony_ci if (xfs_has_crc(mp) && 311862306a36Sopenharmony_ci !xfs_buf_verify_cksum(bp, XFS_AGF_CRC_OFF)) 311962306a36Sopenharmony_ci xfs_verifier_error(bp, -EFSBADCRC, __this_address); 312062306a36Sopenharmony_ci else { 312162306a36Sopenharmony_ci fa = xfs_agf_verify(bp); 312262306a36Sopenharmony_ci if (XFS_TEST_ERROR(fa, mp, XFS_ERRTAG_ALLOC_READ_AGF)) 312362306a36Sopenharmony_ci xfs_verifier_error(bp, -EFSCORRUPTED, fa); 312462306a36Sopenharmony_ci } 312562306a36Sopenharmony_ci} 312662306a36Sopenharmony_ci 312762306a36Sopenharmony_cistatic void 312862306a36Sopenharmony_cixfs_agf_write_verify( 312962306a36Sopenharmony_ci struct xfs_buf *bp) 313062306a36Sopenharmony_ci{ 313162306a36Sopenharmony_ci struct xfs_mount *mp = bp->b_mount; 313262306a36Sopenharmony_ci struct xfs_buf_log_item *bip = bp->b_log_item; 313362306a36Sopenharmony_ci struct xfs_agf *agf = bp->b_addr; 313462306a36Sopenharmony_ci xfs_failaddr_t fa; 313562306a36Sopenharmony_ci 313662306a36Sopenharmony_ci fa = xfs_agf_verify(bp); 313762306a36Sopenharmony_ci if (fa) { 313862306a36Sopenharmony_ci xfs_verifier_error(bp, -EFSCORRUPTED, fa); 313962306a36Sopenharmony_ci return; 314062306a36Sopenharmony_ci } 314162306a36Sopenharmony_ci 314262306a36Sopenharmony_ci if (!xfs_has_crc(mp)) 314362306a36Sopenharmony_ci return; 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci if (bip) 314662306a36Sopenharmony_ci agf->agf_lsn = cpu_to_be64(bip->bli_item.li_lsn); 314762306a36Sopenharmony_ci 314862306a36Sopenharmony_ci xfs_buf_update_cksum(bp, XFS_AGF_CRC_OFF); 314962306a36Sopenharmony_ci} 315062306a36Sopenharmony_ci 315162306a36Sopenharmony_ciconst struct xfs_buf_ops xfs_agf_buf_ops = { 315262306a36Sopenharmony_ci .name = "xfs_agf", 315362306a36Sopenharmony_ci .magic = { cpu_to_be32(XFS_AGF_MAGIC), cpu_to_be32(XFS_AGF_MAGIC) }, 315462306a36Sopenharmony_ci .verify_read = xfs_agf_read_verify, 315562306a36Sopenharmony_ci .verify_write = xfs_agf_write_verify, 315662306a36Sopenharmony_ci .verify_struct = xfs_agf_verify, 315762306a36Sopenharmony_ci}; 315862306a36Sopenharmony_ci 315962306a36Sopenharmony_ci/* 316062306a36Sopenharmony_ci * Read in the allocation group header (free/alloc section). 316162306a36Sopenharmony_ci */ 316262306a36Sopenharmony_ciint 316362306a36Sopenharmony_cixfs_read_agf( 316462306a36Sopenharmony_ci struct xfs_perag *pag, 316562306a36Sopenharmony_ci struct xfs_trans *tp, 316662306a36Sopenharmony_ci int flags, 316762306a36Sopenharmony_ci struct xfs_buf **agfbpp) 316862306a36Sopenharmony_ci{ 316962306a36Sopenharmony_ci struct xfs_mount *mp = pag->pag_mount; 317062306a36Sopenharmony_ci int error; 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci trace_xfs_read_agf(pag->pag_mount, pag->pag_agno); 317362306a36Sopenharmony_ci 317462306a36Sopenharmony_ci error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, 317562306a36Sopenharmony_ci XFS_AG_DADDR(mp, pag->pag_agno, XFS_AGF_DADDR(mp)), 317662306a36Sopenharmony_ci XFS_FSS_TO_BB(mp, 1), flags, agfbpp, &xfs_agf_buf_ops); 317762306a36Sopenharmony_ci if (error) 317862306a36Sopenharmony_ci return error; 317962306a36Sopenharmony_ci 318062306a36Sopenharmony_ci xfs_buf_set_ref(*agfbpp, XFS_AGF_REF); 318162306a36Sopenharmony_ci return 0; 318262306a36Sopenharmony_ci} 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci/* 318562306a36Sopenharmony_ci * Read in the allocation group header (free/alloc section) and initialise the 318662306a36Sopenharmony_ci * perag structure if necessary. If the caller provides @agfbpp, then return the 318762306a36Sopenharmony_ci * locked buffer to the caller, otherwise free it. 318862306a36Sopenharmony_ci */ 318962306a36Sopenharmony_ciint 319062306a36Sopenharmony_cixfs_alloc_read_agf( 319162306a36Sopenharmony_ci struct xfs_perag *pag, 319262306a36Sopenharmony_ci struct xfs_trans *tp, 319362306a36Sopenharmony_ci int flags, 319462306a36Sopenharmony_ci struct xfs_buf **agfbpp) 319562306a36Sopenharmony_ci{ 319662306a36Sopenharmony_ci struct xfs_buf *agfbp; 319762306a36Sopenharmony_ci struct xfs_agf *agf; 319862306a36Sopenharmony_ci int error; 319962306a36Sopenharmony_ci int allocbt_blks; 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_ci trace_xfs_alloc_read_agf(pag->pag_mount, pag->pag_agno); 320262306a36Sopenharmony_ci 320362306a36Sopenharmony_ci /* We don't support trylock when freeing. */ 320462306a36Sopenharmony_ci ASSERT((flags & (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)) != 320562306a36Sopenharmony_ci (XFS_ALLOC_FLAG_FREEING | XFS_ALLOC_FLAG_TRYLOCK)); 320662306a36Sopenharmony_ci error = xfs_read_agf(pag, tp, 320762306a36Sopenharmony_ci (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XBF_TRYLOCK : 0, 320862306a36Sopenharmony_ci &agfbp); 320962306a36Sopenharmony_ci if (error) 321062306a36Sopenharmony_ci return error; 321162306a36Sopenharmony_ci 321262306a36Sopenharmony_ci agf = agfbp->b_addr; 321362306a36Sopenharmony_ci if (!xfs_perag_initialised_agf(pag)) { 321462306a36Sopenharmony_ci pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks); 321562306a36Sopenharmony_ci pag->pagf_btreeblks = be32_to_cpu(agf->agf_btreeblks); 321662306a36Sopenharmony_ci pag->pagf_flcount = be32_to_cpu(agf->agf_flcount); 321762306a36Sopenharmony_ci pag->pagf_longest = be32_to_cpu(agf->agf_longest); 321862306a36Sopenharmony_ci pag->pagf_levels[XFS_BTNUM_BNOi] = 321962306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]); 322062306a36Sopenharmony_ci pag->pagf_levels[XFS_BTNUM_CNTi] = 322162306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); 322262306a36Sopenharmony_ci pag->pagf_levels[XFS_BTNUM_RMAPi] = 322362306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); 322462306a36Sopenharmony_ci pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level); 322562306a36Sopenharmony_ci if (xfs_agfl_needs_reset(pag->pag_mount, agf)) 322662306a36Sopenharmony_ci set_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate); 322762306a36Sopenharmony_ci else 322862306a36Sopenharmony_ci clear_bit(XFS_AGSTATE_AGFL_NEEDS_RESET, &pag->pag_opstate); 322962306a36Sopenharmony_ci 323062306a36Sopenharmony_ci /* 323162306a36Sopenharmony_ci * Update the in-core allocbt counter. Filter out the rmapbt 323262306a36Sopenharmony_ci * subset of the btreeblks counter because the rmapbt is managed 323362306a36Sopenharmony_ci * by perag reservation. Subtract one for the rmapbt root block 323462306a36Sopenharmony_ci * because the rmap counter includes it while the btreeblks 323562306a36Sopenharmony_ci * counter only tracks non-root blocks. 323662306a36Sopenharmony_ci */ 323762306a36Sopenharmony_ci allocbt_blks = pag->pagf_btreeblks; 323862306a36Sopenharmony_ci if (xfs_has_rmapbt(pag->pag_mount)) 323962306a36Sopenharmony_ci allocbt_blks -= be32_to_cpu(agf->agf_rmap_blocks) - 1; 324062306a36Sopenharmony_ci if (allocbt_blks > 0) 324162306a36Sopenharmony_ci atomic64_add(allocbt_blks, 324262306a36Sopenharmony_ci &pag->pag_mount->m_allocbt_blks); 324362306a36Sopenharmony_ci 324462306a36Sopenharmony_ci set_bit(XFS_AGSTATE_AGF_INIT, &pag->pag_opstate); 324562306a36Sopenharmony_ci } 324662306a36Sopenharmony_ci#ifdef DEBUG 324762306a36Sopenharmony_ci else if (!xfs_is_shutdown(pag->pag_mount)) { 324862306a36Sopenharmony_ci ASSERT(pag->pagf_freeblks == be32_to_cpu(agf->agf_freeblks)); 324962306a36Sopenharmony_ci ASSERT(pag->pagf_btreeblks == be32_to_cpu(agf->agf_btreeblks)); 325062306a36Sopenharmony_ci ASSERT(pag->pagf_flcount == be32_to_cpu(agf->agf_flcount)); 325162306a36Sopenharmony_ci ASSERT(pag->pagf_longest == be32_to_cpu(agf->agf_longest)); 325262306a36Sopenharmony_ci ASSERT(pag->pagf_levels[XFS_BTNUM_BNOi] == 325362306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi])); 325462306a36Sopenharmony_ci ASSERT(pag->pagf_levels[XFS_BTNUM_CNTi] == 325562306a36Sopenharmony_ci be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); 325662306a36Sopenharmony_ci } 325762306a36Sopenharmony_ci#endif 325862306a36Sopenharmony_ci if (agfbpp) 325962306a36Sopenharmony_ci *agfbpp = agfbp; 326062306a36Sopenharmony_ci else 326162306a36Sopenharmony_ci xfs_trans_brelse(tp, agfbp); 326262306a36Sopenharmony_ci return 0; 326362306a36Sopenharmony_ci} 326462306a36Sopenharmony_ci 326562306a36Sopenharmony_ci/* 326662306a36Sopenharmony_ci * Pre-proces allocation arguments to set initial state that we don't require 326762306a36Sopenharmony_ci * callers to set up correctly, as well as bounds check the allocation args 326862306a36Sopenharmony_ci * that are set up. 326962306a36Sopenharmony_ci */ 327062306a36Sopenharmony_cistatic int 327162306a36Sopenharmony_cixfs_alloc_vextent_check_args( 327262306a36Sopenharmony_ci struct xfs_alloc_arg *args, 327362306a36Sopenharmony_ci xfs_fsblock_t target, 327462306a36Sopenharmony_ci xfs_agnumber_t *minimum_agno) 327562306a36Sopenharmony_ci{ 327662306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 327762306a36Sopenharmony_ci xfs_agblock_t agsize; 327862306a36Sopenharmony_ci 327962306a36Sopenharmony_ci args->fsbno = NULLFSBLOCK; 328062306a36Sopenharmony_ci 328162306a36Sopenharmony_ci *minimum_agno = 0; 328262306a36Sopenharmony_ci if (args->tp->t_highest_agno != NULLAGNUMBER) 328362306a36Sopenharmony_ci *minimum_agno = args->tp->t_highest_agno; 328462306a36Sopenharmony_ci 328562306a36Sopenharmony_ci /* 328662306a36Sopenharmony_ci * Just fix this up, for the case where the last a.g. is shorter 328762306a36Sopenharmony_ci * (or there's only one a.g.) and the caller couldn't easily figure 328862306a36Sopenharmony_ci * that out (xfs_bmap_alloc). 328962306a36Sopenharmony_ci */ 329062306a36Sopenharmony_ci agsize = mp->m_sb.sb_agblocks; 329162306a36Sopenharmony_ci if (args->maxlen > agsize) 329262306a36Sopenharmony_ci args->maxlen = agsize; 329362306a36Sopenharmony_ci if (args->alignment == 0) 329462306a36Sopenharmony_ci args->alignment = 1; 329562306a36Sopenharmony_ci 329662306a36Sopenharmony_ci ASSERT(args->minlen > 0); 329762306a36Sopenharmony_ci ASSERT(args->maxlen > 0); 329862306a36Sopenharmony_ci ASSERT(args->alignment > 0); 329962306a36Sopenharmony_ci ASSERT(args->resv != XFS_AG_RESV_AGFL); 330062306a36Sopenharmony_ci 330162306a36Sopenharmony_ci ASSERT(XFS_FSB_TO_AGNO(mp, target) < mp->m_sb.sb_agcount); 330262306a36Sopenharmony_ci ASSERT(XFS_FSB_TO_AGBNO(mp, target) < agsize); 330362306a36Sopenharmony_ci ASSERT(args->minlen <= args->maxlen); 330462306a36Sopenharmony_ci ASSERT(args->minlen <= agsize); 330562306a36Sopenharmony_ci ASSERT(args->mod < args->prod); 330662306a36Sopenharmony_ci 330762306a36Sopenharmony_ci if (XFS_FSB_TO_AGNO(mp, target) >= mp->m_sb.sb_agcount || 330862306a36Sopenharmony_ci XFS_FSB_TO_AGBNO(mp, target) >= agsize || 330962306a36Sopenharmony_ci args->minlen > args->maxlen || args->minlen > agsize || 331062306a36Sopenharmony_ci args->mod >= args->prod) { 331162306a36Sopenharmony_ci trace_xfs_alloc_vextent_badargs(args); 331262306a36Sopenharmony_ci return -ENOSPC; 331362306a36Sopenharmony_ci } 331462306a36Sopenharmony_ci 331562306a36Sopenharmony_ci if (args->agno != NULLAGNUMBER && *minimum_agno > args->agno) { 331662306a36Sopenharmony_ci trace_xfs_alloc_vextent_skip_deadlock(args); 331762306a36Sopenharmony_ci return -ENOSPC; 331862306a36Sopenharmony_ci } 331962306a36Sopenharmony_ci return 0; 332062306a36Sopenharmony_ci 332162306a36Sopenharmony_ci} 332262306a36Sopenharmony_ci 332362306a36Sopenharmony_ci/* 332462306a36Sopenharmony_ci * Prepare an AG for allocation. If the AG is not prepared to accept the 332562306a36Sopenharmony_ci * allocation, return failure. 332662306a36Sopenharmony_ci * 332762306a36Sopenharmony_ci * XXX(dgc): The complexity of "need_pag" will go away as all caller paths are 332862306a36Sopenharmony_ci * modified to hold their own perag references. 332962306a36Sopenharmony_ci */ 333062306a36Sopenharmony_cistatic int 333162306a36Sopenharmony_cixfs_alloc_vextent_prepare_ag( 333262306a36Sopenharmony_ci struct xfs_alloc_arg *args, 333362306a36Sopenharmony_ci uint32_t alloc_flags) 333462306a36Sopenharmony_ci{ 333562306a36Sopenharmony_ci bool need_pag = !args->pag; 333662306a36Sopenharmony_ci int error; 333762306a36Sopenharmony_ci 333862306a36Sopenharmony_ci if (need_pag) 333962306a36Sopenharmony_ci args->pag = xfs_perag_get(args->mp, args->agno); 334062306a36Sopenharmony_ci 334162306a36Sopenharmony_ci args->agbp = NULL; 334262306a36Sopenharmony_ci error = xfs_alloc_fix_freelist(args, alloc_flags); 334362306a36Sopenharmony_ci if (error) { 334462306a36Sopenharmony_ci trace_xfs_alloc_vextent_nofix(args); 334562306a36Sopenharmony_ci if (need_pag) 334662306a36Sopenharmony_ci xfs_perag_put(args->pag); 334762306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 334862306a36Sopenharmony_ci return error; 334962306a36Sopenharmony_ci } 335062306a36Sopenharmony_ci if (!args->agbp) { 335162306a36Sopenharmony_ci /* cannot allocate in this AG at all */ 335262306a36Sopenharmony_ci trace_xfs_alloc_vextent_noagbp(args); 335362306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 335462306a36Sopenharmony_ci return 0; 335562306a36Sopenharmony_ci } 335662306a36Sopenharmony_ci args->wasfromfl = 0; 335762306a36Sopenharmony_ci return 0; 335862306a36Sopenharmony_ci} 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ci/* 336162306a36Sopenharmony_ci * Post-process allocation results to account for the allocation if it succeed 336262306a36Sopenharmony_ci * and set the allocated block number correctly for the caller. 336362306a36Sopenharmony_ci * 336462306a36Sopenharmony_ci * XXX: we should really be returning ENOSPC for ENOSPC, not 336562306a36Sopenharmony_ci * hiding it behind a "successful" NULLFSBLOCK allocation. 336662306a36Sopenharmony_ci */ 336762306a36Sopenharmony_cistatic int 336862306a36Sopenharmony_cixfs_alloc_vextent_finish( 336962306a36Sopenharmony_ci struct xfs_alloc_arg *args, 337062306a36Sopenharmony_ci xfs_agnumber_t minimum_agno, 337162306a36Sopenharmony_ci int alloc_error, 337262306a36Sopenharmony_ci bool drop_perag) 337362306a36Sopenharmony_ci{ 337462306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 337562306a36Sopenharmony_ci int error = 0; 337662306a36Sopenharmony_ci 337762306a36Sopenharmony_ci /* 337862306a36Sopenharmony_ci * We can end up here with a locked AGF. If we failed, the caller is 337962306a36Sopenharmony_ci * likely going to try to allocate again with different parameters, and 338062306a36Sopenharmony_ci * that can widen the AGs that are searched for free space. If we have 338162306a36Sopenharmony_ci * to do BMBT block allocation, we have to do a new allocation. 338262306a36Sopenharmony_ci * 338362306a36Sopenharmony_ci * Hence leaving this function with the AGF locked opens up potential 338462306a36Sopenharmony_ci * ABBA AGF deadlocks because a future allocation attempt in this 338562306a36Sopenharmony_ci * transaction may attempt to lock a lower number AGF. 338662306a36Sopenharmony_ci * 338762306a36Sopenharmony_ci * We can't release the AGF until the transaction is commited, so at 338862306a36Sopenharmony_ci * this point we must update the "first allocation" tracker to point at 338962306a36Sopenharmony_ci * this AG if the tracker is empty or points to a lower AG. This allows 339062306a36Sopenharmony_ci * the next allocation attempt to be modified appropriately to avoid 339162306a36Sopenharmony_ci * deadlocks. 339262306a36Sopenharmony_ci */ 339362306a36Sopenharmony_ci if (args->agbp && 339462306a36Sopenharmony_ci (args->tp->t_highest_agno == NULLAGNUMBER || 339562306a36Sopenharmony_ci args->agno > minimum_agno)) 339662306a36Sopenharmony_ci args->tp->t_highest_agno = args->agno; 339762306a36Sopenharmony_ci 339862306a36Sopenharmony_ci /* 339962306a36Sopenharmony_ci * If the allocation failed with an error or we had an ENOSPC result, 340062306a36Sopenharmony_ci * preserve the returned error whilst also marking the allocation result 340162306a36Sopenharmony_ci * as "no extent allocated". This ensures that callers that fail to 340262306a36Sopenharmony_ci * capture the error will still treat it as a failed allocation. 340362306a36Sopenharmony_ci */ 340462306a36Sopenharmony_ci if (alloc_error || args->agbno == NULLAGBLOCK) { 340562306a36Sopenharmony_ci args->fsbno = NULLFSBLOCK; 340662306a36Sopenharmony_ci error = alloc_error; 340762306a36Sopenharmony_ci goto out_drop_perag; 340862306a36Sopenharmony_ci } 340962306a36Sopenharmony_ci 341062306a36Sopenharmony_ci args->fsbno = XFS_AGB_TO_FSB(mp, args->agno, args->agbno); 341162306a36Sopenharmony_ci 341262306a36Sopenharmony_ci ASSERT(args->len >= args->minlen); 341362306a36Sopenharmony_ci ASSERT(args->len <= args->maxlen); 341462306a36Sopenharmony_ci ASSERT(args->agbno % args->alignment == 0); 341562306a36Sopenharmony_ci XFS_AG_CHECK_DADDR(mp, XFS_FSB_TO_DADDR(mp, args->fsbno), args->len); 341662306a36Sopenharmony_ci 341762306a36Sopenharmony_ci /* if not file data, insert new block into the reverse map btree */ 341862306a36Sopenharmony_ci if (!xfs_rmap_should_skip_owner_update(&args->oinfo)) { 341962306a36Sopenharmony_ci error = xfs_rmap_alloc(args->tp, args->agbp, args->pag, 342062306a36Sopenharmony_ci args->agbno, args->len, &args->oinfo); 342162306a36Sopenharmony_ci if (error) 342262306a36Sopenharmony_ci goto out_drop_perag; 342362306a36Sopenharmony_ci } 342462306a36Sopenharmony_ci 342562306a36Sopenharmony_ci if (!args->wasfromfl) { 342662306a36Sopenharmony_ci error = xfs_alloc_update_counters(args->tp, args->agbp, 342762306a36Sopenharmony_ci -((long)(args->len))); 342862306a36Sopenharmony_ci if (error) 342962306a36Sopenharmony_ci goto out_drop_perag; 343062306a36Sopenharmony_ci 343162306a36Sopenharmony_ci ASSERT(!xfs_extent_busy_search(mp, args->pag, args->agbno, 343262306a36Sopenharmony_ci args->len)); 343362306a36Sopenharmony_ci } 343462306a36Sopenharmony_ci 343562306a36Sopenharmony_ci xfs_ag_resv_alloc_extent(args->pag, args->resv, args); 343662306a36Sopenharmony_ci 343762306a36Sopenharmony_ci XFS_STATS_INC(mp, xs_allocx); 343862306a36Sopenharmony_ci XFS_STATS_ADD(mp, xs_allocb, args->len); 343962306a36Sopenharmony_ci 344062306a36Sopenharmony_ci trace_xfs_alloc_vextent_finish(args); 344162306a36Sopenharmony_ci 344262306a36Sopenharmony_ciout_drop_perag: 344362306a36Sopenharmony_ci if (drop_perag && args->pag) { 344462306a36Sopenharmony_ci xfs_perag_rele(args->pag); 344562306a36Sopenharmony_ci args->pag = NULL; 344662306a36Sopenharmony_ci } 344762306a36Sopenharmony_ci return error; 344862306a36Sopenharmony_ci} 344962306a36Sopenharmony_ci 345062306a36Sopenharmony_ci/* 345162306a36Sopenharmony_ci * Allocate within a single AG only. This uses a best-fit length algorithm so if 345262306a36Sopenharmony_ci * you need an exact sized allocation without locality constraints, this is the 345362306a36Sopenharmony_ci * fastest way to do it. 345462306a36Sopenharmony_ci * 345562306a36Sopenharmony_ci * Caller is expected to hold a perag reference in args->pag. 345662306a36Sopenharmony_ci */ 345762306a36Sopenharmony_ciint 345862306a36Sopenharmony_cixfs_alloc_vextent_this_ag( 345962306a36Sopenharmony_ci struct xfs_alloc_arg *args, 346062306a36Sopenharmony_ci xfs_agnumber_t agno) 346162306a36Sopenharmony_ci{ 346262306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 346362306a36Sopenharmony_ci xfs_agnumber_t minimum_agno; 346462306a36Sopenharmony_ci uint32_t alloc_flags = 0; 346562306a36Sopenharmony_ci int error; 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_ci ASSERT(args->pag != NULL); 346862306a36Sopenharmony_ci ASSERT(args->pag->pag_agno == agno); 346962306a36Sopenharmony_ci 347062306a36Sopenharmony_ci args->agno = agno; 347162306a36Sopenharmony_ci args->agbno = 0; 347262306a36Sopenharmony_ci 347362306a36Sopenharmony_ci trace_xfs_alloc_vextent_this_ag(args); 347462306a36Sopenharmony_ci 347562306a36Sopenharmony_ci error = xfs_alloc_vextent_check_args(args, XFS_AGB_TO_FSB(mp, agno, 0), 347662306a36Sopenharmony_ci &minimum_agno); 347762306a36Sopenharmony_ci if (error) { 347862306a36Sopenharmony_ci if (error == -ENOSPC) 347962306a36Sopenharmony_ci return 0; 348062306a36Sopenharmony_ci return error; 348162306a36Sopenharmony_ci } 348262306a36Sopenharmony_ci 348362306a36Sopenharmony_ci error = xfs_alloc_vextent_prepare_ag(args, alloc_flags); 348462306a36Sopenharmony_ci if (!error && args->agbp) 348562306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_size(args, alloc_flags); 348662306a36Sopenharmony_ci 348762306a36Sopenharmony_ci return xfs_alloc_vextent_finish(args, minimum_agno, error, false); 348862306a36Sopenharmony_ci} 348962306a36Sopenharmony_ci 349062306a36Sopenharmony_ci/* 349162306a36Sopenharmony_ci * Iterate all AGs trying to allocate an extent starting from @start_ag. 349262306a36Sopenharmony_ci * 349362306a36Sopenharmony_ci * If the incoming allocation type is XFS_ALLOCTYPE_NEAR_BNO, it means the 349462306a36Sopenharmony_ci * allocation attempts in @start_agno have locality information. If we fail to 349562306a36Sopenharmony_ci * allocate in that AG, then we revert to anywhere-in-AG for all the other AGs 349662306a36Sopenharmony_ci * we attempt to allocation in as there is no locality optimisation possible for 349762306a36Sopenharmony_ci * those allocations. 349862306a36Sopenharmony_ci * 349962306a36Sopenharmony_ci * On return, args->pag may be left referenced if we finish before the "all 350062306a36Sopenharmony_ci * failed" return point. The allocation finish still needs the perag, and 350162306a36Sopenharmony_ci * so the caller will release it once they've finished the allocation. 350262306a36Sopenharmony_ci * 350362306a36Sopenharmony_ci * When we wrap the AG iteration at the end of the filesystem, we have to be 350462306a36Sopenharmony_ci * careful not to wrap into AGs below ones we already have locked in the 350562306a36Sopenharmony_ci * transaction if we are doing a blocking iteration. This will result in an 350662306a36Sopenharmony_ci * out-of-order locking of AGFs and hence can cause deadlocks. 350762306a36Sopenharmony_ci */ 350862306a36Sopenharmony_cistatic int 350962306a36Sopenharmony_cixfs_alloc_vextent_iterate_ags( 351062306a36Sopenharmony_ci struct xfs_alloc_arg *args, 351162306a36Sopenharmony_ci xfs_agnumber_t minimum_agno, 351262306a36Sopenharmony_ci xfs_agnumber_t start_agno, 351362306a36Sopenharmony_ci xfs_agblock_t target_agbno, 351462306a36Sopenharmony_ci uint32_t alloc_flags) 351562306a36Sopenharmony_ci{ 351662306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 351762306a36Sopenharmony_ci xfs_agnumber_t restart_agno = minimum_agno; 351862306a36Sopenharmony_ci xfs_agnumber_t agno; 351962306a36Sopenharmony_ci int error = 0; 352062306a36Sopenharmony_ci 352162306a36Sopenharmony_ci if (alloc_flags & XFS_ALLOC_FLAG_TRYLOCK) 352262306a36Sopenharmony_ci restart_agno = 0; 352362306a36Sopenharmony_cirestart: 352462306a36Sopenharmony_ci for_each_perag_wrap_range(mp, start_agno, restart_agno, 352562306a36Sopenharmony_ci mp->m_sb.sb_agcount, agno, args->pag) { 352662306a36Sopenharmony_ci args->agno = agno; 352762306a36Sopenharmony_ci error = xfs_alloc_vextent_prepare_ag(args, alloc_flags); 352862306a36Sopenharmony_ci if (error) 352962306a36Sopenharmony_ci break; 353062306a36Sopenharmony_ci if (!args->agbp) { 353162306a36Sopenharmony_ci trace_xfs_alloc_vextent_loopfailed(args); 353262306a36Sopenharmony_ci continue; 353362306a36Sopenharmony_ci } 353462306a36Sopenharmony_ci 353562306a36Sopenharmony_ci /* 353662306a36Sopenharmony_ci * Allocation is supposed to succeed now, so break out of the 353762306a36Sopenharmony_ci * loop regardless of whether we succeed or not. 353862306a36Sopenharmony_ci */ 353962306a36Sopenharmony_ci if (args->agno == start_agno && target_agbno) { 354062306a36Sopenharmony_ci args->agbno = target_agbno; 354162306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_near(args, alloc_flags); 354262306a36Sopenharmony_ci } else { 354362306a36Sopenharmony_ci args->agbno = 0; 354462306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_size(args, alloc_flags); 354562306a36Sopenharmony_ci } 354662306a36Sopenharmony_ci break; 354762306a36Sopenharmony_ci } 354862306a36Sopenharmony_ci if (error) { 354962306a36Sopenharmony_ci xfs_perag_rele(args->pag); 355062306a36Sopenharmony_ci args->pag = NULL; 355162306a36Sopenharmony_ci return error; 355262306a36Sopenharmony_ci } 355362306a36Sopenharmony_ci if (args->agbp) 355462306a36Sopenharmony_ci return 0; 355562306a36Sopenharmony_ci 355662306a36Sopenharmony_ci /* 355762306a36Sopenharmony_ci * We didn't find an AG we can alloation from. If we were given 355862306a36Sopenharmony_ci * constraining flags by the caller, drop them and retry the allocation 355962306a36Sopenharmony_ci * without any constraints being set. 356062306a36Sopenharmony_ci */ 356162306a36Sopenharmony_ci if (alloc_flags & XFS_ALLOC_FLAG_TRYLOCK) { 356262306a36Sopenharmony_ci alloc_flags &= ~XFS_ALLOC_FLAG_TRYLOCK; 356362306a36Sopenharmony_ci restart_agno = minimum_agno; 356462306a36Sopenharmony_ci goto restart; 356562306a36Sopenharmony_ci } 356662306a36Sopenharmony_ci 356762306a36Sopenharmony_ci ASSERT(args->pag == NULL); 356862306a36Sopenharmony_ci trace_xfs_alloc_vextent_allfailed(args); 356962306a36Sopenharmony_ci return 0; 357062306a36Sopenharmony_ci} 357162306a36Sopenharmony_ci 357262306a36Sopenharmony_ci/* 357362306a36Sopenharmony_ci * Iterate from the AGs from the start AG to the end of the filesystem, trying 357462306a36Sopenharmony_ci * to allocate blocks. It starts with a near allocation attempt in the initial 357562306a36Sopenharmony_ci * AG, then falls back to anywhere-in-ag after the first AG fails. It will wrap 357662306a36Sopenharmony_ci * back to zero if allowed by previous allocations in this transaction, 357762306a36Sopenharmony_ci * otherwise will wrap back to the start AG and run a second blocking pass to 357862306a36Sopenharmony_ci * the end of the filesystem. 357962306a36Sopenharmony_ci */ 358062306a36Sopenharmony_ciint 358162306a36Sopenharmony_cixfs_alloc_vextent_start_ag( 358262306a36Sopenharmony_ci struct xfs_alloc_arg *args, 358362306a36Sopenharmony_ci xfs_fsblock_t target) 358462306a36Sopenharmony_ci{ 358562306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 358662306a36Sopenharmony_ci xfs_agnumber_t minimum_agno; 358762306a36Sopenharmony_ci xfs_agnumber_t start_agno; 358862306a36Sopenharmony_ci xfs_agnumber_t rotorstep = xfs_rotorstep; 358962306a36Sopenharmony_ci bool bump_rotor = false; 359062306a36Sopenharmony_ci uint32_t alloc_flags = XFS_ALLOC_FLAG_TRYLOCK; 359162306a36Sopenharmony_ci int error; 359262306a36Sopenharmony_ci 359362306a36Sopenharmony_ci ASSERT(args->pag == NULL); 359462306a36Sopenharmony_ci 359562306a36Sopenharmony_ci args->agno = NULLAGNUMBER; 359662306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 359762306a36Sopenharmony_ci 359862306a36Sopenharmony_ci trace_xfs_alloc_vextent_start_ag(args); 359962306a36Sopenharmony_ci 360062306a36Sopenharmony_ci error = xfs_alloc_vextent_check_args(args, target, &minimum_agno); 360162306a36Sopenharmony_ci if (error) { 360262306a36Sopenharmony_ci if (error == -ENOSPC) 360362306a36Sopenharmony_ci return 0; 360462306a36Sopenharmony_ci return error; 360562306a36Sopenharmony_ci } 360662306a36Sopenharmony_ci 360762306a36Sopenharmony_ci if ((args->datatype & XFS_ALLOC_INITIAL_USER_DATA) && 360862306a36Sopenharmony_ci xfs_is_inode32(mp)) { 360962306a36Sopenharmony_ci target = XFS_AGB_TO_FSB(mp, 361062306a36Sopenharmony_ci ((mp->m_agfrotor / rotorstep) % 361162306a36Sopenharmony_ci mp->m_sb.sb_agcount), 0); 361262306a36Sopenharmony_ci bump_rotor = 1; 361362306a36Sopenharmony_ci } 361462306a36Sopenharmony_ci 361562306a36Sopenharmony_ci start_agno = max(minimum_agno, XFS_FSB_TO_AGNO(mp, target)); 361662306a36Sopenharmony_ci error = xfs_alloc_vextent_iterate_ags(args, minimum_agno, start_agno, 361762306a36Sopenharmony_ci XFS_FSB_TO_AGBNO(mp, target), alloc_flags); 361862306a36Sopenharmony_ci 361962306a36Sopenharmony_ci if (bump_rotor) { 362062306a36Sopenharmony_ci if (args->agno == start_agno) 362162306a36Sopenharmony_ci mp->m_agfrotor = (mp->m_agfrotor + 1) % 362262306a36Sopenharmony_ci (mp->m_sb.sb_agcount * rotorstep); 362362306a36Sopenharmony_ci else 362462306a36Sopenharmony_ci mp->m_agfrotor = (args->agno * rotorstep + 1) % 362562306a36Sopenharmony_ci (mp->m_sb.sb_agcount * rotorstep); 362662306a36Sopenharmony_ci } 362762306a36Sopenharmony_ci 362862306a36Sopenharmony_ci return xfs_alloc_vextent_finish(args, minimum_agno, error, true); 362962306a36Sopenharmony_ci} 363062306a36Sopenharmony_ci 363162306a36Sopenharmony_ci/* 363262306a36Sopenharmony_ci * Iterate from the agno indicated via @target through to the end of the 363362306a36Sopenharmony_ci * filesystem attempting blocking allocation. This does not wrap or try a second 363462306a36Sopenharmony_ci * pass, so will not recurse into AGs lower than indicated by the target. 363562306a36Sopenharmony_ci */ 363662306a36Sopenharmony_ciint 363762306a36Sopenharmony_cixfs_alloc_vextent_first_ag( 363862306a36Sopenharmony_ci struct xfs_alloc_arg *args, 363962306a36Sopenharmony_ci xfs_fsblock_t target) 364062306a36Sopenharmony_ci { 364162306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 364262306a36Sopenharmony_ci xfs_agnumber_t minimum_agno; 364362306a36Sopenharmony_ci xfs_agnumber_t start_agno; 364462306a36Sopenharmony_ci uint32_t alloc_flags = XFS_ALLOC_FLAG_TRYLOCK; 364562306a36Sopenharmony_ci int error; 364662306a36Sopenharmony_ci 364762306a36Sopenharmony_ci ASSERT(args->pag == NULL); 364862306a36Sopenharmony_ci 364962306a36Sopenharmony_ci args->agno = NULLAGNUMBER; 365062306a36Sopenharmony_ci args->agbno = NULLAGBLOCK; 365162306a36Sopenharmony_ci 365262306a36Sopenharmony_ci trace_xfs_alloc_vextent_first_ag(args); 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci error = xfs_alloc_vextent_check_args(args, target, &minimum_agno); 365562306a36Sopenharmony_ci if (error) { 365662306a36Sopenharmony_ci if (error == -ENOSPC) 365762306a36Sopenharmony_ci return 0; 365862306a36Sopenharmony_ci return error; 365962306a36Sopenharmony_ci } 366062306a36Sopenharmony_ci 366162306a36Sopenharmony_ci start_agno = max(minimum_agno, XFS_FSB_TO_AGNO(mp, target)); 366262306a36Sopenharmony_ci error = xfs_alloc_vextent_iterate_ags(args, minimum_agno, start_agno, 366362306a36Sopenharmony_ci XFS_FSB_TO_AGBNO(mp, target), alloc_flags); 366462306a36Sopenharmony_ci return xfs_alloc_vextent_finish(args, minimum_agno, error, true); 366562306a36Sopenharmony_ci} 366662306a36Sopenharmony_ci 366762306a36Sopenharmony_ci/* 366862306a36Sopenharmony_ci * Allocate at the exact block target or fail. Caller is expected to hold a 366962306a36Sopenharmony_ci * perag reference in args->pag. 367062306a36Sopenharmony_ci */ 367162306a36Sopenharmony_ciint 367262306a36Sopenharmony_cixfs_alloc_vextent_exact_bno( 367362306a36Sopenharmony_ci struct xfs_alloc_arg *args, 367462306a36Sopenharmony_ci xfs_fsblock_t target) 367562306a36Sopenharmony_ci{ 367662306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 367762306a36Sopenharmony_ci xfs_agnumber_t minimum_agno; 367862306a36Sopenharmony_ci int error; 367962306a36Sopenharmony_ci 368062306a36Sopenharmony_ci ASSERT(args->pag != NULL); 368162306a36Sopenharmony_ci ASSERT(args->pag->pag_agno == XFS_FSB_TO_AGNO(mp, target)); 368262306a36Sopenharmony_ci 368362306a36Sopenharmony_ci args->agno = XFS_FSB_TO_AGNO(mp, target); 368462306a36Sopenharmony_ci args->agbno = XFS_FSB_TO_AGBNO(mp, target); 368562306a36Sopenharmony_ci 368662306a36Sopenharmony_ci trace_xfs_alloc_vextent_exact_bno(args); 368762306a36Sopenharmony_ci 368862306a36Sopenharmony_ci error = xfs_alloc_vextent_check_args(args, target, &minimum_agno); 368962306a36Sopenharmony_ci if (error) { 369062306a36Sopenharmony_ci if (error == -ENOSPC) 369162306a36Sopenharmony_ci return 0; 369262306a36Sopenharmony_ci return error; 369362306a36Sopenharmony_ci } 369462306a36Sopenharmony_ci 369562306a36Sopenharmony_ci error = xfs_alloc_vextent_prepare_ag(args, 0); 369662306a36Sopenharmony_ci if (!error && args->agbp) 369762306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_exact(args); 369862306a36Sopenharmony_ci 369962306a36Sopenharmony_ci return xfs_alloc_vextent_finish(args, minimum_agno, error, false); 370062306a36Sopenharmony_ci} 370162306a36Sopenharmony_ci 370262306a36Sopenharmony_ci/* 370362306a36Sopenharmony_ci * Allocate an extent as close to the target as possible. If there are not 370462306a36Sopenharmony_ci * viable candidates in the AG, then fail the allocation. 370562306a36Sopenharmony_ci * 370662306a36Sopenharmony_ci * Caller may or may not have a per-ag reference in args->pag. 370762306a36Sopenharmony_ci */ 370862306a36Sopenharmony_ciint 370962306a36Sopenharmony_cixfs_alloc_vextent_near_bno( 371062306a36Sopenharmony_ci struct xfs_alloc_arg *args, 371162306a36Sopenharmony_ci xfs_fsblock_t target) 371262306a36Sopenharmony_ci{ 371362306a36Sopenharmony_ci struct xfs_mount *mp = args->mp; 371462306a36Sopenharmony_ci xfs_agnumber_t minimum_agno; 371562306a36Sopenharmony_ci bool needs_perag = args->pag == NULL; 371662306a36Sopenharmony_ci uint32_t alloc_flags = 0; 371762306a36Sopenharmony_ci int error; 371862306a36Sopenharmony_ci 371962306a36Sopenharmony_ci if (!needs_perag) 372062306a36Sopenharmony_ci ASSERT(args->pag->pag_agno == XFS_FSB_TO_AGNO(mp, target)); 372162306a36Sopenharmony_ci 372262306a36Sopenharmony_ci args->agno = XFS_FSB_TO_AGNO(mp, target); 372362306a36Sopenharmony_ci args->agbno = XFS_FSB_TO_AGBNO(mp, target); 372462306a36Sopenharmony_ci 372562306a36Sopenharmony_ci trace_xfs_alloc_vextent_near_bno(args); 372662306a36Sopenharmony_ci 372762306a36Sopenharmony_ci error = xfs_alloc_vextent_check_args(args, target, &minimum_agno); 372862306a36Sopenharmony_ci if (error) { 372962306a36Sopenharmony_ci if (error == -ENOSPC) 373062306a36Sopenharmony_ci return 0; 373162306a36Sopenharmony_ci return error; 373262306a36Sopenharmony_ci } 373362306a36Sopenharmony_ci 373462306a36Sopenharmony_ci if (needs_perag) 373562306a36Sopenharmony_ci args->pag = xfs_perag_grab(mp, args->agno); 373662306a36Sopenharmony_ci 373762306a36Sopenharmony_ci error = xfs_alloc_vextent_prepare_ag(args, alloc_flags); 373862306a36Sopenharmony_ci if (!error && args->agbp) 373962306a36Sopenharmony_ci error = xfs_alloc_ag_vextent_near(args, alloc_flags); 374062306a36Sopenharmony_ci 374162306a36Sopenharmony_ci return xfs_alloc_vextent_finish(args, minimum_agno, error, needs_perag); 374262306a36Sopenharmony_ci} 374362306a36Sopenharmony_ci 374462306a36Sopenharmony_ci/* Ensure that the freelist is at full capacity. */ 374562306a36Sopenharmony_ciint 374662306a36Sopenharmony_cixfs_free_extent_fix_freelist( 374762306a36Sopenharmony_ci struct xfs_trans *tp, 374862306a36Sopenharmony_ci struct xfs_perag *pag, 374962306a36Sopenharmony_ci struct xfs_buf **agbp) 375062306a36Sopenharmony_ci{ 375162306a36Sopenharmony_ci struct xfs_alloc_arg args; 375262306a36Sopenharmony_ci int error; 375362306a36Sopenharmony_ci 375462306a36Sopenharmony_ci memset(&args, 0, sizeof(struct xfs_alloc_arg)); 375562306a36Sopenharmony_ci args.tp = tp; 375662306a36Sopenharmony_ci args.mp = tp->t_mountp; 375762306a36Sopenharmony_ci args.agno = pag->pag_agno; 375862306a36Sopenharmony_ci args.pag = pag; 375962306a36Sopenharmony_ci 376062306a36Sopenharmony_ci /* 376162306a36Sopenharmony_ci * validate that the block number is legal - the enables us to detect 376262306a36Sopenharmony_ci * and handle a silent filesystem corruption rather than crashing. 376362306a36Sopenharmony_ci */ 376462306a36Sopenharmony_ci if (args.agno >= args.mp->m_sb.sb_agcount) 376562306a36Sopenharmony_ci return -EFSCORRUPTED; 376662306a36Sopenharmony_ci 376762306a36Sopenharmony_ci error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); 376862306a36Sopenharmony_ci if (error) 376962306a36Sopenharmony_ci return error; 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_ci *agbp = args.agbp; 377262306a36Sopenharmony_ci return 0; 377362306a36Sopenharmony_ci} 377462306a36Sopenharmony_ci 377562306a36Sopenharmony_ci/* 377662306a36Sopenharmony_ci * Free an extent. 377762306a36Sopenharmony_ci * Just break up the extent address and hand off to xfs_free_ag_extent 377862306a36Sopenharmony_ci * after fixing up the freelist. 377962306a36Sopenharmony_ci */ 378062306a36Sopenharmony_ciint 378162306a36Sopenharmony_ci__xfs_free_extent( 378262306a36Sopenharmony_ci struct xfs_trans *tp, 378362306a36Sopenharmony_ci struct xfs_perag *pag, 378462306a36Sopenharmony_ci xfs_agblock_t agbno, 378562306a36Sopenharmony_ci xfs_extlen_t len, 378662306a36Sopenharmony_ci const struct xfs_owner_info *oinfo, 378762306a36Sopenharmony_ci enum xfs_ag_resv_type type, 378862306a36Sopenharmony_ci bool skip_discard) 378962306a36Sopenharmony_ci{ 379062306a36Sopenharmony_ci struct xfs_mount *mp = tp->t_mountp; 379162306a36Sopenharmony_ci struct xfs_buf *agbp; 379262306a36Sopenharmony_ci struct xfs_agf *agf; 379362306a36Sopenharmony_ci int error; 379462306a36Sopenharmony_ci unsigned int busy_flags = 0; 379562306a36Sopenharmony_ci 379662306a36Sopenharmony_ci ASSERT(len != 0); 379762306a36Sopenharmony_ci ASSERT(type != XFS_AG_RESV_AGFL); 379862306a36Sopenharmony_ci 379962306a36Sopenharmony_ci if (XFS_TEST_ERROR(false, mp, 380062306a36Sopenharmony_ci XFS_ERRTAG_FREE_EXTENT)) 380162306a36Sopenharmony_ci return -EIO; 380262306a36Sopenharmony_ci 380362306a36Sopenharmony_ci error = xfs_free_extent_fix_freelist(tp, pag, &agbp); 380462306a36Sopenharmony_ci if (error) 380562306a36Sopenharmony_ci return error; 380662306a36Sopenharmony_ci agf = agbp->b_addr; 380762306a36Sopenharmony_ci 380862306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, agbno >= mp->m_sb.sb_agblocks)) { 380962306a36Sopenharmony_ci error = -EFSCORRUPTED; 381062306a36Sopenharmony_ci goto err_release; 381162306a36Sopenharmony_ci } 381262306a36Sopenharmony_ci 381362306a36Sopenharmony_ci /* validate the extent size is legal now we have the agf locked */ 381462306a36Sopenharmony_ci if (XFS_IS_CORRUPT(mp, agbno + len > be32_to_cpu(agf->agf_length))) { 381562306a36Sopenharmony_ci error = -EFSCORRUPTED; 381662306a36Sopenharmony_ci goto err_release; 381762306a36Sopenharmony_ci } 381862306a36Sopenharmony_ci 381962306a36Sopenharmony_ci error = xfs_free_ag_extent(tp, agbp, pag->pag_agno, agbno, len, oinfo, 382062306a36Sopenharmony_ci type); 382162306a36Sopenharmony_ci if (error) 382262306a36Sopenharmony_ci goto err_release; 382362306a36Sopenharmony_ci 382462306a36Sopenharmony_ci if (skip_discard) 382562306a36Sopenharmony_ci busy_flags |= XFS_EXTENT_BUSY_SKIP_DISCARD; 382662306a36Sopenharmony_ci xfs_extent_busy_insert(tp, pag, agbno, len, busy_flags); 382762306a36Sopenharmony_ci return 0; 382862306a36Sopenharmony_ci 382962306a36Sopenharmony_cierr_release: 383062306a36Sopenharmony_ci xfs_trans_brelse(tp, agbp); 383162306a36Sopenharmony_ci return error; 383262306a36Sopenharmony_ci} 383362306a36Sopenharmony_ci 383462306a36Sopenharmony_cistruct xfs_alloc_query_range_info { 383562306a36Sopenharmony_ci xfs_alloc_query_range_fn fn; 383662306a36Sopenharmony_ci void *priv; 383762306a36Sopenharmony_ci}; 383862306a36Sopenharmony_ci 383962306a36Sopenharmony_ci/* Format btree record and pass to our callback. */ 384062306a36Sopenharmony_ciSTATIC int 384162306a36Sopenharmony_cixfs_alloc_query_range_helper( 384262306a36Sopenharmony_ci struct xfs_btree_cur *cur, 384362306a36Sopenharmony_ci const union xfs_btree_rec *rec, 384462306a36Sopenharmony_ci void *priv) 384562306a36Sopenharmony_ci{ 384662306a36Sopenharmony_ci struct xfs_alloc_query_range_info *query = priv; 384762306a36Sopenharmony_ci struct xfs_alloc_rec_incore irec; 384862306a36Sopenharmony_ci xfs_failaddr_t fa; 384962306a36Sopenharmony_ci 385062306a36Sopenharmony_ci xfs_alloc_btrec_to_irec(rec, &irec); 385162306a36Sopenharmony_ci fa = xfs_alloc_check_irec(cur, &irec); 385262306a36Sopenharmony_ci if (fa) 385362306a36Sopenharmony_ci return xfs_alloc_complain_bad_rec(cur, fa, &irec); 385462306a36Sopenharmony_ci 385562306a36Sopenharmony_ci return query->fn(cur, &irec, query->priv); 385662306a36Sopenharmony_ci} 385762306a36Sopenharmony_ci 385862306a36Sopenharmony_ci/* Find all free space within a given range of blocks. */ 385962306a36Sopenharmony_ciint 386062306a36Sopenharmony_cixfs_alloc_query_range( 386162306a36Sopenharmony_ci struct xfs_btree_cur *cur, 386262306a36Sopenharmony_ci const struct xfs_alloc_rec_incore *low_rec, 386362306a36Sopenharmony_ci const struct xfs_alloc_rec_incore *high_rec, 386462306a36Sopenharmony_ci xfs_alloc_query_range_fn fn, 386562306a36Sopenharmony_ci void *priv) 386662306a36Sopenharmony_ci{ 386762306a36Sopenharmony_ci union xfs_btree_irec low_brec = { .a = *low_rec }; 386862306a36Sopenharmony_ci union xfs_btree_irec high_brec = { .a = *high_rec }; 386962306a36Sopenharmony_ci struct xfs_alloc_query_range_info query = { .priv = priv, .fn = fn }; 387062306a36Sopenharmony_ci 387162306a36Sopenharmony_ci ASSERT(cur->bc_btnum == XFS_BTNUM_BNO); 387262306a36Sopenharmony_ci return xfs_btree_query_range(cur, &low_brec, &high_brec, 387362306a36Sopenharmony_ci xfs_alloc_query_range_helper, &query); 387462306a36Sopenharmony_ci} 387562306a36Sopenharmony_ci 387662306a36Sopenharmony_ci/* Find all free space records. */ 387762306a36Sopenharmony_ciint 387862306a36Sopenharmony_cixfs_alloc_query_all( 387962306a36Sopenharmony_ci struct xfs_btree_cur *cur, 388062306a36Sopenharmony_ci xfs_alloc_query_range_fn fn, 388162306a36Sopenharmony_ci void *priv) 388262306a36Sopenharmony_ci{ 388362306a36Sopenharmony_ci struct xfs_alloc_query_range_info query; 388462306a36Sopenharmony_ci 388562306a36Sopenharmony_ci ASSERT(cur->bc_btnum == XFS_BTNUM_BNO); 388662306a36Sopenharmony_ci query.priv = priv; 388762306a36Sopenharmony_ci query.fn = fn; 388862306a36Sopenharmony_ci return xfs_btree_query_all(cur, xfs_alloc_query_range_helper, &query); 388962306a36Sopenharmony_ci} 389062306a36Sopenharmony_ci 389162306a36Sopenharmony_ci/* 389262306a36Sopenharmony_ci * Scan part of the keyspace of the free space and tell us if the area has no 389362306a36Sopenharmony_ci * records, is fully mapped by records, or is partially filled. 389462306a36Sopenharmony_ci */ 389562306a36Sopenharmony_ciint 389662306a36Sopenharmony_cixfs_alloc_has_records( 389762306a36Sopenharmony_ci struct xfs_btree_cur *cur, 389862306a36Sopenharmony_ci xfs_agblock_t bno, 389962306a36Sopenharmony_ci xfs_extlen_t len, 390062306a36Sopenharmony_ci enum xbtree_recpacking *outcome) 390162306a36Sopenharmony_ci{ 390262306a36Sopenharmony_ci union xfs_btree_irec low; 390362306a36Sopenharmony_ci union xfs_btree_irec high; 390462306a36Sopenharmony_ci 390562306a36Sopenharmony_ci memset(&low, 0, sizeof(low)); 390662306a36Sopenharmony_ci low.a.ar_startblock = bno; 390762306a36Sopenharmony_ci memset(&high, 0xFF, sizeof(high)); 390862306a36Sopenharmony_ci high.a.ar_startblock = bno + len - 1; 390962306a36Sopenharmony_ci 391062306a36Sopenharmony_ci return xfs_btree_has_records(cur, &low, &high, NULL, outcome); 391162306a36Sopenharmony_ci} 391262306a36Sopenharmony_ci 391362306a36Sopenharmony_ci/* 391462306a36Sopenharmony_ci * Walk all the blocks in the AGFL. The @walk_fn can return any negative 391562306a36Sopenharmony_ci * error code or XFS_ITER_*. 391662306a36Sopenharmony_ci */ 391762306a36Sopenharmony_ciint 391862306a36Sopenharmony_cixfs_agfl_walk( 391962306a36Sopenharmony_ci struct xfs_mount *mp, 392062306a36Sopenharmony_ci struct xfs_agf *agf, 392162306a36Sopenharmony_ci struct xfs_buf *agflbp, 392262306a36Sopenharmony_ci xfs_agfl_walk_fn walk_fn, 392362306a36Sopenharmony_ci void *priv) 392462306a36Sopenharmony_ci{ 392562306a36Sopenharmony_ci __be32 *agfl_bno; 392662306a36Sopenharmony_ci unsigned int i; 392762306a36Sopenharmony_ci int error; 392862306a36Sopenharmony_ci 392962306a36Sopenharmony_ci agfl_bno = xfs_buf_to_agfl_bno(agflbp); 393062306a36Sopenharmony_ci i = be32_to_cpu(agf->agf_flfirst); 393162306a36Sopenharmony_ci 393262306a36Sopenharmony_ci /* Nothing to walk in an empty AGFL. */ 393362306a36Sopenharmony_ci if (agf->agf_flcount == cpu_to_be32(0)) 393462306a36Sopenharmony_ci return 0; 393562306a36Sopenharmony_ci 393662306a36Sopenharmony_ci /* Otherwise, walk from first to last, wrapping as needed. */ 393762306a36Sopenharmony_ci for (;;) { 393862306a36Sopenharmony_ci error = walk_fn(mp, be32_to_cpu(agfl_bno[i]), priv); 393962306a36Sopenharmony_ci if (error) 394062306a36Sopenharmony_ci return error; 394162306a36Sopenharmony_ci if (i == be32_to_cpu(agf->agf_fllast)) 394262306a36Sopenharmony_ci break; 394362306a36Sopenharmony_ci if (++i == xfs_agfl_size(mp)) 394462306a36Sopenharmony_ci i = 0; 394562306a36Sopenharmony_ci } 394662306a36Sopenharmony_ci 394762306a36Sopenharmony_ci return 0; 394862306a36Sopenharmony_ci} 394962306a36Sopenharmony_ci 395062306a36Sopenharmony_ciint __init 395162306a36Sopenharmony_cixfs_extfree_intent_init_cache(void) 395262306a36Sopenharmony_ci{ 395362306a36Sopenharmony_ci xfs_extfree_item_cache = kmem_cache_create("xfs_extfree_intent", 395462306a36Sopenharmony_ci sizeof(struct xfs_extent_free_item), 395562306a36Sopenharmony_ci 0, 0, NULL); 395662306a36Sopenharmony_ci 395762306a36Sopenharmony_ci return xfs_extfree_item_cache != NULL ? 0 : -ENOMEM; 395862306a36Sopenharmony_ci} 395962306a36Sopenharmony_ci 396062306a36Sopenharmony_civoid 396162306a36Sopenharmony_cixfs_extfree_intent_destroy_cache(void) 396262306a36Sopenharmony_ci{ 396362306a36Sopenharmony_ci kmem_cache_destroy(xfs_extfree_item_cache); 396462306a36Sopenharmony_ci xfs_extfree_item_cache = NULL; 396562306a36Sopenharmony_ci} 3966