^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) 2000-2005 Silicon Graphics, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "xfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "xfs_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "xfs_shared.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "xfs_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "xfs_log_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "xfs_trans_resv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "xfs_mount.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "xfs_defer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "xfs_da_format.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "xfs_da_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "xfs_attr_sf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "xfs_inode.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "xfs_trans.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "xfs_bmap.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "xfs_bmap_btree.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "xfs_attr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "xfs_attr_leaf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "xfs_attr_remote.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "xfs_quota.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "xfs_trans_space.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "xfs_trace.h"
^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) * xfs_attr.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Provide the external interfaces to manage attribute lists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /*========================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * Function prototypes for the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *========================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Internal routines when attribute list fits inside the inode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * Internal routines when attribute list is one block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) STATIC int xfs_attr_leaf_hasname(struct xfs_da_args *args, struct xfs_buf **bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * Internal routines when attribute list is more than one block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) STATIC int xfs_attr_node_get(xfs_da_args_t *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) STATIC int xfs_attr_node_hasname(xfs_da_args_t *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) struct xfs_da_state **state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) xfs_inode_hasattr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct xfs_inode *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (!XFS_IFORK_Q(ip) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ip->i_afp->if_nextents == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*========================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * Overall external interface routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) *========================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * Retrieve an extended attribute and its value. Must have ilock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Returns 0 on successful retrieval, otherwise an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) xfs_attr_get_ilocked(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ASSERT(xfs_isilocked(args->dp, XFS_ILOCK_SHARED | XFS_ILOCK_EXCL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (!xfs_inode_hasattr(args->dp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -ENOATTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (args->dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return xfs_attr_shortform_getvalue(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (xfs_bmap_one_block(args->dp, XFS_ATTR_FORK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return xfs_attr_leaf_get(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return xfs_attr_node_get(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Retrieve an extended attribute by name, and its value if requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * If args->valuelen is zero, then the caller does not want the value, just an
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * indication whether the attribute exists and the size of the value if it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * exists. The size is returned in args.valuelen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * If args->value is NULL but args->valuelen is non-zero, allocate the buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * for the value after existence of the attribute has been determined. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * caller always has to free args->value if it is set, no matter if this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * function was successful or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * If the attribute is found, but exceeds the size limit set by the caller in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * args->valuelen, return -ERANGE with the size of the attribute that was found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * in args->valuelen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) xfs_attr_get(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) uint lock_mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) XFS_STATS_INC(args->dp->i_mount, xs_attr_get);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (XFS_FORCED_SHUTDOWN(args->dp->i_mount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) args->geo = args->dp->i_mount->m_attr_geo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) args->whichfork = XFS_ATTR_FORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) args->hashval = xfs_da_hashname(args->name, args->namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Entirely possible to look up a name which doesn't exist */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) args->op_flags = XFS_DA_OP_OKNOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) lock_mode = xfs_ilock_attr_map_shared(args->dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) error = xfs_attr_get_ilocked(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) xfs_iunlock(args->dp, lock_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * Calculate how many blocks we need for the new attribute,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) xfs_attr_calc_size(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int *local)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct xfs_mount *mp = args->dp->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) int nblks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * Determine space new attribute will use, and if it would be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * "local" or "remote" (note: local != inline).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) size = xfs_attr_leaf_newentsize(args, local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) nblks = XFS_DAENTER_SPACE_RES(mp, XFS_ATTR_FORK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (*local) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (size > (args->geo->blksize / 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /* Double split possible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) nblks *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * Out of line attribute, cannot double split, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * make room for the attribute value itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) uint dblocks = xfs_attr3_rmt_blocks(mp, args->valuelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) nblks += dblocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) nblks += XFS_NEXTENTADD_SPACE_RES(mp, dblocks, XFS_ATTR_FORK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return nblks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) xfs_attr_try_sf_addname(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct xfs_inode *dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * Build initial attribute list (if required).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (dp->i_afp->if_format == XFS_DINODE_FMT_EXTENTS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) xfs_attr_shortform_create(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) error = xfs_attr_shortform_addname(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (error == -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * Commit the shortform mods, and we're done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * NOTE: this is also the error path (EEXIST, etc).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (!error && !(args->op_flags & XFS_DA_OP_NOTIME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (dp->i_mount->m_flags & XFS_MOUNT_WSYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) xfs_trans_set_sync(args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * Check to see if the attr should be upgraded from non-existent or shortform to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * single-leaf-block attribute list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static inline bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) xfs_attr_is_shortform(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct xfs_inode *ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return ip->i_afp->if_format == XFS_DINODE_FMT_LOCAL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ip->i_afp->if_nextents == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^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) * Attempts to set an attr in shortform, or converts short form to leaf form if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * there is not enough room. If the attr is set, the transaction is committed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * and set to NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) xfs_attr_set_shortform(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) struct xfs_buf **leaf_bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) int error, error2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * Try to add the attr to the attribute list in the inode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) error = xfs_attr_try_sf_addname(dp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (error != -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) error2 = xfs_trans_commit(args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) args->trans = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return error ? error : error2;
^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) * It won't fit in the shortform, transform to a leaf block. GROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * another possible req'mt for a double-split btree op.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) error = xfs_attr_shortform_to_leaf(args, leaf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) * Prevent the leaf buffer from being unlocked so that a concurrent AIL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * push cannot grab the half-baked leaf buffer and run into problems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * with the write verifier. Once we're done rolling the transaction we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * can release the hold and add the attr to the leaf.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) xfs_trans_bhold(args->trans, *leaf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) error = xfs_defer_finish(&args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) xfs_trans_bhold_release(args->trans, *leaf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) xfs_trans_brelse(args->trans, *leaf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * Set the attribute specified in @args.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) xfs_attr_set_args(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct xfs_buf *leaf_bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * If the attribute list is already in leaf format, jump straight to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * leaf handling. Otherwise, try to add the attribute to the shortform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * list; if there's no room then convert the list to leaf format and try
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (xfs_attr_is_shortform(dp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * If the attr was successfully set in shortform, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) * transaction is committed and set to NULL. Otherwise, is it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) * converted from shortform to leaf, and the transaction is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) * retained.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) error = xfs_attr_set_shortform(args, &leaf_bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) if (error || !args->trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) error = xfs_attr_leaf_addname(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (error != -ENOSPC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * Promote the attribute list to the Btree format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) error = xfs_attr3_leaf_to_node(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * Finish any deferred work items and roll the transaction once
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * more. The goal here is to call node_addname with the inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * and transaction in the same state (inode locked and joined,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * transaction clean) no matter how we got to this step.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) error = xfs_defer_finish(&args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) * Commit the current trans (including the inode) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) * start a new one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) error = xfs_trans_roll_inode(&args->trans, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) error = xfs_attr_node_addname(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) * Return EEXIST if attr is found, or ENOATTR if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) xfs_has_attr(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct xfs_buf *bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if (!xfs_inode_hasattr(dp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return -ENOATTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return xfs_attr_sf_findname(args, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) error = xfs_attr_leaf_hasname(args, &bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) xfs_trans_brelse(args->trans, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return xfs_attr_node_hasname(args, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) }
^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) * Remove the attribute specified in @args.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) xfs_attr_remove_args(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) if (!xfs_inode_hasattr(dp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) error = -ENOATTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) } else if (dp->i_afp->if_format == XFS_DINODE_FMT_LOCAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) error = xfs_attr_shortform_remove(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) error = xfs_attr_leaf_removename(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) error = xfs_attr_node_removename(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) return error;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * Note: If args->value is NULL the attribute will be removed, just like the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * Linux ->setattr API.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) xfs_attr_set(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) struct xfs_mount *mp = dp->i_mount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct xfs_trans_res tres;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) bool rsvd = (args->attr_filter & XFS_ATTR_ROOT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int error, local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) unsigned int total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (XFS_FORCED_SHUTDOWN(dp->i_mount))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) error = xfs_qm_dqattach(dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) args->geo = mp->m_attr_geo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) args->whichfork = XFS_ATTR_FORK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) args->hashval = xfs_da_hashname(args->name, args->namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * We have no control over the attribute names that userspace passes us
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * to remove, so we have to allow the name lookup prior to attribute
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * removal to fail as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) args->op_flags = XFS_DA_OP_OKNOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) if (args->value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) XFS_STATS_INC(mp, xs_attr_set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) args->op_flags |= XFS_DA_OP_ADDNAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) args->total = xfs_attr_calc_size(args, &local);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * If the inode doesn't have an attribute fork, add one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * (inode must not be locked when we call this routine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (XFS_IFORK_Q(dp) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) int sf_size = sizeof(struct xfs_attr_sf_hdr) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) xfs_attr_sf_entsize_byname(args->namelen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) args->valuelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) error = xfs_bmap_add_attrfork(dp, sf_size, rsvd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) M_RES(mp)->tr_attrsetrt.tr_logres *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) args->total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) tres.tr_logcount = XFS_ATTRSET_LOG_COUNT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) tres.tr_logflags = XFS_TRANS_PERM_LOG_RES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) total = args->total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) XFS_STATS_INC(mp, xs_attr_remove);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) tres = M_RES(mp)->tr_attrrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) total = XFS_ATTRRM_SPACE_RES(mp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * Root fork attributes can use reserved data blocks for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * operation if necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) error = xfs_trans_alloc(mp, &tres, total, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) rsvd ? XFS_TRANS_RESERVE : 0, &args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) xfs_ilock(dp, XFS_ILOCK_EXCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) xfs_trans_ijoin(args->trans, dp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (args->value) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) unsigned int quota_flags = XFS_QMOPT_RES_REGBLKS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (rsvd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) quota_flags |= XFS_QMOPT_FORCE_RES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) error = xfs_trans_reserve_quota_nblks(args->trans, dp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) args->total, 0, quota_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) goto out_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) error = xfs_has_attr(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (error == -EEXIST && (args->attr_flags & XATTR_CREATE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) goto out_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) if (error == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) goto out_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (error != -ENOATTR && error != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) goto out_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) error = xfs_attr_set_args(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) goto out_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* shortform attribute has already been committed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (!args->trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) error = xfs_has_attr(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (error != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) goto out_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) error = xfs_attr_remove_args(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) goto out_trans_cancel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * If this is a synchronous mount, make sure that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * transaction goes to disk before returning to the user.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (mp->m_flags & XFS_MOUNT_WSYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) xfs_trans_set_sync(args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (!(args->op_flags & XFS_DA_OP_NOTIME))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) xfs_trans_ichgtime(args->trans, dp, XFS_ICHGTIME_CHG);
^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) * Commit the last in the sequence of transactions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) error = xfs_trans_commit(args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) out_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) xfs_iunlock(dp, XFS_ILOCK_EXCL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) out_trans_cancel:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (args->trans)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) xfs_trans_cancel(args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) goto out_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) /*========================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) * External routines when attribute list is inside the inode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) *========================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static inline int xfs_attr_sf_totsize(struct xfs_inode *dp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct xfs_attr_shortform *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) sf = (struct xfs_attr_shortform *)dp->i_afp->if_u1.if_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return be16_to_cpu(sf->hdr.totsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * Add a name to the shortform attribute list structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * This is the external routine.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) xfs_attr_shortform_addname(xfs_da_args_t *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) int newsize, forkoff, retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) trace_xfs_attr_sf_addname(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) retval = xfs_attr_shortform_lookup(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (retval == -EEXIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (args->attr_flags & XATTR_CREATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) retval = xfs_attr_shortform_remove(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) * Since we have removed the old attr, clear ATTR_REPLACE so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * that the leaf format add routine won't trip over the attr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) * not being around.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) args->attr_flags &= ~XATTR_REPLACE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (args->namelen >= XFS_ATTR_SF_ENTSIZE_MAX ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) args->valuelen >= XFS_ATTR_SF_ENTSIZE_MAX)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) newsize = xfs_attr_sf_totsize(args->dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) newsize += xfs_attr_sf_entsize_byname(args->namelen, args->valuelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) forkoff = xfs_attr_shortform_bytesfit(args->dp, newsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (!forkoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) xfs_attr_shortform_add(args, forkoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return 0;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) /*========================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * External routines when attribute list is one block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) *========================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) /* Store info about a remote block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) STATIC void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) xfs_attr_save_rmt_blk(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) args->blkno2 = args->blkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) args->index2 = args->index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) args->rmtblkno2 = args->rmtblkno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) args->rmtblkcnt2 = args->rmtblkcnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) args->rmtvaluelen2 = args->rmtvaluelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) /* Set stored info about a remote block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) STATIC void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) xfs_attr_restore_rmt_blk(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) args->blkno = args->blkno2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) args->index = args->index2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) args->rmtblkno = args->rmtblkno2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) args->rmtblkcnt = args->rmtblkcnt2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) args->rmtvaluelen = args->rmtvaluelen2;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * Tries to add an attribute to an inode in leaf form
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * This function is meant to execute as part of a delayed operation and leaves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * the transaction handling to the caller. On success the attribute is added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * and the inode and transaction are left dirty. If there is not enough space,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * the attr data is converted to node format and -ENOSPC is returned. Caller is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * responsible for handling the dirty inode and transaction or adding the attr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * in node format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) xfs_attr_leaf_try_add(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) struct xfs_buf *bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * Look up the given attribute in the leaf block. Figure out if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * the given flags produce an error or call for an atomic rename.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) retval = xfs_attr_leaf_hasname(args, &bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (retval != -ENOATTR && retval != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) goto out_brelse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (retval == -EEXIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (args->attr_flags & XATTR_CREATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) goto out_brelse;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) trace_xfs_attr_leaf_replace(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) /* save the attribute state for later removal*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) args->op_flags |= XFS_DA_OP_RENAME; /* an atomic rename */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) xfs_attr_save_rmt_blk(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * clear the remote attr state now that it is saved so that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * values reflect the state of the attribute we are about to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * add, not the attribute we just found and will remove later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) args->rmtblkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) args->rmtblkcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) args->rmtvaluelen = 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) * Add the attribute to the leaf block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return xfs_attr3_leaf_add(bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) out_brelse:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) xfs_trans_brelse(args->trans, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) return retval;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * Add a name to the leaf attribute list structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * This leaf block cannot have a "remote" value, we only call this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * if bmap_one_block() says there is only one block (ie: no remote blks).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) xfs_attr_leaf_addname(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) int error, forkoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) struct xfs_buf *bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) trace_xfs_attr_leaf_addname(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) error = xfs_attr_leaf_try_add(args, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * Commit the transaction that added the attr name so that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * later routines can manage their own transactions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) error = xfs_trans_roll_inode(&args->trans, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) * If there was an out-of-line value, allocate the blocks we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * identified for its storage and copy the value. This is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * after we create the attribute so that we don't overflow the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * maximum size of a transaction and/or hit a deadlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (args->rmtblkno > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) error = xfs_attr_rmtval_set(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (!(args->op_flags & XFS_DA_OP_RENAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * Added a "remote" value, just clear the incomplete flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) if (args->rmtblkno > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) error = xfs_attr3_leaf_clearflag(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * If this is an atomic rename operation, we must "flip" the incomplete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * flags on the "new" and "old" attribute/value pairs so that one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * disappears and one appears atomically. Then we must remove the "old"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * attribute/value pair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * In a separate transaction, set the incomplete flag on the "old" attr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * and clear the incomplete flag on the "new" attr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) error = xfs_attr3_leaf_flipflags(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) * Commit the flag value change and start the next trans in series.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) error = xfs_trans_roll_inode(&args->trans, args->dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return error;
^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) * Dismantle the "old" attribute/value pair by removing a "remote" value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * (if it exists).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) xfs_attr_restore_rmt_blk(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (args->rmtblkno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) error = xfs_attr_rmtval_invalidate(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) error = xfs_attr_rmtval_remove(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * Read in the block containing the "old" attr, then remove the "old"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * attr from that block (neat, huh!)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) &bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) xfs_attr3_leaf_remove(bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * If the result is small enough, shrink it all into the inode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) forkoff = xfs_attr_shortform_allfit(bp, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (forkoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) /* bp is gone due to xfs_da_shrink_inode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) * Return EEXIST if attr is found, or ENOATTR if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) xfs_attr_leaf_hasname(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct xfs_buf **bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) error = xfs_attr3_leaf_read(args->trans, args->dp, 0, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) error = xfs_attr3_leaf_lookup_int(*bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (error != -ENOATTR && error != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) xfs_trans_brelse(args->trans, *bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) * Remove a name from the leaf attribute list structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * This leaf block cannot have a "remote" value, we only call this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) * if bmap_one_block() says there is only one block (ie: no remote blks).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) xfs_attr_leaf_removename(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct xfs_inode *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct xfs_buf *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) int error, forkoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) trace_xfs_attr_leaf_removename(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) * Remove the attribute.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) error = xfs_attr_leaf_hasname(args, &bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (error == -ENOATTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) xfs_trans_brelse(args->trans, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) } else if (error != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) xfs_attr3_leaf_remove(bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * If the result is small enough, shrink it all into the inode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) forkoff = xfs_attr_shortform_allfit(bp, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (forkoff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return xfs_attr3_leaf_to_shortform(bp, args, forkoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /* bp is gone due to xfs_da_shrink_inode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * Look up a name in a leaf attribute list structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) * This leaf block cannot have a "remote" value, we only call this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) * if bmap_one_block() says there is only one block (ie: no remote blks).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) * Returns 0 on successful retrieval, otherwise an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) xfs_attr_leaf_get(xfs_da_args_t *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) struct xfs_buf *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) trace_xfs_attr_leaf_get(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) error = xfs_attr_leaf_hasname(args, &bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (error == -ENOATTR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) xfs_trans_brelse(args->trans, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) } else if (error != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) error = xfs_attr3_leaf_getvalue(bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) xfs_trans_brelse(args->trans, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * Return EEXIST if attr is found, or ENOATTR if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * statep: If not null is set to point at the found state. Caller will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * be responsible for freeing the state in this case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) xfs_attr_node_hasname(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) struct xfs_da_state **statep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) struct xfs_da_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) int retval, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) state = xfs_da_state_alloc(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (statep != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) *statep = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * Search to see if name exists, and get back a pointer to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) error = xfs_da3_node_lookup_int(state, &retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) xfs_da_state_free(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (statep != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) *statep = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) xfs_da_state_free(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) /*========================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) * External routines when attribute list size > geo->blksize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) *========================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) * Add a name to a Btree-format attribute list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) * This will involve walking down the Btree, and may involve splitting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) * leaf nodes and even splitting intermediate nodes up to and including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) * the root node (a special case of an intermediate node).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) * "Remote" attribute values confuse the issue and atomic rename operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * add a whole extra layer of confusion on top of that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) xfs_attr_node_addname(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) struct xfs_da_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct xfs_da_state_blk *blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct xfs_inode *dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) int retval, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) trace_xfs_attr_node_addname(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * Fill in bucket of arguments/results/context to carry around.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) restart:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) * Search to see if name already exists, and get back a pointer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * to where it should go.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) retval = xfs_attr_node_hasname(args, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (retval != -ENOATTR && retval != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) blk = &state->path.blk[ state->path.active-1 ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (retval == -ENOATTR && (args->attr_flags & XATTR_REPLACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (retval == -EEXIST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) if (args->attr_flags & XATTR_CREATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) trace_xfs_attr_node_replace(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* save the attribute state for later removal*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) args->op_flags |= XFS_DA_OP_RENAME; /* atomic rename op */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) xfs_attr_save_rmt_blk(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) * clear the remote attr state now that it is saved so that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) * values reflect the state of the attribute we are about to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) * add, not the attribute we just found and will remove later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) args->rmtblkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) args->rmtblkcnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) args->rmtvaluelen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) retval = xfs_attr3_leaf_add(blk->bp, state->args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) if (retval == -ENOSPC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (state->path.active == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) * Its really a single leaf node, but it had
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) * out-of-line values so it looked like it *might*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) * have been a b-tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) xfs_da_state_free(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) error = xfs_attr3_leaf_to_node(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) error = xfs_defer_finish(&args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) * Commit the node conversion and start the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * trans in the chain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) error = xfs_trans_roll_inode(&args->trans, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) goto restart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * Split as many Btree elements as required.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * This code tracks the new and old attr's location
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) * in the index/blkno/rmtblkno/rmtblkcnt fields and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) error = xfs_da3_split(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) error = xfs_defer_finish(&args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * Addition succeeded, update Btree hashvals.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) xfs_da3_fixhashpath(state, &state->path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * Kill the state structure, we're done with it and need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * allow the buffers to come back later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) xfs_da_state_free(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) state = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) * Commit the leaf addition or btree split and start the next
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) * trans in the chain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) error = xfs_trans_roll_inode(&args->trans, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) * If there was an out-of-line value, allocate the blocks we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) * identified for its storage and copy the value. This is done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) * after we create the attribute so that we don't overflow the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) * maximum size of a transaction and/or hit a deadlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (args->rmtblkno > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) error = xfs_attr_rmtval_set(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!(args->op_flags & XFS_DA_OP_RENAME)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) * Added a "remote" value, just clear the incomplete flag.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (args->rmtblkno > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) error = xfs_attr3_leaf_clearflag(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) retval = error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) * If this is an atomic rename operation, we must "flip" the incomplete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * flags on the "new" and "old" attribute/value pairs so that one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) * disappears and one appears atomically. Then we must remove the "old"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) * attribute/value pair.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) * In a separate transaction, set the incomplete flag on the "old" attr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) * and clear the incomplete flag on the "new" attr.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) error = xfs_attr3_leaf_flipflags(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) * Commit the flag value change and start the next trans in series
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) error = xfs_trans_roll_inode(&args->trans, args->dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * Dismantle the "old" attribute/value pair by removing a "remote" value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) * (if it exists).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) xfs_attr_restore_rmt_blk(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) if (args->rmtblkno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) error = xfs_attr_rmtval_invalidate(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) error = xfs_attr_rmtval_remove(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * Re-find the "old" attribute entry after any split ops. The INCOMPLETE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * flag means that we will find the "old" attr, not the "new" one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) args->attr_filter |= XFS_ATTR_INCOMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) state = xfs_da_state_alloc(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) state->inleaf = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) error = xfs_da3_node_lookup_int(state, &retval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * Remove the name and update the hashvals in the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) blk = &state->path.blk[state->path.active-1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) error = xfs_attr3_leaf_remove(blk->bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) xfs_da3_fixhashpath(state, &state->path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) * Check to see if the tree needs to be collapsed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) if (retval && (state->path.active > 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) error = xfs_da3_join(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) retval = error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) xfs_da_state_free(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * Shrink an attribute from leaf to shortform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) xfs_attr_node_shrink(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) struct xfs_da_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) int error, forkoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) struct xfs_buf *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) * Have to get rid of the copy of this dabuf in the state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) ASSERT(state->path.active == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) ASSERT(state->path.blk[0].bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) state->path.blk[0].bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) forkoff = xfs_attr_shortform_allfit(bp, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (forkoff) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) /* bp is gone due to xfs_da_shrink_inode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) xfs_trans_brelse(args->trans, bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * for later deletion of the entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) xfs_attr_leaf_mark_incomplete(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) struct xfs_da_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) * Fill in disk block numbers in the state structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) * so that we can get the buffers back after we commit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) * several transactions in the following calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) error = xfs_attr_fillstate(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) * Mark the attribute as INCOMPLETE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) return xfs_attr3_leaf_setflag(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * Initial setup for xfs_attr_node_removename. Make sure the attr is there and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * the blocks are valid. Attr keys with remote blocks will be marked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) * incomplete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) STATIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) int xfs_attr_node_removename_setup(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) struct xfs_da_state **state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) error = xfs_attr_node_hasname(args, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) if (error != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) ASSERT((*state)->path.blk[(*state)->path.active - 1].bp != NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) ASSERT((*state)->path.blk[(*state)->path.active - 1].magic ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) XFS_ATTR_LEAF_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (args->rmtblkno > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) error = xfs_attr_leaf_mark_incomplete(args, *state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) return xfs_attr_rmtval_invalidate(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) xfs_attr_node_remove_rmt(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) struct xfs_da_args *args,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) struct xfs_da_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) error = xfs_attr_rmtval_remove(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) * Refill the state structure with buffers, the prior calls released our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) return xfs_attr_refillstate(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) * Remove a name from a B-tree attribute list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) * This will involve walking down the Btree, and may involve joining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) * leaf nodes and even joining intermediate nodes up to and including
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) * the root node (a special case of an intermediate node).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) xfs_attr_node_removename(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) struct xfs_da_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct xfs_da_state_blk *blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) int retval, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) struct xfs_inode *dp = args->dp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) trace_xfs_attr_node_removename(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) error = xfs_attr_node_removename_setup(args, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * If there is an out-of-line value, de-allocate the blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) * This is done before we remove the attribute so that we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) * overflow the maximum size of a transaction and/or hit a deadlock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) if (args->rmtblkno > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) error = xfs_attr_node_remove_rmt(args, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) * Remove the name and update the hashvals in the tree.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) blk = &state->path.blk[ state->path.active-1 ];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) retval = xfs_attr3_leaf_remove(blk->bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) xfs_da3_fixhashpath(state, &state->path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * Check to see if the tree needs to be collapsed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) if (retval && (state->path.active > 1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) error = xfs_da3_join(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) error = xfs_defer_finish(&args->trans);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) * Commit the Btree join operation and start a new trans.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) error = xfs_trans_roll_inode(&args->trans, dp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * If the result is small enough, push it all into the inode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) error = xfs_attr_node_shrink(args, state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) xfs_da_state_free(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) * Fill in the disk block numbers in the state structure for the buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) * that are attached to the state structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) * This is done so that we can quickly reattach ourselves to those buffers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) * after some set of transaction commits have released these buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) xfs_attr_fillstate(xfs_da_state_t *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) xfs_da_state_path_t *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) xfs_da_state_blk_t *blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) int level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) trace_xfs_attr_fillstate(state->args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) * Roll down the "path" in the state structure, storing the on-disk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) * block number for those buffers in the "path".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) path = &state->path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) if (blk->bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) blk->bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) blk->disk_blkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * Roll down the "altpath" in the state structure, storing the on-disk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) * block number for those buffers in the "altpath".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) path = &state->altpath;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (blk->bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) blk->disk_blkno = XFS_BUF_ADDR(blk->bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) blk->bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) blk->disk_blkno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) * Reattach the buffers to the state structure based on the disk block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) * numbers stored in the state structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) * This is done after some set of transaction commits have released those
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) * buffers from our grip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) xfs_attr_refillstate(xfs_da_state_t *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) xfs_da_state_path_t *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) xfs_da_state_blk_t *blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) int level, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) trace_xfs_attr_refillstate(state->args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * Roll down the "path" in the state structure, storing the on-disk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * block number for those buffers in the "path".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) path = &state->path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) if (blk->disk_blkno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) error = xfs_da3_node_read_mapped(state->args->trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) state->args->dp, blk->disk_blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) &blk->bp, XFS_ATTR_FORK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) blk->bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) * Roll down the "altpath" in the state structure, storing the on-disk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) * block number for those buffers in the "altpath".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) path = &state->altpath;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) for (blk = path->blk, level = 0; level < path->active; blk++, level++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) if (blk->disk_blkno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) error = xfs_da3_node_read_mapped(state->args->trans,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) state->args->dp, blk->disk_blkno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) &blk->bp, XFS_ATTR_FORK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) if (error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) blk->bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * Retrieve the attribute data from a node attribute list.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) * This routine gets called for any attribute fork that has more than one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) * block, ie: both true Btree attr lists and for single-leaf-blocks with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) * "remote" values taking up more blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) * Returns 0 on successful retrieval, otherwise an error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) STATIC int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) xfs_attr_node_get(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) struct xfs_da_args *args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) struct xfs_da_state *state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) struct xfs_da_state_blk *blk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) int error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) trace_xfs_attr_node_get(args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) * Search to see if name exists, and get back a pointer to it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) error = xfs_attr_node_hasname(args, &state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) if (error != -EEXIST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) goto out_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) * Get the value, local or "remote"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) blk = &state->path.blk[state->path.active - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) error = xfs_attr3_leaf_getvalue(blk->bp, args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * If not in a transaction, we have to release all the buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) out_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) for (i = 0; state != NULL && i < state->path.active; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) xfs_trans_brelse(args->trans, state->path.blk[i].bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) state->path.blk[i].bp = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) xfs_da_state_free(state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) /* Returns true if the attribute entry name is valid. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) xfs_attr_namecheck(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) const void *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) * MAXNAMELEN includes the trailing null, but (name/length) leave it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) * out, so use >= for the length check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) if (length >= MAXNAMELEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) /* There shouldn't be any nulls here */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) return !memchr(name, 0, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) }