This patch adds a new functions to check for the existence of
an attribute. Subroutines are also added to handle the cases
of leaf blocks, nodes or shortform. We will need this later
for delayed attributes since delayed operations cannot return
error codes.
Signed-off-by: Allison Henderson <allison.henderson@xxxxxxxxxx>
---
fs/xfs/libxfs/xfs_attr.c | 78
+++++++++++++++++++++++++++++++++++++++++++
fs/xfs/libxfs/xfs_attr.h | 1 +
fs/xfs/libxfs/xfs_attr_leaf.c | 33 ++++++++++++++++++
fs/xfs/libxfs/xfs_attr_leaf.h | 1 +
4 files changed, 113 insertions(+)
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index c3477fa7..0042708 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -53,6 +53,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t
*args);
STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args, bool roll_trans);
STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args, bool
roll_trans);
+STATIC int xfs_leaf_has_attr(xfs_da_args_t *args);
/*
* Internal routines when attribute list is more than one block.
@@ -60,6 +61,7 @@ STATIC int xfs_attr_leaf_removename(xfs_da_args_t
*args, bool roll_trans);
STATIC int xfs_attr_node_get(xfs_da_args_t *args);
STATIC int xfs_attr_node_addname(xfs_da_args_t *args, bool roll_trans);
STATIC int xfs_attr_node_removename(xfs_da_args_t *args, bool
roll_trans);
+STATIC int xfs_attr_node_hasname(xfs_da_args_t *args);
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
@@ -301,6 +303,29 @@ xfs_attr_set_args(
}
/*
+ * Return successful if attr is found, or ENOATTR if not
+ */
+int
+xfs_has_attr(
+ struct xfs_da_args *args)
+{
+ struct xfs_inode *dp = args->dp;
+ int error;
+
+ if (!xfs_inode_hasattr(dp))
+ error = -ENOATTR;
+ else if (dp->i_d.di_aformat == XFS_DINODE_FMT_LOCAL) {
+ ASSERT(dp->i_afp->if_flags & XFS_IFINLINE);
+ error = xfs_shortform_has_attr(args);
+ } else if (xfs_bmap_one_block(dp, XFS_ATTR_FORK))
+ error = xfs_leaf_has_attr(args);
+ else
+ error = xfs_attr_node_hasname(args);
+
+ return error;
+}
+
+/*
* Remove the attribute specified in @args.
*/
int
@@ -836,6 +861,29 @@ xfs_attr_leaf_addname(
}
/*
+ * Return successful if attr is found, or ENOATTR if not
+ */
+STATIC int
+xfs_leaf_has_attr(
+ struct xfs_da_args *args)
+{
+ struct xfs_buf *bp;
+ int error = 0;
+
+ args->blkno = 0;
+ error = xfs_attr3_leaf_read(args->trans, args->dp,
+ args->blkno, -1, &bp);
+ if (error)
+ return error;
+
+ error = xfs_attr3_leaf_lookup_int(bp, args);
+ error = (error == -ENOATTR) ? -ENOATTR : 0;
+ xfs_trans_brelse(args->trans, bp);
+
+ return error;
+}
+
+/*
* Remove a name from the leaf attribute list structure
*
* This leaf block cannot have a "remote" value, we only call this
routine
@@ -1166,6 +1214,36 @@ xfs_attr_node_addname(
}
/*
+ * Return successful if attr is found, or ENOATTR if not
+ */
+STATIC int
+xfs_attr_node_hasname(
+ struct xfs_da_args *args)
+{
+ struct xfs_da_state *state;
+ struct xfs_inode *dp;
+ int retval, error;
+
+ /*
+ * Tie a string around our finger to remind us where we are.
+ */
+ dp = args->dp;
+ state = xfs_da_state_alloc();