xfs: add an explicit owner field to xfs_da_args
authorDarrick J. Wong <djwong@kernel.org>
Mon, 15 Apr 2024 21:54:34 +0000 (14:54 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Mon, 15 Apr 2024 21:58:50 +0000 (14:58 -0700)
Add an explicit owner field to xfs_da_args, which will make it easier
for online fsck to set the owner field of the temporary directory and
xattr structures that it builds to repair damaged metadata.

Note: I hopefully found all the xfs_da_args definitions by looking for
automatic stack variable declarations and xfs_da_args.dp assignments:

git grep -E '(args.*dp =|struct xfs_da_args[[:space:]]*[a-z0-9][a-z0-9]*)'

Note that callers of xfs_attr_{get,set,change} can set the owner to zero
(or leave it unset) to have the default set to args->dp.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
13 files changed:
fs/xfs/libxfs/xfs_attr.c
fs/xfs/libxfs/xfs_attr_leaf.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_da_btree.h
fs/xfs/libxfs/xfs_dir2.c
fs/xfs/libxfs/xfs_exchmaps.c
fs/xfs/scrub/attr.c
fs/xfs/scrub/dabtree.c
fs/xfs/scrub/dir.c
fs/xfs/scrub/readdir.c
fs/xfs/xfs_attr_item.c
fs/xfs/xfs_dir2_readdir.c
fs/xfs/xfs_trace.h

index 673a4b6d2e8d1e8fb7f1beb6c680dff55d99f3cd..74d769461443438b3469f22a4f9b30630f91b9f0 100644 (file)
@@ -264,6 +264,8 @@ xfs_attr_get(
        if (xfs_is_shutdown(args->dp->i_mount))
                return -EIO;
 
+       if (!args->owner)
+               args->owner = args->dp->i_ino;
        args->geo = args->dp->i_mount->m_attr_geo;
        args->whichfork = XFS_ATTR_FORK;
        args->hashval = xfs_da_hashname(args->name, args->namelen);
@@ -937,6 +939,8 @@ xfs_attr_set(
        if (error)
                return error;
 
+       if (!args->owner)
+               args->owner = args->dp->i_ino;
        args->geo = mp->m_attr_geo;
        args->whichfork = XFS_ATTR_FORK;
        args->hashval = xfs_da_hashname(args->name, args->namelen);
index ac904cc1a97bae1eae0aa0acb8a3dc00ea92a55a..e606eae8d3770dff6a79fda004e81a985cb6e2f7 100644 (file)
@@ -904,6 +904,7 @@ xfs_attr_shortform_to_leaf(
        nargs.whichfork = XFS_ATTR_FORK;
        nargs.trans = args->trans;
        nargs.op_flags = XFS_DA_OP_OKNOENT;
+       nargs.owner = args->owner;
 
        sfe = xfs_attr_sf_firstentry(sf);
        for (i = 0; i < sf->count; i++) {
@@ -1106,6 +1107,7 @@ xfs_attr3_leaf_to_shortform(
        nargs.whichfork = XFS_ATTR_FORK;
        nargs.trans = args->trans;
        nargs.op_flags = XFS_DA_OP_OKNOENT;
+       nargs.owner = args->owner;
 
        for (i = 0; i < ichdr.count; entry++, i++) {
                if (entry->flags & XFS_ATTR_INCOMPLETE)
index 656c95a22f2e6deb40128fbe1aa8c1b62b1f64d2..46bbc9f0a11732a2402ea1265466c900e1fca9e4 100644 (file)
@@ -976,6 +976,7 @@ xfs_bmap_add_attrfork_local(
                dargs.total = dargs.geo->fsbcount;
                dargs.whichfork = XFS_DATA_FORK;
                dargs.trans = tp;
+               dargs.owner = ip->i_ino;
                return xfs_dir2_sf_to_block(&dargs);
        }
 
index 706baf36e1751146ede959bd8eaf3becbf62a27d..7fb13f26edaa7bed7a57c9edfc3c4c0b68d40f5a 100644 (file)
@@ -79,6 +79,7 @@ typedef struct xfs_da_args {
        int             rmtvaluelen2;   /* remote attr value length in bytes */
        uint32_t        op_flags;       /* operation flags */
        enum xfs_dacmp  cmpresult;      /* name compare result for lookups */
+       xfs_ino_t       owner;          /* inode that owns the dir/attr data */
 } xfs_da_args_t;
 
 /*
index 4821519efad4b7e6cf8ba5eb50079773ec158f91..9da99fa20c7591cc268a504dddeab4b287cb2e53 100644 (file)
@@ -250,6 +250,7 @@ xfs_dir_init(
        args->geo = dp->i_mount->m_dir_geo;
        args->dp = dp;
        args->trans = tp;
+       args->owner = dp->i_ino;
        error = xfs_dir2_sf_create(args, pdp->i_ino);
        kfree(args);
        return error;
@@ -295,6 +296,7 @@ xfs_dir_createname(
        args->whichfork = XFS_DATA_FORK;
        args->trans = tp;
        args->op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
+       args->owner = dp->i_ino;
        if (!inum)
                args->op_flags |= XFS_DA_OP_JUSTCHECK;
 
@@ -383,6 +385,7 @@ xfs_dir_lookup(
        args->whichfork = XFS_DATA_FORK;
        args->trans = tp;
        args->op_flags = XFS_DA_OP_OKNOENT;
+       args->owner = dp->i_ino;
        if (ci_name)
                args->op_flags |= XFS_DA_OP_CILOOKUP;
 
@@ -456,6 +459,7 @@ xfs_dir_removename(
        args->total = total;
        args->whichfork = XFS_DATA_FORK;
        args->trans = tp;
+       args->owner = dp->i_ino;
 
        if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
                rval = xfs_dir2_sf_removename(args);
@@ -517,6 +521,7 @@ xfs_dir_replace(
        args->total = total;
        args->whichfork = XFS_DATA_FORK;
        args->trans = tp;
+       args->owner = dp->i_ino;
 
        if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
                rval = xfs_dir2_sf_replace(args);
index 7fa244228750a5c7cec945ef74d5fd87175f3f69..8d28e8cce5e93b0fc5b706166907ca1b239e7542 100644 (file)
@@ -429,6 +429,7 @@ xfs_exchmaps_attr_to_sf(
                .geo            = tp->t_mountp->m_attr_geo,
                .whichfork      = XFS_ATTR_FORK,
                .trans          = tp,
+               .owner          = xmi->xmi_ip2->i_ino,
        };
        struct xfs_buf          *bp;
        int                     forkoff;
@@ -459,6 +460,7 @@ xfs_exchmaps_dir_to_sf(
                .geo            = tp->t_mountp->m_dir_geo,
                .whichfork      = XFS_DATA_FORK,
                .trans          = tp,
+               .owner          = xmi->xmi_ip2->i_ino,
        };
        struct xfs_dir2_sf_hdr  sfh;
        struct xfs_buf          *bp;
index 83c7feb387147aae768af77b7e02c19e060e73ea..0c467f4f8e778057db47de727242eaae8ec3d77b 100644 (file)
@@ -169,6 +169,7 @@ xchk_xattr_listent(
                .hashval                = xfs_da_hashname(name, namelen),
                .trans                  = context->tp,
                .valuelen               = valuelen,
+               .owner                  = context->dp->i_ino,
        };
        struct xchk_xattr_buf           *ab;
        struct xchk_xattr               *sx;
index 82b150d3b8b700fabb301a34fa3e6d8e32036968..fa6385a99ac4edf8b0d2a15bdbc3758991bbbb0a 100644 (file)
@@ -494,6 +494,7 @@ xchk_da_btree(
        ds->dargs.whichfork = whichfork;
        ds->dargs.trans = sc->tp;
        ds->dargs.op_flags = XFS_DA_OP_OKNOENT;
+       ds->dargs.owner = sc->ip->i_ino;
        ds->state = xfs_da_state_alloc(&ds->dargs);
        ds->sc = sc;
        ds->private = private;
index 076a310b8eb00aa15a0034ac213ac749169c0d03..042e28547e0447ceb4633ceaae455f7fefe33bcf 100644 (file)
@@ -621,10 +621,11 @@ xchk_directory_blocks(
 {
        struct xfs_bmbt_irec    got;
        struct xfs_da_args      args = {
-               .dp             = sc ->ip,
+               .dp             = sc->ip,
                .whichfork      = XFS_DATA_FORK,
                .geo            = sc->mp->m_dir_geo,
                .trans          = sc->tp,
+               .owner          = sc->ip->i_ino,
        };
        struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, XFS_DATA_FORK);
        struct xfs_mount        *mp = sc->mp;
index dfdcb96b6c169b3cb50ba2c388034346112a5e93..fb98b7624994a34ce21c531371cbcd9080cbceb3 100644 (file)
@@ -273,6 +273,7 @@ xchk_dir_walk(
                .dp             = dp,
                .geo            = dp->i_mount->m_dir_geo,
                .trans          = sc->tp,
+               .owner          = dp->i_ino,
        };
        bool                    isblock;
        int                     error;
@@ -324,6 +325,7 @@ xchk_dir_lookup(
                .hashval        = xfs_dir2_hashname(dp->i_mount, name),
                .whichfork      = XFS_DATA_FORK,
                .op_flags       = XFS_DA_OP_OKNOENT,
+               .owner          = dp->i_ino,
        };
        bool                    isblock, isleaf;
        int                     error;
index 9b4c61e1c22e8ddfb1e4942e8e6282b6c4557d9f..d460347056945184a3e7793682a4962196394768 100644 (file)
@@ -540,6 +540,7 @@ xfs_attri_recover_work(
        args->attr_filter = attrp->alfi_attr_filter & XFS_ATTRI_FILTER_MASK;
        args->op_flags = XFS_DA_OP_RECOVERY | XFS_DA_OP_OKNOENT |
                         XFS_DA_OP_LOGGED;
+       args->owner = args->dp->i_ino;
 
        ASSERT(xfs_sb_version_haslogxattrs(&mp->m_sb));
 
index cf9296b7e06ff63f484ed18b14212646f0136ad3..4e811fa393adda9764aa864c1d4bfe55459fed62 100644 (file)
@@ -532,6 +532,7 @@ xfs_readdir(
        args.dp = dp;
        args.geo = dp->i_mount->m_dir_geo;
        args.trans = tp;
+       args.owner = dp->i_ino;
 
        if (dp->i_df.if_format == XFS_DINODE_FMT_LOCAL)
                return xfs_dir2_sf_getdents(&args, ctx);
index caef95f2c87cbfdc7cf963cddf4480410a7a567f..939baf08331b5801058ca31af6b9e7d6c9ee788e 100644 (file)
@@ -1931,6 +1931,7 @@ DECLARE_EVENT_CLASS(xfs_da_class,
                __field(xfs_dahash_t, hashval)
                __field(xfs_ino_t, inumber)
                __field(uint32_t, op_flags)
+               __field(xfs_ino_t, owner)
        ),
        TP_fast_assign(
                __entry->dev = VFS_I(args->dp)->i_sb->s_dev;
@@ -1941,9 +1942,10 @@ DECLARE_EVENT_CLASS(xfs_da_class,
                __entry->hashval = args->hashval;
                __entry->inumber = args->inumber;
                __entry->op_flags = args->op_flags;
+               __entry->owner = args->owner;
        ),
        TP_printk("dev %d:%d ino 0x%llx name %.*s namelen %d hashval 0x%x "
-                 "inumber 0x%llx op_flags %s",
+                 "inumber 0x%llx op_flags %s owner 0x%llx",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->ino,
                  __entry->namelen,
@@ -1951,7 +1953,8 @@ DECLARE_EVENT_CLASS(xfs_da_class,
                  __entry->namelen,
                  __entry->hashval,
                  __entry->inumber,
-                 __print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS))
+                 __print_flags(__entry->op_flags, "|", XFS_DA_OP_FLAGS),
+                 __entry->owner)
 )
 
 #define DEFINE_DIR2_EVENT(name) \