[PATCH 1/9] xfs: add an explicit owner field to xfs_da_args

Darrick J. Wong
2023-12-31T22:32:32Z

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]*)'

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
db/attrset.c | 2 ++
db/namei.c | 1 +
libxfs/xfs_attr_leaf.c | 2 ++
libxfs/xfs_bmap.c | 1 +
libxfs/xfs_da_btree.h | 1 +
libxfs/xfs_dir2.c | 5 +++++
libxfs/xfs_swapext.c | 2 ++
repair/phase6.c | 3 +++
8 files changed, 17 insertions(+)

diff --git a/db/attrset.c b/db/attrset.c
index 0d8d70a8429..2b6cdb5f5c3 100644
--- a/db/attrset.c
+++ b/db/attrset.c
@@ -161,6 +161,7 @@ attr_set_f(
(unsigned long long)iocur_top->ino);
goto out;
}
+ args.owner = iocur_top->ino;

if (libxfs_attr_set(&args)) {
dbprintf(_("failed to set attr %s on inode %llu\n"),
@@ -247,6 +248,7 @@ attr_remove_f(
(unsigned long long)iocur_top->ino);
goto out;
}
+ args.owner = iocur_top->ino;

if (libxfs_attr_set(&args)) {
dbprintf(_("failed to remove attr %s from inode %llu\n"),
diff --git a/db/namei.c b/db/namei.c
index 063721ca98f..eb09288b490 100644
--- a/db/namei.c
+++ b/db/namei.c
@@ -448,6 +448,7 @@ listdir(
struct xfs_da_args args = {
.dp = dp,
.geo = dp->i_mount->m_dir_geo,
+ .owner = dp->i_ino,
};
int error;
bool isblock;
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index aa7aad36864..e3e9c265fab 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -972,6 +972,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 = &sf->list[0];
for (i = 0; i < sf->hdr.count; i++) {
@@ -1175,6 +1176,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)
diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c
index 54db35bc398..296e7d85f63 100644
--- a/libxfs/xfs_bmap.c
+++ b/libxfs/xfs_bmap.c
@@ -952,6 +952,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);
}

diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h
index 706baf36e17..7fb13f26eda 100644
--- a/libxfs/xfs_da_btree.h
+++ b/libxfs/xfs_da_btree.h
@@ -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;

/*
diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index e503bf8f92f..79b6ec893fd 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -249,6 +249,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);
kmem_free(args);
return error;
@@ -294,6 +295,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;

@@ -388,6 +390,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;

@@ -461,6 +464,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);
@@ -522,6 +526,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);
diff --git a/libxfs/xfs_swapext.c b/libxfs/xfs_swapext.c
index 92d2f8fa133..5c96ad8a203 100644
--- a/libxfs/xfs_swapext.c
+++ b/libxfs/xfs_swapext.c
@@ -524,6 +524,7 @@ xfs_swapext_attr_to_sf(
.geo = tp->t_mountp->m_attr_geo,
.whichfork = XFS_ATTR_FORK,
.trans = tp,
+ .owner = sxi->sxi_ip2->i_ino,
};
struct xfs_buf *bp;
int forkoff;
@@ -554,6 +555,7 @@ xfs_swapext_dir_to_sf(
.geo = tp->t_mountp->m_dir_geo,
.whichfork = XFS_DATA_FORK,
.trans = tp,
+ .owner = sxi->sxi_ip2->i_ino,
};
struct xfs_dir2_sf_hdr sfh;
struct xfs_buf *bp;
diff --git a/repair/phase6.c b/repair/phase6.c
index c681a69017d..ac037cf80ad 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1393,6 +1393,7 @@ dir2_kill_block(
args.trans = tp;
args.whichfork = XFS_DATA_FORK;
args.geo = mp->m_dir_geo;
+ args.owner = ip->i_ino;
if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk)
error = -libxfs_da_shrink_inode(&args, da_bno, bp);
else
@@ -1496,6 +1497,7 @@ longform_dir2_entry_check_data(
struct xfs_da_args da = {
.dp = ip,
.geo = mp->m_dir_geo,
+ .owner = ip->i_ino,
};

@@ -2284,6 +2286,7 @@ longform_dir2_entry_check(
/* is this a block, leaf, or node directory? */
args.dp = ip;
args.geo = mp->m_dir_geo;
+ args.owner = ip->i_ino;
libxfs_dir2_isblock(&args, &isblock);
libxfs_dir2_isleaf(&args, &isleaf);