^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2016 Oracle. All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Darrick J. Wong <darrick.wong@oracle.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "xfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "xfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "xfs_shared.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "xfs_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "xfs_log_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "xfs_trans_resv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "xfs_mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "xfs_defer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "xfs_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "xfs_bmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "xfs_refcount_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "xfs_alloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "xfs_errortag.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "xfs_error.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "xfs_trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "xfs_trans.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "xfs_bit.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "xfs_refcount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "xfs_rmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* Allowable refcount adjustment amounts. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) enum xfs_refc_adjust_op {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) XFS_REFCOUNT_ADJUST_INCREASE = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) XFS_REFCOUNT_ADJUST_DECREASE = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) XFS_REFCOUNT_ADJUST_COW_ALLOC = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) XFS_REFCOUNT_ADJUST_COW_FREE = -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) STATIC int __xfs_refcount_cow_alloc(struct xfs_btree_cur *rcur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) xfs_agblock_t agbno, xfs_extlen_t aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) xfs_agblock_t agbno, xfs_extlen_t aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Look up the first record less than or equal to [bno, len] in the btree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * given by cur.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) xfs_refcount_lookup_le(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) xfs_agblock_t bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.agno, bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) XFS_LOOKUP_LE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) cur->bc_rec.rc.rc_startblock = bno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) cur->bc_rec.rc.rc_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * Look up the first record greater than or equal to [bno, len] in the btree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * given by cur.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) xfs_refcount_lookup_ge(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) xfs_agblock_t bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.agno, bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) XFS_LOOKUP_GE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) cur->bc_rec.rc.rc_startblock = bno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) cur->bc_rec.rc.rc_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Look up the first record equal to [bno, len] in the btree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * given by cur.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) xfs_refcount_lookup_eq(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) xfs_agblock_t bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) trace_xfs_refcount_lookup(cur->bc_mp, cur->bc_ag.agno, bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) XFS_LOOKUP_LE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) cur->bc_rec.rc.rc_startblock = bno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) cur->bc_rec.rc.rc_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Convert on-disk record to in-core format. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) xfs_refcount_btrec_to_irec(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) union xfs_btree_rec *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct xfs_refcount_irec *irec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * Get the data from the pointed-to record.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) xfs_refcount_get_rec(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) struct xfs_refcount_irec *irec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) int *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct xfs_mount *mp = cur->bc_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) xfs_agnumber_t agno = cur->bc_ag.agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) union xfs_btree_rec *rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) xfs_agblock_t realstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) error = xfs_btree_get_rec(cur, &rec, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (error || !*stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) xfs_refcount_btrec_to_irec(rec, irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) agno = cur->bc_ag.agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) goto out_bad_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* handle special COW-staging state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) realstart = irec->rc_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (realstart & XFS_REFC_COW_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (irec->rc_refcount != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto out_bad_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) realstart &= ~XFS_REFC_COW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) } else if (irec->rc_refcount < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) goto out_bad_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* check for valid extent range, including overflow */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!xfs_verify_agbno(mp, agno, realstart))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) goto out_bad_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (realstart > realstart + irec->rc_blockcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto out_bad_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (!xfs_verify_agbno(mp, agno, realstart + irec->rc_blockcount - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) goto out_bad_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) goto out_bad_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) trace_xfs_refcount_get(cur->bc_mp, cur->bc_ag.agno, irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) out_bad_rec:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) xfs_warn(mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) "Refcount BTree record corruption in AG %d detected!", agno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) xfs_warn(mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) "Start block 0x%x, block count 0x%x, references 0x%x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * Update the record referred to by cur to the value given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * by [bno, len, refcount].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * This either works (return 0) or gets an EFSCORRUPTED error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) xfs_refcount_update(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct xfs_refcount_irec *irec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) union xfs_btree_rec rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) trace_xfs_refcount_update(cur->bc_mp, cur->bc_ag.agno, irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) error = xfs_btree_update(cur, &rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) trace_xfs_refcount_update_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * Insert the record referred to by cur to the value given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * by [bno, len, refcount].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * This either works (return 0) or gets an EFSCORRUPTED error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) xfs_refcount_insert(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct xfs_refcount_irec *irec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) trace_xfs_refcount_insert(cur->bc_mp, cur->bc_ag.agno, irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) cur->bc_rec.rc.rc_startblock = irec->rc_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) cur->bc_rec.rc.rc_refcount = irec->rc_refcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) error = xfs_btree_insert(cur, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (XFS_IS_CORRUPT(cur->bc_mp, *i != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) trace_xfs_refcount_insert_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * Remove the record referred to by cur, then set the pointer to the spot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * where the record could be re-inserted, in case we want to increment or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * decrement the cursor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * This either works (return 0) or gets an EFSCORRUPTED error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) xfs_refcount_delete(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) int *i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct xfs_refcount_irec irec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) int found_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) error = xfs_refcount_get_rec(cur, &irec, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) trace_xfs_refcount_delete(cur->bc_mp, cur->bc_ag.agno, &irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) error = xfs_btree_delete(cur, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (XFS_IS_CORRUPT(cur->bc_mp, *i != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) error = xfs_refcount_lookup_ge(cur, irec.rc_startblock, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) trace_xfs_refcount_delete_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * Adjusting the Reference Count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * As stated elsewhere, the reference count btree (refcbt) stores
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * >1 reference counts for extents of physical blocks. In this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * operation, we're either raising or lowering the reference count of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * some subrange stored in the tree:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * <------ adjustment range ------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * ----+ +---+-----+ +--+--------+---------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) * 2 | | 3 | 4 | |17| 55 | 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * ----+ +---+-----+ +--+--------+---------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * X axis is physical blocks number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * reference counts are the numbers inside the rectangles
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * The first thing we need to do is to ensure that there are no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * refcount extents crossing either boundary of the range to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * adjusted. For any extent that does cross a boundary, split it into
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) * two extents so that we can increment the refcount of one of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * pieces later:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * <------ adjustment range ------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * ----+ +---+-----+ +--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * 2 | | 3 | 2 | |17| 55 | 10 | 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * ----+ +---+-----+ +--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * For this next step, let's assume that all the physical blocks in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * the adjustment range are mapped to a file and are therefore in use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * at least once. Therefore, we can infer that any gap in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * refcount tree within the adjustment range represents a physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * extent with refcount == 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * <------ adjustment range ------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * ----+---+---+-----+-+--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * 2 |"1"| 3 | 2 |1|17| 55 | 10 | 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * ----+---+---+-----+-+--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * For each extent that falls within the interval range, figure out
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * which extent is to the left or the right of that extent. Now we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * have a left, current, and right extent. If the new reference count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * of the center extent enables us to merge left, center, and right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * into one record covering all three, do so. If the center extent is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * at the left end of the range, abuts the left extent, and its new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) * reference count matches the left extent's record, then merge them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) * If the center extent is at the right end of the range, abuts the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * right extent, and the reference counts match, merge those. In the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * example, we can left merge (assuming an increment operation):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * <------ adjustment range ------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * --------+---+-----+-+--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * 2 | 3 | 2 |1|17| 55 | 10 | 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * --------+---+-----+-+--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) * For all other extents within the range, adjust the reference count
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * or delete it if the refcount falls below 2. If we were
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * incrementing, the end result looks like this:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * <------ adjustment range ------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * --------+---+-----+-+--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * 2 | 4 | 3 |2|18| 56 | 11 | 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) * --------+---+-----+-+--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) * The result of a decrement operation looks as such:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * <------ adjustment range ------>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * ----+ +---+ +--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * 2 | | 2 | |16| 54 | 9 | 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * ----+ +---+ +--+--------+----+----
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * DDDD 111111DD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * The blocks marked "D" are freed; the blocks marked "1" are only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * referenced once and therefore the record is removed from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * refcount btree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /* Next block after this extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static inline xfs_agblock_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) xfs_refc_next(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct xfs_refcount_irec *rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return rc->rc_startblock + rc->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * Split a refcount extent that crosses agbno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) xfs_refcount_split_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) bool *shape_changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct xfs_refcount_irec rcext, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int found_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) *shape_changed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) error = xfs_refcount_lookup_le(cur, agbno, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (!found_rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) error = xfs_refcount_get_rec(cur, &rcext, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (rcext.rc_startblock == agbno || xfs_refc_next(&rcext) <= agbno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) *shape_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) trace_xfs_refcount_split_extent(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) &rcext, agbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Establish the right extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) tmp = rcext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) tmp.rc_startblock = agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) tmp.rc_blockcount -= (agbno - rcext.rc_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) error = xfs_refcount_update(cur, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Insert the left extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) tmp = rcext;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) tmp.rc_blockcount = agbno - rcext.rc_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) error = xfs_refcount_insert(cur, &tmp, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) trace_xfs_refcount_split_extent_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * Merge the left, center, and right extents.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) xfs_refcount_merge_center_extents(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) struct xfs_refcount_irec *left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct xfs_refcount_irec *center,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct xfs_refcount_irec *right,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) unsigned long long extlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) xfs_extlen_t *aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int found_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) trace_xfs_refcount_merge_center_extents(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) cur->bc_ag.agno, left, center, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * Make sure the center and right extents are not in the btree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * If the center extent was synthesized, the first delete call
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * removes the right extent and we skip the second deletion.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * If center and right were in the btree, then the first delete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * call removes the center and the second one removes the right
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * extent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) error = xfs_refcount_lookup_ge(cur, center->rc_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) error = xfs_refcount_delete(cur, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (center->rc_refcount > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) error = xfs_refcount_delete(cur, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* Enlarge the left extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) error = xfs_refcount_lookup_le(cur, left->rc_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) left->rc_blockcount = extlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) error = xfs_refcount_update(cur, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) *aglen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) trace_xfs_refcount_merge_center_extents_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * Merge with the left extent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) xfs_refcount_merge_left_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct xfs_refcount_irec *left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) struct xfs_refcount_irec *cleft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) xfs_agblock_t *agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) xfs_extlen_t *aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int found_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) trace_xfs_refcount_merge_left_extent(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) cur->bc_ag.agno, left, cleft);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* If the extent at agbno (cleft) wasn't synthesized, remove it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (cleft->rc_refcount > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) error = xfs_refcount_lookup_le(cur, cleft->rc_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) error = xfs_refcount_delete(cur, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /* Enlarge the left extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) error = xfs_refcount_lookup_le(cur, left->rc_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) left->rc_blockcount += cleft->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) error = xfs_refcount_update(cur, left);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) *agbno += cleft->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) *aglen -= cleft->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) trace_xfs_refcount_merge_left_extent_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * Merge with the right extent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) xfs_refcount_merge_right_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) struct xfs_refcount_irec *right,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) struct xfs_refcount_irec *cright,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) xfs_extlen_t *aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) int found_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) trace_xfs_refcount_merge_right_extent(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) cur->bc_ag.agno, cright, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * If the extent ending at agbno+aglen (cright) wasn't synthesized,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * remove it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (cright->rc_refcount > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) error = xfs_refcount_lookup_le(cur, cright->rc_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) error = xfs_refcount_delete(cur, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) /* Enlarge the right extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) error = xfs_refcount_lookup_le(cur, right->rc_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) right->rc_startblock -= cright->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) right->rc_blockcount += cright->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) error = xfs_refcount_update(cur, right);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) *aglen -= cright->rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) trace_xfs_refcount_merge_right_extent_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) #define XFS_FIND_RCEXT_SHARED 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) #define XFS_FIND_RCEXT_COW 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * Find the left extent and the one after it (cleft). This function assumes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * that we've already split any extent crossing agbno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) xfs_refcount_find_left_extents(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct xfs_refcount_irec *left,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct xfs_refcount_irec *cleft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) xfs_extlen_t aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) struct xfs_refcount_irec tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) int found_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) left->rc_startblock = cleft->rc_startblock = NULLAGBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) error = xfs_refcount_lookup_le(cur, agbno - 1, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (!found_rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (xfs_refc_next(&tmp) != agbno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) /* We have a left extent; retrieve (or invent) the next right one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) *left = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) error = xfs_btree_increment(cur, 0, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (found_rec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /* if tmp starts at the end of our range, just use that */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (tmp.rc_startblock == agbno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) *cleft = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * There's a gap in the refcntbt at the start of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) * range we're interested in (refcount == 1) so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * synthesize the implied extent and pass it back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * We assume here that the agbno/aglen range was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) * passed in from a data fork extent mapping and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * therefore is allocated to exactly one owner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) cleft->rc_startblock = agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) cleft->rc_blockcount = min(aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) tmp.rc_startblock - agbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) cleft->rc_refcount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * No extents, so pretend that there's one covering the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) cleft->rc_startblock = agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) cleft->rc_blockcount = aglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) cleft->rc_refcount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) left, cleft, agbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) trace_xfs_refcount_find_left_extent_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * Find the right extent and the one before it (cright). This function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * assumes that we've already split any extents crossing agbno + aglen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) xfs_refcount_find_right_extents(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) struct xfs_refcount_irec *right,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) struct xfs_refcount_irec *cright,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) xfs_extlen_t aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) struct xfs_refcount_irec tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int found_rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) right->rc_startblock = cright->rc_startblock = NULLAGBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) error = xfs_refcount_lookup_ge(cur, agbno + aglen, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) if (!found_rec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (tmp.rc_startblock != agbno + aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /* We have a right extent; retrieve (or invent) the next left one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) *right = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) error = xfs_btree_decrement(cur, 0, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (found_rec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) error = xfs_refcount_get_rec(cur, &tmp, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* if tmp ends at the end of our range, just use that */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (xfs_refc_next(&tmp) == agbno + aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) *cright = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * There's a gap in the refcntbt at the end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * range we're interested in (refcount == 1) so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * create the implied extent and pass it back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * We assume here that the agbno/aglen range was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * passed in from a data fork extent mapping and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * therefore is allocated to exactly one owner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) cright->rc_startblock = max(agbno, xfs_refc_next(&tmp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) cright->rc_blockcount = right->rc_startblock -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) cright->rc_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) cright->rc_refcount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * No extents, so pretend that there's one covering the whole
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) cright->rc_startblock = agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) cright->rc_blockcount = aglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) cright->rc_refcount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) cright, right, agbno + aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) trace_xfs_refcount_find_right_extent_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) /* Is this extent valid? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) static inline bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) xfs_refc_valid(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) struct xfs_refcount_irec *rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return rc->rc_startblock != NULLAGBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) * Try to merge with any extents on the boundaries of the adjustment range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) xfs_refcount_merge_extents(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) xfs_agblock_t *agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) xfs_extlen_t *aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) enum xfs_refc_adjust_op adjust,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) bool *shape_changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) struct xfs_refcount_irec left = {0}, cleft = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct xfs_refcount_irec cright = {0}, right = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) unsigned long long ulen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) bool cequal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) *shape_changed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * Find the extent just below agbno [left], just above agbno [cleft],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * just below (agbno + aglen) [cright], and just above (agbno + aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * [right].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) *aglen, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) *aglen, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* No left or right extent to merge; exit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (!xfs_refc_valid(&left) && !xfs_refc_valid(&right))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) cequal = (cleft.rc_startblock == cright.rc_startblock) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) (cleft.rc_blockcount == cright.rc_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /* Try to merge left, cleft, and right. cleft must == cright. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) right.rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (xfs_refc_valid(&left) && xfs_refc_valid(&right) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) xfs_refc_valid(&cleft) && xfs_refc_valid(&cright) && cequal &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) left.rc_refcount == cleft.rc_refcount + adjust &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) right.rc_refcount == cleft.rc_refcount + adjust &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) ulen < MAXREFCEXTLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) *shape_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return xfs_refcount_merge_center_extents(cur, &left, &cleft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) &right, ulen, aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) /* Try to merge left and cleft. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) if (xfs_refc_valid(&left) && xfs_refc_valid(&cleft) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) left.rc_refcount == cleft.rc_refcount + adjust &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) ulen < MAXREFCEXTLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) *shape_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) error = xfs_refcount_merge_left_extent(cur, &left, &cleft,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) agbno, aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) * If we just merged left + cleft and cleft == cright,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) * we no longer have a cright to merge with right. We're done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (cequal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* Try to merge cright and right. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) ulen = (unsigned long long)right.rc_blockcount + cright.rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (xfs_refc_valid(&right) && xfs_refc_valid(&cright) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) right.rc_refcount == cright.rc_refcount + adjust &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) ulen < MAXREFCEXTLEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) *shape_changed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) return xfs_refcount_merge_right_extent(cur, &right, &cright,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * XXX: This is a pretty hand-wavy estimate. The penalty for guessing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * true incorrectly is a shutdown FS; the penalty for guessing false
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) * incorrectly is more transaction rolls than might be necessary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * Be conservative here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) xfs_refcount_still_have_space(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct xfs_btree_cur *cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) unsigned long overhead;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) overhead = cur->bc_ag.refc.shape_changes *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) xfs_allocfree_log_count(cur->bc_mp, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) overhead *= cur->bc_mp->m_sb.sb_blocksize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) * Only allow 2 refcount extent updates per transaction if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) * refcount continue update "error" has been injected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (cur->bc_ag.refc.nr_ops > 2 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) XFS_TEST_ERROR(false, cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (cur->bc_ag.refc.nr_ops == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) else if (overhead > cur->bc_tp->t_log_res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return cur->bc_tp->t_log_res - overhead >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) cur->bc_ag.refc.nr_ops * XFS_REFCOUNT_ITEM_OVERHEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * Adjust the refcounts of middle extents. At this point we should have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * split extents that crossed the adjustment range; merged with adjacent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * extents; and updated agbno/aglen to reflect the merges. Therefore,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * all we have to do is update the extents inside [agbno, agbno + aglen].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) xfs_refcount_adjust_extents(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) xfs_agblock_t *agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) xfs_extlen_t *aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) enum xfs_refc_adjust_op adj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) struct xfs_owner_info *oinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) struct xfs_refcount_irec ext, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) int found_rec, found_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) xfs_fsblock_t fsbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) /* Merging did all the work already. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (*aglen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) error = xfs_refcount_lookup_ge(cur, *agbno, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) while (*aglen > 0 && xfs_refcount_still_have_space(cur)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) error = xfs_refcount_get_rec(cur, &ext, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (!found_rec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) ext.rc_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) ext.rc_refcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) * Deal with a hole in the refcount tree; if a file maps to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) * these blocks and there's no refcountbt record, pretend that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) * there is one with refcount == 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) if (ext.rc_startblock != *agbno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) tmp.rc_startblock = *agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) tmp.rc_blockcount = min(*aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) ext.rc_startblock - *agbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) tmp.rc_refcount = 1 + adj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) trace_xfs_refcount_modify_extent(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) cur->bc_ag.agno, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * Either cover the hole (increment) or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * delete the range (decrement).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (tmp.rc_refcount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) error = xfs_refcount_insert(cur, &tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) &found_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) if (XFS_IS_CORRUPT(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) found_tmp != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) cur->bc_ag.refc.nr_ops++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) tmp.rc_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) xfs_bmap_add_free(cur->bc_tp, fsbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) tmp.rc_blockcount, oinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) (*agbno) += tmp.rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) (*aglen) -= tmp.rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) error = xfs_refcount_lookup_ge(cur, *agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* Stop if there's nothing left to modify */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (*aglen == 0 || !xfs_refcount_still_have_space(cur))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) * Adjust the reference count and either update the tree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) * (incr) or free the blocks (decr).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (ext.rc_refcount == MAXREFCOUNT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) goto skip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) ext.rc_refcount += adj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) trace_xfs_refcount_modify_extent(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) cur->bc_ag.agno, &ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) if (ext.rc_refcount > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) error = xfs_refcount_update(cur, &ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) cur->bc_ag.refc.nr_ops++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) } else if (ext.rc_refcount == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) error = xfs_refcount_delete(cur, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) cur->bc_ag.refc.nr_ops++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) goto advloop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) fsbno = XFS_AGB_TO_FSB(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) ext.rc_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) xfs_bmap_add_free(cur->bc_tp, fsbno, ext.rc_blockcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) oinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) skip:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) error = xfs_btree_increment(cur, 0, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) advloop:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) (*agbno) += ext.rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) (*aglen) -= ext.rc_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) trace_xfs_refcount_modify_extent_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) /* Adjust the reference count of a range of AG blocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) xfs_refcount_adjust(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) xfs_extlen_t aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) xfs_agblock_t *new_agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) xfs_extlen_t *new_aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) enum xfs_refc_adjust_op adj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) struct xfs_owner_info *oinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) bool shape_changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) int shape_changes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) *new_agbno = agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) *new_aglen = aglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) if (adj == XFS_REFCOUNT_ADJUST_INCREASE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) trace_xfs_refcount_increase(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) agbno, aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) trace_xfs_refcount_decrease(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) agbno, aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * Ensure that no rcextents cross the boundary of the adjustment range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) if (shape_changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) shape_changes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) if (shape_changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) shape_changes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * Try to merge with the left or right extents of the range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) error = xfs_refcount_merge_extents(cur, new_agbno, new_aglen, adj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) XFS_FIND_RCEXT_SHARED, &shape_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (shape_changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) shape_changes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (shape_changes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) cur->bc_ag.refc.shape_changes++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) /* Now that we've taken care of the ends, adjust the middle extents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) error = xfs_refcount_adjust_extents(cur, new_agbno, new_aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) adj, oinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) trace_xfs_refcount_adjust_error(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) /* Clean up after calling xfs_refcount_finish_one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) xfs_refcount_finish_one_cleanup(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) struct xfs_btree_cur *rcur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) int error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) struct xfs_buf *agbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) if (rcur == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) agbp = rcur->bc_ag.agbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) xfs_btree_del_cursor(rcur, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) xfs_trans_brelse(tp, agbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) * Process one of the deferred refcount operations. We pass back the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) * btree cursor to maintain our lock on the btree between calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) * This saves time and eliminates a buffer deadlock between the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) * superblock and the AGF because we'll always grab them in the same
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) * order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) xfs_refcount_finish_one(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) enum xfs_refcount_intent_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) xfs_fsblock_t startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) xfs_extlen_t blockcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) xfs_fsblock_t *new_fsb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) xfs_extlen_t *new_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) struct xfs_btree_cur **pcur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) struct xfs_btree_cur *rcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) struct xfs_buf *agbp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) xfs_agnumber_t agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) xfs_agblock_t bno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) xfs_agblock_t new_agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) unsigned long nr_ops = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) int shape_changes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) agno = XFS_FSB_TO_AGNO(mp, startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) ASSERT(agno != NULLAGNUMBER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) bno = XFS_FSB_TO_AGBNO(mp, startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) trace_xfs_refcount_deferred(mp, XFS_FSB_TO_AGNO(mp, startblock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) type, XFS_FSB_TO_AGBNO(mp, startblock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) if (XFS_TEST_ERROR(false, mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) XFS_ERRTAG_REFCOUNT_FINISH_ONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * If we haven't gotten a cursor or the cursor AG doesn't match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * the startblock, get one now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) rcur = *pcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (rcur != NULL && rcur->bc_ag.agno != agno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) nr_ops = rcur->bc_ag.refc.nr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) shape_changes = rcur->bc_ag.refc.shape_changes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) xfs_refcount_finish_one_cleanup(tp, rcur, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) rcur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) *pcur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) if (rcur == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) error = xfs_alloc_read_agf(tp->t_mountp, tp, agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) XFS_ALLOC_FLAG_FREEING, &agbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (!rcur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) error = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) goto out_cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) rcur->bc_ag.refc.nr_ops = nr_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) rcur->bc_ag.refc.shape_changes = shape_changes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) *pcur = rcur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) switch (type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) case XFS_REFCOUNT_INCREASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) new_len, XFS_REFCOUNT_ADJUST_INCREASE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) case XFS_REFCOUNT_DECREASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) error = xfs_refcount_adjust(rcur, bno, blockcount, &new_agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) new_len, XFS_REFCOUNT_ADJUST_DECREASE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) *new_fsb = XFS_AGB_TO_FSB(mp, agno, new_agbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) case XFS_REFCOUNT_ALLOC_COW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) *new_fsb = startblock + blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) *new_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) error = __xfs_refcount_cow_alloc(rcur, bno, blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) case XFS_REFCOUNT_FREE_COW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) *new_fsb = startblock + blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) *new_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) error = __xfs_refcount_cow_free(rcur, bno, blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) ASSERT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (!error && *new_len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) trace_xfs_refcount_finish_one_leftover(mp, agno, type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) bno, blockcount, new_agbno, *new_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) out_cur:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) xfs_trans_brelse(tp, agbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) * Record a refcount intent for later processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) __xfs_refcount_add(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) enum xfs_refcount_intent_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) xfs_fsblock_t startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) xfs_extlen_t blockcount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) struct xfs_refcount_intent *ri;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) trace_xfs_refcount_defer(tp->t_mountp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) XFS_FSB_TO_AGNO(tp->t_mountp, startblock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) type, XFS_FSB_TO_AGBNO(tp->t_mountp, startblock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) ri = kmem_alloc(sizeof(struct xfs_refcount_intent),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) KM_NOFS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) INIT_LIST_HEAD(&ri->ri_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) ri->ri_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ri->ri_startblock = startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) ri->ri_blockcount = blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) xfs_defer_add(tp, XFS_DEFER_OPS_TYPE_REFCOUNT, &ri->ri_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) * Increase the reference count of the blocks backing a file's extent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) xfs_refcount_increase_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) struct xfs_bmbt_irec *PREV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) __xfs_refcount_add(tp, XFS_REFCOUNT_INCREASE, PREV->br_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) PREV->br_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) * Decrease the reference count of the blocks backing a file's extent.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) xfs_refcount_decrease_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct xfs_bmbt_irec *PREV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) if (!xfs_sb_version_hasreflink(&tp->t_mountp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) __xfs_refcount_add(tp, XFS_REFCOUNT_DECREASE, PREV->br_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) PREV->br_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * Given an AG extent, find the lowest-numbered run of shared blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) * within that range and return the range in fbno/flen. If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) * find_end_of_shared is set, return the longest contiguous extent of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) * shared blocks; if not, just return the first extent we find. If no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) * shared blocks are found, fbno and flen will be set to NULLAGBLOCK
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) * and 0, respectively.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) xfs_refcount_find_shared(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) xfs_extlen_t aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) xfs_agblock_t *fbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) xfs_extlen_t *flen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) bool find_end_of_shared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) struct xfs_refcount_irec tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) int have;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) trace_xfs_refcount_find_shared(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) agbno, aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) /* By default, skip the whole range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) *fbno = NULLAGBLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) *flen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) /* Try to find a refcount extent that crosses the start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) error = xfs_refcount_lookup_le(cur, agbno, &have);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (!have) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) /* No left extent, look at the next one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) error = xfs_btree_increment(cur, 0, &have);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) if (!have)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) error = xfs_refcount_get_rec(cur, &tmp, &i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) /* If the extent ends before the start, look at the next one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) error = xfs_btree_increment(cur, 0, &have);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) if (!have)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) error = xfs_refcount_get_rec(cur, &tmp, &i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) /* If the extent starts after the range we want, bail out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) if (tmp.rc_startblock >= agbno + aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) /* We found the start of a shared extent! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (tmp.rc_startblock < agbno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) tmp.rc_blockcount -= (agbno - tmp.rc_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) tmp.rc_startblock = agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) *fbno = tmp.rc_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) *flen = min(tmp.rc_blockcount, agbno + aglen - *fbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) if (!find_end_of_shared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) /* Otherwise, find the end of this shared extent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) while (*fbno + *flen < agbno + aglen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) error = xfs_btree_increment(cur, 0, &have);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (!have)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) error = xfs_refcount_get_rec(cur, &tmp, &i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (XFS_IS_CORRUPT(cur->bc_mp, i != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (tmp.rc_startblock >= agbno + aglen ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) tmp.rc_startblock != *fbno + *flen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) *flen = min(*flen + tmp.rc_blockcount, agbno + aglen - *fbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) trace_xfs_refcount_find_shared_result(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) cur->bc_ag.agno, *fbno, *flen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) trace_xfs_refcount_find_shared_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * Recovering CoW Blocks After a Crash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * Due to the way that the copy on write mechanism works, there's a window of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) * opportunity in which we can lose track of allocated blocks during a crash.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * Because CoW uses delayed allocation in the in-core CoW fork, writeback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) * causes blocks to be allocated and stored in the CoW fork. The blocks are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) * no longer in the free space btree but are not otherwise recorded anywhere
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) * until the write completes and the blocks are mapped into the file. A crash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) * in between allocation and remapping results in the replacement blocks being
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) * lost. This situation is exacerbated by the CoW extent size hint because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) * allocations can hang around for long time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) * However, there is a place where we can record these allocations before they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) * become mappings -- the reference count btree. The btree does not record
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) * extents with refcount == 1, so we can record allocations with a refcount of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) * 1. Blocks being used for CoW writeout cannot be shared, so there should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) * no conflict with shared block records. These mappings should be created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) * when we allocate blocks to the CoW fork and deleted when they're removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) * from the CoW fork.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) * Minor nit: records for in-progress CoW allocations and records for shared
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) * extents must never be merged, to preserve the property that (except for CoW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * allocations) there are no refcount btree entries with refcount == 1. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) * only time this could potentially happen is when unsharing a block that's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) * adjacent to CoW allocations, so we must be careful to avoid this.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) * At mount time we recover lost CoW allocations by searching the refcount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) * btree for these refcount == 1 mappings. These represent CoW allocations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) * that were in progress at the time the filesystem went down, so we can free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * them to get the space back.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * This mechanism is superior to creating EFIs for unmapped CoW extents for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * several reasons -- first, EFIs pin the tail of the log and would have to be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) * periodically relogged to avoid filling up the log. Second, CoW completions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) * will have to file an EFD and create new EFIs for whatever remains in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * CoW fork; this partially takes care of (1) but extent-size reservations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) * will have to periodically relog even if there's no writeout in progress.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) * This can happen if the CoW extent size hint is set, which you really want.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) * Third, EFIs cannot currently be automatically relogged into newer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) * transactions to advance the log tail. Fourth, stuffing the log full of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) * EFIs places an upper bound on the number of CoW allocations that can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) * held filesystem-wide at any given time. Recording them in the refcount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) * btree doesn't require us to maintain any state in memory and doesn't pin
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) * the log.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) * Adjust the refcounts of CoW allocations. These allocations are "magic"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) * in that they're not referenced anywhere else in the filesystem, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) * stash them in the refcount btree with a refcount of 1 until either file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) * remapping (or CoW cancellation) happens.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) xfs_refcount_adjust_cow_extents(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) xfs_extlen_t aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) enum xfs_refc_adjust_op adj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) struct xfs_refcount_irec ext, tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) int found_rec, found_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) if (aglen == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) /* Find any overlapping refcount records */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) error = xfs_refcount_lookup_ge(cur, agbno, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) error = xfs_refcount_get_rec(cur, &ext, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) if (!found_rec) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) XFS_REFC_COW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) ext.rc_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) ext.rc_refcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) switch (adj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) case XFS_REFCOUNT_ADJUST_COW_ALLOC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) /* Adding a CoW reservation, there should be nothing here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if (XFS_IS_CORRUPT(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) agbno + aglen > ext.rc_startblock)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) tmp.rc_startblock = agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) tmp.rc_blockcount = aglen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) tmp.rc_refcount = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) trace_xfs_refcount_modify_extent(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) cur->bc_ag.agno, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) error = xfs_refcount_insert(cur, &tmp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) &found_tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) if (XFS_IS_CORRUPT(cur->bc_mp, found_tmp != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) case XFS_REFCOUNT_ADJUST_COW_FREE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /* Removing a CoW reservation, there should be one extent. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_startblock != agbno)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_blockcount != aglen)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) if (XFS_IS_CORRUPT(cur->bc_mp, ext.rc_refcount != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) ext.rc_refcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) trace_xfs_refcount_modify_extent(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) cur->bc_ag.agno, &ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) error = xfs_refcount_delete(cur, &found_rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) if (XFS_IS_CORRUPT(cur->bc_mp, found_rec != 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) ASSERT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) trace_xfs_refcount_modify_extent_error(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) cur->bc_ag.agno, error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * Add or remove refcount btree entries for CoW reservations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) xfs_refcount_adjust_cow(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) xfs_extlen_t aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) enum xfs_refc_adjust_op adj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) bool shape_changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) agbno += XFS_REFC_COW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) * Ensure that no rcextents cross the boundary of the adjustment range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) error = xfs_refcount_split_extent(cur, agbno, &shape_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) * Try to merge with the left or right extents of the range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) XFS_FIND_RCEXT_COW, &shape_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) /* Now that we've taken care of the ends, adjust the middle extents */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) error = xfs_refcount_adjust_cow_extents(cur, agbno, aglen, adj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) goto out_error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) out_error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) trace_xfs_refcount_adjust_cow_error(cur->bc_mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) error, _RET_IP_);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) * Record a CoW allocation in the refcount btree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) __xfs_refcount_cow_alloc(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) struct xfs_btree_cur *rcur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) xfs_extlen_t aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) agbno, aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) /* Add refcount btree reservation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) return xfs_refcount_adjust_cow(rcur, agbno, aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) XFS_REFCOUNT_ADJUST_COW_ALLOC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) * Remove a CoW allocation from the refcount btree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) __xfs_refcount_cow_free(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) struct xfs_btree_cur *rcur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) xfs_agblock_t agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) xfs_extlen_t aglen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) agbno, aglen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) /* Remove refcount btree reservation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) return xfs_refcount_adjust_cow(rcur, agbno, aglen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) XFS_REFCOUNT_ADJUST_COW_FREE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) /* Record a CoW staging extent in the refcount btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) xfs_refcount_alloc_cow_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) xfs_fsblock_t fsb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) xfs_extlen_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) if (!xfs_sb_version_hasreflink(&mp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) __xfs_refcount_add(tp, XFS_REFCOUNT_ALLOC_COW, fsb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) /* Add rmap entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) xfs_rmap_alloc_extent(tp, XFS_FSB_TO_AGNO(mp, fsb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) /* Forget a CoW staging event in the refcount btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) xfs_refcount_free_cow_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) xfs_fsblock_t fsb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) xfs_extlen_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) if (!xfs_sb_version_hasreflink(&mp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) /* Remove rmap entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) xfs_rmap_free_extent(tp, XFS_FSB_TO_AGNO(mp, fsb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) __xfs_refcount_add(tp, XFS_REFCOUNT_FREE_COW, fsb, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) struct xfs_refcount_recovery {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) struct list_head rr_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) struct xfs_refcount_irec rr_rrec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) /* Stuff an extent on the recovery list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) xfs_refcount_recover_extent(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) union xfs_btree_rec *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) struct list_head *debris = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) struct xfs_refcount_recovery *rr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) if (XFS_IS_CORRUPT(cur->bc_mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) be32_to_cpu(rec->refc.rc_refcount) != 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) return -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) rr = kmem_alloc(sizeof(struct xfs_refcount_recovery), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) list_add_tail(&rr->rr_list, debris);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) /* Find and remove leftover CoW reservations. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) xfs_refcount_recover_cow_leftovers(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) xfs_agnumber_t agno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) struct xfs_trans *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) struct xfs_btree_cur *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) struct xfs_buf *agbp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) struct xfs_refcount_recovery *rr, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) struct list_head debris;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) union xfs_btree_irec low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) union xfs_btree_irec high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) xfs_fsblock_t fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) xfs_agblock_t agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) if (mp->m_sb.sb_agblocks >= XFS_REFC_COW_START)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) INIT_LIST_HEAD(&debris);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) * In this first part, we use an empty transaction to gather up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) * all the leftover CoW extents so that we can subsequently
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) * delete them. The empty transaction is used to avoid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) * a buffer lock deadlock if there happens to be a loop in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) * refcountbt because we're allowed to re-grab a buffer that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) * already attached to our transaction. When we're done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) * recording the CoW debris we cancel the (empty) transaction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) * and everything goes away cleanly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) error = xfs_trans_alloc_empty(mp, &tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) goto out_trans;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) /* Find all the leftover CoW staging extents. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) memset(&low, 0, sizeof(low));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) memset(&high, 0, sizeof(high));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) low.rc.rc_startblock = XFS_REFC_COW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) high.rc.rc_startblock = -1U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) error = xfs_btree_query_range(cur, &low, &high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) xfs_refcount_recover_extent, &debris);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) xfs_btree_del_cursor(cur, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) xfs_trans_brelse(tp, agbp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) /* Now iterate the list to free the leftovers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) list_for_each_entry_safe(rr, n, &debris, rr_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) /* Set up transaction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) trace_xfs_refcount_recover_extent(mp, agno, &rr->rr_rrec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) /* Free the orphan record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) agbno = rr->rr_rrec.rc_startblock - XFS_REFC_COW_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) fsb = XFS_AGB_TO_FSB(mp, agno, agbno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) xfs_refcount_free_cow_extent(tp, fsb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) rr->rr_rrec.rc_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) /* Free the block. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) xfs_bmap_add_free(tp, fsb, rr->rr_rrec.rc_blockcount, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) error = xfs_trans_commit(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) goto out_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) list_del(&rr->rr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) kmem_free(rr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) out_trans:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) out_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) /* Free the leftover list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) list_for_each_entry_safe(rr, n, &debris, rr_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) list_del(&rr->rr_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) kmem_free(rr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) /* Is there a record covering a given extent? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) xfs_refcount_has_record(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) xfs_agblock_t bno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) xfs_extlen_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) bool *exists)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) union xfs_btree_irec low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) union xfs_btree_irec high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) memset(&low, 0, sizeof(low));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) low.rc.rc_startblock = bno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) memset(&high, 0xFF, sizeof(high));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) high.rc.rc_startblock = bno + len - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) return xfs_btree_has_record(cur, &low, &high, exists);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) }