^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) 2017 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_trans.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "xfs_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "xfs_rmap_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "xfs_trace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "xfs_rmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "xfs_alloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "xfs_bit.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/fsmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "xfs_fsmap.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_refcount_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "xfs_alloc_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "xfs_rtalloc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* Convert an xfs_fsmap to an fsmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) xfs_fsmap_from_internal(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct fsmap *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct xfs_fsmap *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) dest->fmr_device = src->fmr_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) dest->fmr_flags = src->fmr_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) dest->fmr_physical = BBTOB(src->fmr_physical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) dest->fmr_owner = src->fmr_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) dest->fmr_offset = BBTOB(src->fmr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) dest->fmr_length = BBTOB(src->fmr_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) dest->fmr_reserved[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) dest->fmr_reserved[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) dest->fmr_reserved[2] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /* Convert an fsmap to an xfs_fsmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) xfs_fsmap_to_internal(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct xfs_fsmap *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct fsmap *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) dest->fmr_device = src->fmr_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) dest->fmr_flags = src->fmr_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) dest->fmr_physical = BTOBBT(src->fmr_physical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) dest->fmr_owner = src->fmr_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) dest->fmr_offset = BTOBBT(src->fmr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) dest->fmr_length = BTOBBT(src->fmr_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* Convert an fsmap owner into an rmapbt owner. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) xfs_fsmap_owner_to_rmap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct xfs_rmap_irec *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct xfs_fsmap *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (!(src->fmr_flags & FMR_OF_SPECIAL_OWNER)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) dest->rm_owner = src->fmr_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) switch (src->fmr_owner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case 0: /* "lowest owner id possible" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) case -1ULL: /* "highest owner id possible" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) dest->rm_owner = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) case XFS_FMR_OWN_FREE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) dest->rm_owner = XFS_RMAP_OWN_NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) case XFS_FMR_OWN_UNKNOWN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) dest->rm_owner = XFS_RMAP_OWN_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) case XFS_FMR_OWN_FS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dest->rm_owner = XFS_RMAP_OWN_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) case XFS_FMR_OWN_LOG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) dest->rm_owner = XFS_RMAP_OWN_LOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) case XFS_FMR_OWN_AG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dest->rm_owner = XFS_RMAP_OWN_AG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) case XFS_FMR_OWN_INOBT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) dest->rm_owner = XFS_RMAP_OWN_INOBT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) case XFS_FMR_OWN_INODES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) dest->rm_owner = XFS_RMAP_OWN_INODES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) case XFS_FMR_OWN_REFC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) dest->rm_owner = XFS_RMAP_OWN_REFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) case XFS_FMR_OWN_COW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) dest->rm_owner = XFS_RMAP_OWN_COW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) case XFS_FMR_OWN_DEFECTIVE: /* not implemented */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /* fall through */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* Convert an rmapbt owner into an fsmap owner. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) xfs_fsmap_owner_from_rmap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) struct xfs_fsmap *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct xfs_rmap_irec *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dest->fmr_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!XFS_RMAP_NON_INODE_OWNER(src->rm_owner)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) dest->fmr_owner = src->rm_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dest->fmr_flags |= FMR_OF_SPECIAL_OWNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) switch (src->rm_owner) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) case XFS_RMAP_OWN_FS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) dest->fmr_owner = XFS_FMR_OWN_FS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) case XFS_RMAP_OWN_LOG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dest->fmr_owner = XFS_FMR_OWN_LOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case XFS_RMAP_OWN_AG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dest->fmr_owner = XFS_FMR_OWN_AG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) case XFS_RMAP_OWN_INOBT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) dest->fmr_owner = XFS_FMR_OWN_INOBT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) case XFS_RMAP_OWN_INODES:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) dest->fmr_owner = XFS_FMR_OWN_INODES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) case XFS_RMAP_OWN_REFC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) dest->fmr_owner = XFS_FMR_OWN_REFC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) case XFS_RMAP_OWN_COW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) dest->fmr_owner = XFS_FMR_OWN_COW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case XFS_RMAP_OWN_NULL: /* "free" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) dest->fmr_owner = XFS_FMR_OWN_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ASSERT(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) return -EFSCORRUPTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* getfsmap query state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct xfs_getfsmap_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct xfs_fsmap_head *head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct fsmap *fsmap_recs; /* mapping records */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct xfs_buf *agf_bp; /* AGF, for refcount queries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) xfs_daddr_t next_daddr; /* next daddr we expect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) u64 missing_owner; /* owner of holes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) u32 dev; /* device id */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) xfs_agnumber_t agno; /* AG number, if applicable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) struct xfs_rmap_irec low; /* low rmap key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct xfs_rmap_irec high; /* high rmap key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bool last; /* last extent? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) /* Associate a device with a getfsmap handler. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct xfs_getfsmap_dev {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) int (*fn)(struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct xfs_fsmap *keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct xfs_getfsmap_info *info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* Compare two getfsmap device handlers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) xfs_getfsmap_dev_compare(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) const void *p1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) const void *p2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) const struct xfs_getfsmap_dev *d1 = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) const struct xfs_getfsmap_dev *d2 = p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return d1->dev - d2->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) /* Decide if this mapping is shared. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) xfs_getfsmap_is_shared(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) struct xfs_getfsmap_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct xfs_rmap_irec *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) bool *stat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct xfs_btree_cur *cur;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) xfs_agblock_t fbno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) xfs_extlen_t flen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) *stat = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (!xfs_sb_version_hasreflink(&mp->m_sb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* rt files will have agno set to NULLAGNUMBER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (info->agno == NULLAGNUMBER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* Are there any shared blocks here? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) flen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) cur = xfs_refcountbt_init_cursor(mp, tp, info->agf_bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) info->agno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) error = xfs_refcount_find_shared(cur, rec->rm_startblock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) rec->rm_blockcount, &fbno, &flen, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) xfs_btree_del_cursor(cur, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) *stat = flen > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) xfs_getfsmap_format(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct xfs_fsmap *xfm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct xfs_getfsmap_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) struct fsmap *rec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) trace_xfs_getfsmap_mapping(mp, xfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) rec = &info->fsmap_recs[info->head->fmh_entries++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) xfs_fsmap_from_internal(rec, xfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^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) * Format a reverse mapping for getfsmap, having translated rm_startblock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * into the appropriate daddr units.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) xfs_getfsmap_helper(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct xfs_getfsmap_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct xfs_rmap_irec *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) xfs_daddr_t rec_daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct xfs_fsmap fmr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) bool shared;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) if (fatal_signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) * Filter out records that start before our startpoint, if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * caller requested that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (xfs_rmap_compare(rec, &info->low) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (info->next_daddr < rec_daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) info->next_daddr = rec_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* Are we just counting mappings? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) if (info->head->fmh_count == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (info->head->fmh_entries == UINT_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return -ECANCELED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (rec_daddr > info->next_daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) info->head->fmh_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (info->last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) info->head->fmh_entries++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (info->next_daddr < rec_daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) info->next_daddr = rec_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^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) * If the record starts past the last physical block we saw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * then we've found a gap. Report the gap as being owned by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) * whatever the caller specified is the missing owner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (rec_daddr > info->next_daddr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (info->head->fmh_entries >= info->head->fmh_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return -ECANCELED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) fmr.fmr_device = info->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) fmr.fmr_physical = info->next_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) fmr.fmr_owner = info->missing_owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) fmr.fmr_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) fmr.fmr_length = rec_daddr - info->next_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) fmr.fmr_flags = FMR_OF_SPECIAL_OWNER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) xfs_getfsmap_format(mp, &fmr, info);
^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) if (info->last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) /* Fill out the extent we found */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (info->head->fmh_entries >= info->head->fmh_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return -ECANCELED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) trace_xfs_fsmap_mapping(mp, info->dev, info->agno, rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) fmr.fmr_device = info->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) fmr.fmr_physical = rec_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) error = xfs_fsmap_owner_from_rmap(&fmr, rec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) fmr.fmr_offset = XFS_FSB_TO_BB(mp, rec->rm_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) fmr.fmr_length = XFS_FSB_TO_BB(mp, rec->rm_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (rec->rm_flags & XFS_RMAP_UNWRITTEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) fmr.fmr_flags |= FMR_OF_PREALLOC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (rec->rm_flags & XFS_RMAP_ATTR_FORK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) fmr.fmr_flags |= FMR_OF_ATTR_FORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) fmr.fmr_flags |= FMR_OF_EXTENT_MAP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (fmr.fmr_flags == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) error = xfs_getfsmap_is_shared(tp, info, rec, &shared);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (shared)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) fmr.fmr_flags |= FMR_OF_SHARED;
^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) xfs_getfsmap_format(mp, &fmr, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) rec_daddr += XFS_FSB_TO_BB(mp, rec->rm_blockcount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (info->next_daddr < rec_daddr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) info->next_daddr = rec_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* Transform a rmapbt irec into a fsmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) xfs_getfsmap_datadev_helper(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) struct xfs_rmap_irec *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) struct xfs_mount *mp = cur->bc_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) struct xfs_getfsmap_info *info = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) xfs_fsblock_t fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) xfs_daddr_t rec_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) fsb = XFS_AGB_TO_FSB(mp, cur->bc_ag.agno, rec->rm_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) rec_daddr = XFS_FSB_TO_DADDR(mp, fsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return xfs_getfsmap_helper(cur->bc_tp, info, rec, rec_daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) /* Transform a bnobt irec into a fsmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) xfs_getfsmap_datadev_bnobt_helper(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) struct xfs_btree_cur *cur,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct xfs_alloc_rec_incore *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct xfs_mount *mp = cur->bc_mp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct xfs_getfsmap_info *info = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) struct xfs_rmap_irec irec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) xfs_daddr_t rec_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) rec_daddr = XFS_AGB_TO_DADDR(mp, cur->bc_ag.agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) rec->ar_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) irec.rm_startblock = rec->ar_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) irec.rm_blockcount = rec->ar_blockcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) irec.rm_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) irec.rm_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return xfs_getfsmap_helper(cur->bc_tp, info, &irec, rec_daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* Set rmap flags based on the getfsmap flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) xfs_getfsmap_set_irec_flags(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct xfs_rmap_irec *irec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) struct xfs_fsmap *fmr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) irec->rm_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (fmr->fmr_flags & FMR_OF_ATTR_FORK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) irec->rm_flags |= XFS_RMAP_ATTR_FORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (fmr->fmr_flags & FMR_OF_EXTENT_MAP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) irec->rm_flags |= XFS_RMAP_BMBT_BLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (fmr->fmr_flags & FMR_OF_PREALLOC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) irec->rm_flags |= XFS_RMAP_UNWRITTEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) /* Execute a getfsmap query against the log device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) xfs_getfsmap_logdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct xfs_fsmap *keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) struct xfs_getfsmap_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) struct xfs_rmap_irec rmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* Set up search keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) info->low.rm_startblock = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) error = xfs_fsmap_owner_to_rmap(&info->low, keys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) info->low.rm_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) error = xfs_fsmap_owner_to_rmap(&info->high, keys + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) info->high.rm_startblock = -1U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) info->high.rm_owner = ULLONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) info->high.rm_offset = ULLONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) info->high.rm_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) info->missing_owner = XFS_FMR_OWN_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (keys[0].fmr_physical > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) /* Fabricate an rmap entry for the external log device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) rmap.rm_startblock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) rmap.rm_blockcount = mp->m_sb.sb_logblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) rmap.rm_owner = XFS_RMAP_OWN_LOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) rmap.rm_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) rmap.rm_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return xfs_getfsmap_helper(tp, info, &rmap, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) #ifdef CONFIG_XFS_RT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* Transform a rtbitmap "record" into a fsmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) xfs_getfsmap_rtdev_rtbitmap_helper(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct xfs_rtalloc_rec *rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct xfs_getfsmap_info *info = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct xfs_rmap_irec irec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) xfs_daddr_t rec_daddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) irec.rm_startblock = rec->ar_startext * mp->m_sb.sb_rextsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) rec_daddr = XFS_FSB_TO_BB(mp, irec.rm_startblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) irec.rm_blockcount = rec->ar_extcount * mp->m_sb.sb_rextsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) irec.rm_owner = XFS_RMAP_OWN_NULL; /* "free" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) irec.rm_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) irec.rm_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return xfs_getfsmap_helper(tp, info, &irec, rec_daddr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Execute a getfsmap query against the realtime device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) __xfs_getfsmap_rtdev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) struct xfs_fsmap *keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int (*query_fn)(struct xfs_trans *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct xfs_getfsmap_info *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) struct xfs_getfsmap_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) xfs_fsblock_t start_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) xfs_fsblock_t end_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) xfs_daddr_t eofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) if (keys[0].fmr_physical >= eofs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (keys[1].fmr_physical >= eofs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) keys[1].fmr_physical = eofs - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) start_fsb = XFS_BB_TO_FSBT(mp, keys[0].fmr_physical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) end_fsb = XFS_BB_TO_FSB(mp, keys[1].fmr_physical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* Set up search keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) info->low.rm_startblock = start_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) info->low.rm_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) info->high.rm_startblock = end_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) info->high.rm_offset = XFS_BB_TO_FSBT(mp, keys[1].fmr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) info->high.rm_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) trace_xfs_fsmap_high_key(mp, info->dev, info->agno, &info->high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return query_fn(tp, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* Actually query the realtime bitmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) xfs_getfsmap_rtdev_rtbitmap_query(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct xfs_getfsmap_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct xfs_rtalloc_rec alow = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct xfs_rtalloc_rec ahigh = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) xfs_ilock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) alow.ar_startext = info->low.rm_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) ahigh.ar_startext = info->high.rm_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) do_div(alow.ar_startext, tp->t_mountp->m_sb.sb_rextsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (do_div(ahigh.ar_startext, tp->t_mountp->m_sb.sb_rextsize))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) ahigh.ar_startext++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) error = xfs_rtalloc_query_range(tp, &alow, &ahigh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) xfs_getfsmap_rtdev_rtbitmap_helper, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* Report any gaps at the end of the rtbitmap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) info->last = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) error = xfs_getfsmap_rtdev_rtbitmap_helper(tp, &ahigh, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) xfs_iunlock(tp->t_mountp->m_rbmip, XFS_ILOCK_SHARED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) /* Execute a getfsmap query against the realtime device rtbitmap. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) xfs_getfsmap_rtdev_rtbitmap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) struct xfs_fsmap *keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) struct xfs_getfsmap_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) info->missing_owner = XFS_FMR_OWN_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return __xfs_getfsmap_rtdev(tp, keys, xfs_getfsmap_rtdev_rtbitmap_query,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) #endif /* CONFIG_XFS_RT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* Execute a getfsmap query against the regular data device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) __xfs_getfsmap_datadev(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct xfs_fsmap *keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct xfs_getfsmap_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) int (*query_fn)(struct xfs_trans *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) struct xfs_getfsmap_info *,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct xfs_btree_cur **,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) void *),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) struct xfs_mount *mp = tp->t_mountp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) struct xfs_btree_cur *bt_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) xfs_fsblock_t start_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) xfs_fsblock_t end_fsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) xfs_agnumber_t start_ag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) xfs_agnumber_t end_ag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) xfs_daddr_t eofs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) if (keys[0].fmr_physical >= eofs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (keys[1].fmr_physical >= eofs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) keys[1].fmr_physical = eofs - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) start_fsb = XFS_DADDR_TO_FSB(mp, keys[0].fmr_physical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) end_fsb = XFS_DADDR_TO_FSB(mp, keys[1].fmr_physical);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * Convert the fsmap low/high keys to AG based keys. Initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * low to the fsmap low key and max out the high key to the end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * of the AG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) info->low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) info->low.rm_offset = XFS_BB_TO_FSBT(mp, keys[0].fmr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) error = xfs_fsmap_owner_to_rmap(&info->low, &keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) info->low.rm_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) xfs_getfsmap_set_irec_flags(&info->low, &keys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) info->high.rm_startblock = -1U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) info->high.rm_owner = ULLONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) info->high.rm_offset = ULLONG_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) info->high.rm_blockcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) info->high.rm_flags = XFS_RMAP_KEY_FLAGS | XFS_RMAP_REC_FLAGS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) start_ag = XFS_FSB_TO_AGNO(mp, start_fsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) end_ag = XFS_FSB_TO_AGNO(mp, end_fsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /* Query each AG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) for (info->agno = start_ag; info->agno <= end_ag; info->agno++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * Set the AG high key from the fsmap high key if this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * is the last AG that we're querying.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (info->agno == end_ag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) info->high.rm_startblock = XFS_FSB_TO_AGBNO(mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) end_fsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) info->high.rm_offset = XFS_BB_TO_FSBT(mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) keys[1].fmr_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) error = xfs_fsmap_owner_to_rmap(&info->high, &keys[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) xfs_getfsmap_set_irec_flags(&info->high, &keys[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (bt_cur) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) bt_cur = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) xfs_trans_brelse(tp, info->agf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) info->agf_bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) error = xfs_alloc_read_agf(mp, tp, info->agno, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) &info->agf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) trace_xfs_fsmap_low_key(mp, info->dev, info->agno, &info->low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) trace_xfs_fsmap_high_key(mp, info->dev, info->agno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) &info->high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) error = query_fn(tp, info, &bt_cur, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * Set the AG low key to the start of the AG prior to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * moving on to the next AG.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) if (info->agno == start_ag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) info->low.rm_startblock = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) info->low.rm_owner = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) info->low.rm_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) info->low.rm_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /* Report any gap at the end of the AG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) info->last = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) error = query_fn(tp, info, &bt_cur, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) if (bt_cur)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) XFS_BTREE_NOERROR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (info->agf_bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) xfs_trans_brelse(tp, info->agf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) info->agf_bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) /* Actually query the rmap btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) xfs_getfsmap_datadev_rmapbt_query(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct xfs_getfsmap_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct xfs_btree_cur **curpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) /* Report any gap at the end of the last AG. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (info->last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return xfs_getfsmap_datadev_helper(*curpp, &info->high, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /* Allocate cursor for this AG and query_range it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) *curpp = xfs_rmapbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) info->agno);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) return xfs_rmap_query_range(*curpp, &info->low, &info->high,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) xfs_getfsmap_datadev_helper, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) /* Execute a getfsmap query against the regular data device rmapbt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) xfs_getfsmap_datadev_rmapbt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct xfs_fsmap *keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) struct xfs_getfsmap_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) info->missing_owner = XFS_FMR_OWN_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return __xfs_getfsmap_datadev(tp, keys, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) xfs_getfsmap_datadev_rmapbt_query, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* Actually query the bno btree. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) xfs_getfsmap_datadev_bnobt_query(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct xfs_getfsmap_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) struct xfs_btree_cur **curpp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) struct xfs_alloc_rec_incore *key = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* Report any gap at the end of the last AG. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (info->last)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) return xfs_getfsmap_datadev_bnobt_helper(*curpp, &key[1], info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) /* Allocate cursor for this AG and query_range it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) *curpp = xfs_allocbt_init_cursor(tp->t_mountp, tp, info->agf_bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) info->agno, XFS_BTNUM_BNO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) key->ar_startblock = info->low.rm_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) key[1].ar_startblock = info->high.rm_startblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return xfs_alloc_query_range(*curpp, key, &key[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) xfs_getfsmap_datadev_bnobt_helper, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* Execute a getfsmap query against the regular data device's bnobt. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) xfs_getfsmap_datadev_bnobt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) struct xfs_trans *tp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) struct xfs_fsmap *keys,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) struct xfs_getfsmap_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct xfs_alloc_rec_incore akeys[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) info->missing_owner = XFS_FMR_OWN_UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return __xfs_getfsmap_datadev(tp, keys, info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) xfs_getfsmap_datadev_bnobt_query, &akeys[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* Do we recognize the device? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) STATIC bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) xfs_getfsmap_is_valid_device(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) struct xfs_fsmap *fm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (fm->fmr_device == 0 || fm->fmr_device == UINT_MAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) fm->fmr_device == new_encode_dev(mp->m_ddev_targp->bt_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (mp->m_logdev_targp &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) fm->fmr_device == new_encode_dev(mp->m_logdev_targp->bt_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (mp->m_rtdev_targp &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) fm->fmr_device == new_encode_dev(mp->m_rtdev_targp->bt_dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* Ensure that the low key is less than the high key. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) STATIC bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) xfs_getfsmap_check_keys(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct xfs_fsmap *low_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) struct xfs_fsmap *high_key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (low_key->fmr_device > high_key->fmr_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (low_key->fmr_device < high_key->fmr_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (low_key->fmr_physical > high_key->fmr_physical)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (low_key->fmr_physical < high_key->fmr_physical)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (low_key->fmr_owner > high_key->fmr_owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (low_key->fmr_owner < high_key->fmr_owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) if (low_key->fmr_offset > high_key->fmr_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (low_key->fmr_offset < high_key->fmr_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * There are only two devices if we didn't configure RT devices at build time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) #ifdef CONFIG_XFS_RT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) #define XFS_GETFSMAP_DEVS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) #define XFS_GETFSMAP_DEVS 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) #endif /* CONFIG_XFS_RT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * Get filesystem's extents as described in head, and format for output. Fills
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * in the supplied records array until there are no more reverse mappings to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * return or head.fmh_entries == head.fmh_count. In the second case, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * function returns -ECANCELED to indicate that more records would have been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) * Key to Confusion
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) * ----------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) * There are multiple levels of keys and counters at work here:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) * xfs_fsmap_head.fmh_keys -- low and high fsmap keys passed in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) * these reflect fs-wide sector addrs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) * dkeys -- fmh_keys used to query each device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) * these are fmh_keys but w/ the low key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) * bumped up by fmr_length.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * xfs_getfsmap_info.next_daddr -- next disk addr we expect to see; this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * is how we detect gaps in the fsmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) records and report them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * xfs_getfsmap_info.low/high -- per-AG low/high keys computed from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * dkeys; used to query the metadata.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) xfs_getfsmap(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct xfs_mount *mp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct xfs_fsmap_head *head,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct fsmap *fsmap_recs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) struct xfs_trans *tp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) struct xfs_fsmap dkeys[2]; /* per-dev keys */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) struct xfs_getfsmap_dev handlers[XFS_GETFSMAP_DEVS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct xfs_getfsmap_info info = { NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) bool use_rmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) if (head->fmh_iflags & ~FMH_IF_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[0]) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) !xfs_getfsmap_is_valid_device(mp, &head->fmh_keys[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) use_rmap = capable(CAP_SYS_ADMIN) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) xfs_sb_version_hasrmapbt(&mp->m_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) head->fmh_entries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) /* Set up our device handlers. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) memset(handlers, 0, sizeof(handlers));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) handlers[0].dev = new_encode_dev(mp->m_ddev_targp->bt_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (use_rmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) handlers[0].fn = xfs_getfsmap_datadev_rmapbt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) handlers[0].fn = xfs_getfsmap_datadev_bnobt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (mp->m_logdev_targp != mp->m_ddev_targp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) handlers[1].dev = new_encode_dev(mp->m_logdev_targp->bt_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) handlers[1].fn = xfs_getfsmap_logdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) #ifdef CONFIG_XFS_RT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (mp->m_rtdev_targp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) handlers[2].dev = new_encode_dev(mp->m_rtdev_targp->bt_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) handlers[2].fn = xfs_getfsmap_rtdev_rtbitmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) #endif /* CONFIG_XFS_RT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) xfs_sort(handlers, XFS_GETFSMAP_DEVS, sizeof(struct xfs_getfsmap_dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) xfs_getfsmap_dev_compare);
^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) * To continue where we left off, we allow userspace to use the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) * last mapping from a previous call as the low key of the next.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) * This is identified by a non-zero length in the low key. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * have to increment the low key in this scenario to ensure we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) * don't return the same mapping again, and instead return the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) * very next mapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) * If the low key mapping refers to file data, the same physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) * blocks could be mapped to several other files/offsets.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * According to rmapbt record ordering, the minimal next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * possible record for the block range is the next starting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * offset in the same inode. Therefore, bump the file offset to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * continue the search appropriately. For all other low key
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) * mapping types (attr blocks, metadata), bump the physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) * offset as there can be no other mapping for the same physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) * block range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) dkeys[0] = head->fmh_keys[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) if (dkeys[0].fmr_flags & (FMR_OF_SPECIAL_OWNER | FMR_OF_EXTENT_MAP)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) dkeys[0].fmr_physical += dkeys[0].fmr_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) dkeys[0].fmr_owner = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (dkeys[0].fmr_offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) dkeys[0].fmr_offset += dkeys[0].fmr_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) dkeys[0].fmr_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) memset(&dkeys[1], 0xFF, sizeof(struct xfs_fsmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (!xfs_getfsmap_check_keys(dkeys, &head->fmh_keys[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) info.next_daddr = head->fmh_keys[0].fmr_physical +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) head->fmh_keys[0].fmr_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) info.fsmap_recs = fsmap_recs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) info.head = head;
^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) * If fsmap runs concurrently with a scrub, the freeze can be delayed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * indefinitely as we walk the rmapbt and iterate over metadata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * buffers. Freeze quiesces the log (which waits for the buffer LRU to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) * be emptied) and that won't happen while we're reading buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) sb_start_write(mp->m_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) /* For each device we support... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) /* Is this device within the range the user asked for? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) if (!handlers[i].fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) if (head->fmh_keys[0].fmr_device > handlers[i].dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) if (head->fmh_keys[1].fmr_device < handlers[i].dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) * If this device number matches the high key, we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * to pass the high key to the handler to limit the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * query results. If the device number exceeds the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * low key, zero out the low key so that we get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * everything from the beginning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (handlers[i].dev == head->fmh_keys[1].fmr_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) dkeys[1] = head->fmh_keys[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (handlers[i].dev > head->fmh_keys[0].fmr_device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) error = xfs_trans_alloc_empty(mp, &tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) info.dev = handlers[i].dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) info.last = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) info.agno = NULLAGNUMBER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) error = handlers[i].fn(tp, dkeys, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) tp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) info.next_daddr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (tp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) xfs_trans_cancel(tp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) sb_end_write(mp->m_super);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) head->fmh_oflags = FMH_OF_DEV_T;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }