^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) 2019 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_inode.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_ialloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "xfs_ialloc_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "xfs_iwalk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "xfs_error.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "xfs_trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "xfs_icache.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "xfs_health.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "xfs_trans.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "xfs_pwork.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Walking Inodes in the Filesystem
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * ================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * This iterator function walks a subset of filesystem inodes in increasing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * order from @startino until there are no more inodes. For each allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * inode it finds, it calls a walk function with the relevant inode number and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * a pointer to caller-provided data. The walk function can return the usual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * negative error code to stop the iteration; 0 to continue the iteration; or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * -ECANCELED to stop the iteration. This return value is returned to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Internally, we allow the walk function to do anything, which means that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * cannot maintain the inobt cursor or our lock on the AGI buffer. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * therefore cache the inobt records in kernel memory and only call the walk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * function when our memory buffer is full. @nr_recs is the number of records
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * that we've cached, and @sz_recs is the size of our cache.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * It is the responsibility of the walk function to ensure it accesses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * allocated inodes, as the inobt records may be stale by the time they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * acted upon.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct xfs_iwalk_ag {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* parallel work control data; will be null if single threaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct xfs_pwork pwork;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct xfs_mount *mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct xfs_trans *tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* Where do we start the traversal? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) xfs_ino_t startino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* What was the last inode number we saw when iterating the inobt? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) xfs_ino_t lastino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) /* Array of inobt records we cache. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct xfs_inobt_rec_incore *recs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Number of entries allocated for the @recs array. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned int sz_recs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) /* Number of entries in the @recs array that are in use. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) unsigned int nr_recs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /* Inode walk function and data pointer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) xfs_iwalk_fn iwalk_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) xfs_inobt_walk_fn inobt_walk_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * Make it look like the inodes up to startino are free so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * bulkstat can start its inode iteration at the correct place without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * needing to special case everywhere.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) unsigned int trim_start:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* Skip empty inobt records? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned int skip_empty:1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * Loop over all clusters in a chunk for a given incore inode allocation btree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * record. Do a readahead if there are any allocated inodes in that cluster.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) STATIC void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) xfs_iwalk_ichunk_ra(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) xfs_agnumber_t agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct xfs_inobt_rec_incore *irec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct xfs_ino_geometry *igeo = M_IGEO(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) xfs_agblock_t agbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) struct blk_plug plug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int i; /* inode chunk index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) blk_start_plug(&plug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) for (i = 0; i < XFS_INODES_PER_CHUNK; i += igeo->inodes_per_cluster) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) xfs_inofree_t imask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) imask = xfs_inobt_maskn(i, igeo->inodes_per_cluster);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (imask & ~irec->ir_free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) xfs_btree_reada_bufs(mp, agno, agbno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) igeo->blocks_per_cluster,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) &xfs_inode_buf_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) agbno += igeo->blocks_per_cluster;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) blk_finish_plug(&plug);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Set the bits in @irec's free mask that correspond to the inodes before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * @agino so that we skip them. This is how we restart an inode walk that was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * interrupted in the middle of an inode record.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) STATIC void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) xfs_iwalk_adjust_start(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) xfs_agino_t agino, /* starting inode of chunk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct xfs_inobt_rec_incore *irec) /* btree record */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) int idx; /* index into inode chunk */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) idx = agino - irec->ir_startino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * We got a right chunk with some left inodes allocated at it. Grab
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * the chunk record. Mark all the uninteresting inodes free because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * they're before our start point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) for (i = 0; i < idx; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (XFS_INOBT_MASK(i) & ~irec->ir_free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) irec->ir_freecount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) irec->ir_free |= xfs_inobt_maskn(0, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* Allocate memory for a walk. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) xfs_iwalk_alloc(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct xfs_iwalk_ag *iwag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ASSERT(iwag->recs == NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) iwag->nr_recs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* Allocate a prefetch buffer for inobt records. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) size = iwag->sz_recs * sizeof(struct xfs_inobt_rec_incore);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) iwag->recs = kmem_alloc(size, KM_MAYFAIL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) if (iwag->recs == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /* Free memory we allocated for a walk. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) STATIC void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) xfs_iwalk_free(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct xfs_iwalk_ag *iwag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) kmem_free(iwag->recs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) iwag->recs = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* For each inuse inode in each cached inobt record, call our function. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) xfs_iwalk_ag_recs(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct xfs_iwalk_ag *iwag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) struct xfs_mount *mp = iwag->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct xfs_trans *tp = iwag->tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) xfs_ino_t ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) unsigned int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) xfs_agnumber_t agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) agno = XFS_INO_TO_AGNO(mp, iwag->startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) for (i = 0; i < iwag->nr_recs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) struct xfs_inobt_rec_incore *irec = &iwag->recs[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) trace_xfs_iwalk_ag_rec(mp, agno, irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (xfs_pwork_want_abort(&iwag->pwork))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (iwag->inobt_walk_fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) error = iwag->inobt_walk_fn(mp, tp, agno, irec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) iwag->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (!iwag->iwalk_fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) for (j = 0; j < XFS_INODES_PER_CHUNK; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (xfs_pwork_want_abort(&iwag->pwork))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Skip if this inode is free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (XFS_INOBT_MASK(j) & irec->ir_free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /* Otherwise call our function. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino + j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) error = iwag->iwalk_fn(mp, tp, ino, iwag->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* Delete cursor and let go of AGI. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) xfs_iwalk_del_inobt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct xfs_btree_cur **curpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct xfs_buf **agi_bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (*curpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) xfs_btree_del_cursor(*curpp, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) *curpp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (*agi_bpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) xfs_trans_brelse(tp, *agi_bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) *agi_bpp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * Set ourselves up for walking inobt records starting from a given point in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * the filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) * If caller passed in a nonzero start inode number, load the record from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * inobt and make the record look like all the inodes before agino are free so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * that we skip them, and then move the cursor to the next inobt record. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * is how we support starting an iwalk in the middle of an inode chunk.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * If the caller passed in a start number of zero, move the cursor to the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * inobt record.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * The caller is responsible for cleaning up the cursor and buffer pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * regardless of the error status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) xfs_iwalk_ag_start(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct xfs_iwalk_ag *iwag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) xfs_agnumber_t agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) xfs_agino_t agino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct xfs_btree_cur **curpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct xfs_buf **agi_bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) int *has_more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) struct xfs_mount *mp = iwag->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) struct xfs_trans *tp = iwag->tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct xfs_inobt_rec_incore *irec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* Set up a fresh cursor and empty the inobt cache. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) iwag->nr_recs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) error = xfs_inobt_cur(mp, tp, agno, XFS_BTNUM_INO, curpp, agi_bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /* Starting at the beginning of the AG? That's easy! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (agino == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return xfs_inobt_lookup(*curpp, 0, XFS_LOOKUP_GE, has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) * Otherwise, we have to grab the inobt record where we left off, stuff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * the record into our cache, and then see if there are more records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * We require a lookup cache of at least two elements so that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * caller doesn't have to deal with tearing down the cursor to walk the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) error = xfs_inobt_lookup(*curpp, agino, XFS_LOOKUP_LE, has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) * If the LE lookup at @agino yields no records, jump ahead to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * inobt cursor increment to see if there are more records to process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (!*has_more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) goto out_advance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /* Get the record, should always work */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) irec = &iwag->recs[iwag->nr_recs];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) error = xfs_inobt_get_rec(*curpp, irec, has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) if (XFS_IS_CORRUPT(mp, *has_more != 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) iwag->lastino = XFS_AGINO_TO_INO(mp, agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) irec->ir_startino + XFS_INODES_PER_CHUNK - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * If the LE lookup yielded an inobt record before the cursor position,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * skip it and see if there's another one after it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (irec->ir_startino + XFS_INODES_PER_CHUNK <= agino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) goto out_advance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) * If agino fell in the middle of the inode record, make it look like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * the inodes up to agino are free so that we don't return them again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (iwag->trim_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) xfs_iwalk_adjust_start(agino, irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * The prefetch calculation is supposed to give us a large enough inobt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * record cache that grab_ichunk can stage a partial first record and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) * the loop body can cache a record without having to check for cache
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * space until after it reads an inobt record.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) iwag->nr_recs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ASSERT(iwag->nr_recs < iwag->sz_recs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) out_advance:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return xfs_btree_increment(*curpp, 0, has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^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) * The inobt record cache is full, so preserve the inobt cursor state and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * run callbacks on the cached inobt records. When we're done, restore the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * cursor state to wherever the cursor would have been had the cache not been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * full (and therefore we could've just incremented the cursor) if *@has_more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * is true. On exit, *@has_more will indicate whether or not the caller should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) * try for more inode records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) xfs_iwalk_run_callbacks(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) struct xfs_iwalk_ag *iwag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) xfs_agnumber_t agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct xfs_btree_cur **curpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) struct xfs_buf **agi_bpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) int *has_more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct xfs_mount *mp = iwag->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) struct xfs_trans *tp = iwag->tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct xfs_inobt_rec_incore *irec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) xfs_agino_t next_agino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) next_agino = XFS_INO_TO_AGINO(mp, iwag->lastino) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) ASSERT(iwag->nr_recs > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Delete cursor but remember the last record we cached... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) xfs_iwalk_del_inobt(tp, curpp, agi_bpp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) irec = &iwag->recs[iwag->nr_recs - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ASSERT(next_agino == irec->ir_startino + XFS_INODES_PER_CHUNK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) error = xfs_iwalk_ag_recs(iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* ...empty the cache... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) iwag->nr_recs = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (!has_more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) /* ...and recreate the cursor just past where we left off. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) error = xfs_inobt_cur(mp, tp, agno, XFS_BTNUM_INO, curpp, agi_bpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return xfs_inobt_lookup(*curpp, next_agino, XFS_LOOKUP_GE, has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* Walk all inodes in a single AG, from @iwag->startino to the end of the AG. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) xfs_iwalk_ag(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct xfs_iwalk_ag *iwag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct xfs_mount *mp = iwag->mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct xfs_trans *tp = iwag->tp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) struct xfs_buf *agi_bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct xfs_btree_cur *cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) xfs_agnumber_t agno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) xfs_agino_t agino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int has_more;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) /* Set up our cursor at the right place in the inode btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) agno = XFS_INO_TO_AGNO(mp, iwag->startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) agino = XFS_INO_TO_AGINO(mp, iwag->startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) error = xfs_iwalk_ag_start(iwag, agno, agino, &cur, &agi_bp, &has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) while (!error && has_more) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct xfs_inobt_rec_incore *irec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) xfs_ino_t rec_fsino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) cond_resched();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (xfs_pwork_want_abort(&iwag->pwork))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* Fetch the inobt record. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) irec = &iwag->recs[iwag->nr_recs];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) error = xfs_inobt_get_rec(cur, irec, &has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) if (error || !has_more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* Make sure that we always move forward. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) rec_fsino = XFS_AGINO_TO_INO(mp, agno, irec->ir_startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) if (iwag->lastino != NULLFSINO &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) XFS_IS_CORRUPT(mp, iwag->lastino >= rec_fsino)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) error = -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) iwag->lastino = rec_fsino + XFS_INODES_PER_CHUNK - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /* No allocated inodes in this chunk; skip it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (iwag->skip_empty && irec->ir_freecount == irec->ir_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) error = xfs_btree_increment(cur, 0, &has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * Start readahead for this inode chunk in anticipation of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) * walking the inodes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (iwag->iwalk_fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) xfs_iwalk_ichunk_ra(mp, agno, irec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) * If there's space in the buffer for more records, increment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * the btree cursor and grab more.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (++iwag->nr_recs < iwag->sz_recs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) error = xfs_btree_increment(cur, 0, &has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (error || !has_more)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) * Otherwise, we need to save cursor state and run the callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) * function on the cached records. The run_callbacks function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) * is supposed to return a cursor pointing to the record where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) * we would be if we had been able to increment like above.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ASSERT(has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) error = xfs_iwalk_run_callbacks(iwag, agno, &cur, &agi_bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) &has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (iwag->nr_recs == 0 || error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) /* Walk the unprocessed records in the cache. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) error = xfs_iwalk_run_callbacks(iwag, agno, &cur, &agi_bp, &has_more);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) xfs_iwalk_del_inobt(tp, &cur, &agi_bp, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return error;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * We experimentally determined that the reduction in ioctl call overhead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * diminishes when userspace asks for more than 2048 inodes, so we'll cap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * prefetch at this point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) #define IWALK_MAX_INODE_PREFETCH (2048U)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) * Given the number of inodes to prefetch, set the number of inobt records that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * we cache in memory, which controls the number of inodes we try to read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * ahead. Set the maximum if @inodes == 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) static inline unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) xfs_iwalk_prefetch(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) unsigned int inodes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) unsigned int inobt_records;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) * If the caller didn't tell us the number of inodes they wanted,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * assume the maximum prefetch possible for best performance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * Otherwise, cap prefetch at that maximum so that we don't start an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * absurd amount of prefetch.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (inodes == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) inodes = IWALK_MAX_INODE_PREFETCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) inodes = min(inodes, IWALK_MAX_INODE_PREFETCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) /* Round the inode count up to a full chunk. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) inodes = round_up(inodes, XFS_INODES_PER_CHUNK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * In order to convert the number of inodes to prefetch into an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * estimate of the number of inobt records to cache, we require a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * conversion factor that reflects our expectations of the average
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * loading factor of an inode chunk. Based on data gathered, most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) * (but not all) filesystems manage to keep the inode chunks totally
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * full, so we'll underestimate slightly so that our readahead will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) * still deliver the performance we want on aging filesystems:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) * inobt = inodes / (INODES_PER_CHUNK * (4 / 5));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * The funny math is to avoid integer division.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) inobt_records = (inodes * 5) / (4 * XFS_INODES_PER_CHUNK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * Allocate enough space to prefetch at least two inobt records so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * we can cache both the record where the iwalk started and the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) * record. This simplifies the AG inode walk loop setup code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) return max(inobt_records, 2U);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * Walk all inodes in the filesystem starting from @startino. The @iwalk_fn
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * will be called for each allocated inode, being passed the inode's number and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * @data. @max_prefetch controls how many inobt records' worth of inodes we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * try to readahead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) xfs_iwalk(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) xfs_ino_t startino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) unsigned int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) xfs_iwalk_fn iwalk_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) unsigned int inode_records,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct xfs_iwalk_ag iwag = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) .mp = mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) .tp = tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) .iwalk_fn = iwalk_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) .data = data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) .startino = startino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) .sz_recs = xfs_iwalk_prefetch(inode_records),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) .trim_start = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) .skip_empty = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) .pwork = XFS_PWORK_SINGLE_THREADED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) .lastino = NULLFSINO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) ASSERT(agno < mp->m_sb.sb_agcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) error = xfs_iwalk_alloc(&iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) for (; agno < mp->m_sb.sb_agcount; agno++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) error = xfs_iwalk_ag(&iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (flags & XFS_INOBT_WALK_SAME_AG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) xfs_iwalk_free(&iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* Run per-thread iwalk work. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) xfs_iwalk_ag_work(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct xfs_pwork *pwork)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct xfs_iwalk_ag *iwag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) iwag = container_of(pwork, struct xfs_iwalk_ag, pwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) if (xfs_pwork_want_abort(pwork))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) error = xfs_iwalk_alloc(iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) error = xfs_iwalk_ag(iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) xfs_iwalk_free(iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) kmem_free(iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * Walk all the inodes in the filesystem using multiple threads to process each
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * AG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) xfs_iwalk_threaded(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) xfs_ino_t startino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) unsigned int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) xfs_iwalk_fn iwalk_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) unsigned int inode_records,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) bool polled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct xfs_pwork_ctl pctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) unsigned int nr_threads;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ASSERT(agno < mp->m_sb.sb_agcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) ASSERT(!(flags & ~XFS_IWALK_FLAGS_ALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) nr_threads = xfs_pwork_guess_datadev_parallelism(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) error = xfs_pwork_init(mp, &pctl, xfs_iwalk_ag_work, "xfs_iwalk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) nr_threads);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) for (; agno < mp->m_sb.sb_agcount; agno++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) struct xfs_iwalk_ag *iwag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (xfs_pwork_ctl_want_abort(&pctl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) iwag = kmem_zalloc(sizeof(struct xfs_iwalk_ag), 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) iwag->mp = mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) iwag->iwalk_fn = iwalk_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) iwag->data = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) iwag->startino = startino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) iwag->sz_recs = xfs_iwalk_prefetch(inode_records);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) iwag->lastino = NULLFSINO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) xfs_pwork_queue(&pctl, &iwag->pwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (flags & XFS_INOBT_WALK_SAME_AG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (polled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) xfs_pwork_poll(&pctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return xfs_pwork_destroy(&pctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * Allow callers to cache up to a page's worth of inobt records. This reflects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) * the existing inumbers prefetching behavior. Since the inobt walk does not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * itself do anything with the inobt records, we can set a fairly high limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) * here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) #define MAX_INOBT_WALK_PREFETCH \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) (PAGE_SIZE / sizeof(struct xfs_inobt_rec_incore))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * Given the number of records that the user wanted, set the number of inobt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * records that we buffer in memory. Set the maximum if @inobt_records == 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static inline unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) xfs_inobt_walk_prefetch(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) unsigned int inobt_records)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * If the caller didn't tell us the number of inobt records they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * wanted, assume the maximum prefetch possible for best performance.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) if (inobt_records == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) inobt_records = MAX_INOBT_WALK_PREFETCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * Allocate enough space to prefetch at least two inobt records so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * we can cache both the record where the iwalk started and the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * record. This simplifies the AG inode walk loop setup code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) inobt_records = max(inobt_records, 2U);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * Cap prefetch at that maximum so that we don't use an absurd amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * of memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) return min_t(unsigned int, inobt_records, MAX_INOBT_WALK_PREFETCH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * Walk all inode btree records in the filesystem starting from @startino. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * @inobt_walk_fn will be called for each btree record, being passed the incore
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * record and @data. @max_prefetch controls how many inobt records we try to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * cache ahead of time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) xfs_inobt_walk(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) xfs_ino_t startino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) unsigned int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) xfs_inobt_walk_fn inobt_walk_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) unsigned int inobt_records,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) struct xfs_iwalk_ag iwag = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) .mp = mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) .tp = tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) .inobt_walk_fn = inobt_walk_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) .data = data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) .startino = startino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) .sz_recs = xfs_inobt_walk_prefetch(inobt_records),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) .pwork = XFS_PWORK_SINGLE_THREADED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) .lastino = NULLFSINO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, startino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) ASSERT(agno < mp->m_sb.sb_agcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) ASSERT(!(flags & ~XFS_INOBT_WALK_FLAGS_ALL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) error = xfs_iwalk_alloc(&iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) for (; agno < mp->m_sb.sb_agcount; agno++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) error = xfs_iwalk_ag(&iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) iwag.startino = XFS_AGINO_TO_INO(mp, agno + 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (flags & XFS_INOBT_WALK_SAME_AG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) xfs_iwalk_free(&iwag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }