diff mbox series

[10/14] xfs: introduce XFS_ATTRUPDATE_FLAGS operation

Message ID 20241229133836.1194272-11-aalbersh@kernel.org (mailing list archive)
State New
Headers show
Series Direct mapped extended attribute data | expand

Commit Message

Andrey Albershteyn Dec. 29, 2024, 1:38 p.m. UTC
The extended attributes mapped through page cache need a way to
reset XFS_ATTR_INCOMPLETE flag and set data CRC when data IO is
complete. Introduce this new operation which now applies only to
leaf attributes.

Signed-off-by: Andrey Albershteyn <aalbersh@kernel.org>
---
 fs/xfs/libxfs/xfs_attr.c       | 19 ++++++++++++++++++-
 fs/xfs/libxfs/xfs_attr.h       |  3 +++
 fs/xfs/libxfs/xfs_log_format.h |  1 +
 fs/xfs/xfs_attr_item.c         |  6 ++++++
 fs/xfs/xfs_attr_item.h         |  1 +
 fs/xfs/xfs_stats.h             |  1 +
 6 files changed, 30 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index 5060c266f776..55b18ec8bc10 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -855,6 +855,13 @@  xfs_attr_set_iter(
 			attr->xattri_dela_state++;
 		break;
 
+	case XFS_DAS_LEAF_FLAGS_UPDATE:
+		error = xfs_attr3_leaf_setcrc(args);
+		if (error)
+			return error;
+		attr->xattri_dela_state = XFS_DAS_DONE;
+		break;
+
 	case XFS_DAS_LEAF_SET_RMT:
 	case XFS_DAS_NODE_SET_RMT:
 		error = xfs_attr_rmtval_find_space(attr);
@@ -1093,6 +1100,11 @@  xfs_attr_set(
 		tres = M_RES(mp)->tr_attrrm;
 		total = XFS_ATTRRM_SPACE_RES(mp);
 		break;
+	case XFS_ATTRUPDATE_FLAGS:
+		XFS_STATS_INC(mp, xs_attr_flags);
+		tres = M_RES(mp)->tr_attrrm;
+		total = XFS_ATTRRM_SPACE_RES(mp);
+		break;
 	}
 
 	/*
@@ -1119,6 +1131,11 @@  xfs_attr_set(
 			break;
 		}
 
+		if (op == XFS_ATTRUPDATE_FLAGS) {
+			xfs_attr_defer_add(args, XFS_ATTR_DEFER_FLAGS);
+			break;
+		}
+
 		/* Pure create fails if the attr already exists */
 		if (op == XFS_ATTRUPDATE_CREATE)
 			goto out_trans_cancel;
@@ -1126,7 +1143,7 @@  xfs_attr_set(
 		break;
 	case -ENOATTR:
 		/* Can't remove what isn't there. */
-		if (op == XFS_ATTRUPDATE_REMOVE)
+		if (op == XFS_ATTRUPDATE_REMOVE || op == XFS_ATTRUPDATE_FLAGS)
 			goto out_trans_cancel;
 
 		/* Pure replace fails if no existing attr to replace. */
diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
index 0e51d0723f9a..b851e2e4b63c 100644
--- a/fs/xfs/libxfs/xfs_attr.h
+++ b/fs/xfs/libxfs/xfs_attr.h
@@ -448,6 +448,7 @@  enum xfs_delattr_state {
 
 	XFS_DAS_LEAF_ADD,		/* Initial leaf add state */
 	XFS_DAS_LEAF_REMOVE,		/* Initial leaf replace/remove state */
+	XFS_DAS_LEAF_FLAGS_UPDATE,	/* Update leaf XFS_ATTR_* flags and CRC */
 
 	XFS_DAS_NODE_ADD,		/* Initial node add state */
 	XFS_DAS_NODE_REMOVE,		/* Initial node replace/remove state */
@@ -477,6 +478,7 @@  enum xfs_delattr_state {
 	{ XFS_DAS_SF_REMOVE,		"XFS_DAS_SF_REMOVE" }, \
 	{ XFS_DAS_LEAF_ADD,		"XFS_DAS_LEAF_ADD" }, \
 	{ XFS_DAS_LEAF_REMOVE,		"XFS_DAS_LEAF_REMOVE" }, \
+	{ XFS_DAS_LEAF_FLAGS_UPDATE,	"XFS_DAS_LEAF_FLAGS_UPDATE" }, \
 	{ XFS_DAS_NODE_ADD,		"XFS_DAS_NODE_ADD" }, \
 	{ XFS_DAS_NODE_REMOVE,		"XFS_DAS_NODE_REMOVE" }, \
 	{ XFS_DAS_LEAF_SET_RMT,		"XFS_DAS_LEAF_SET_RMT" }, \
@@ -556,6 +558,7 @@  enum xfs_attr_update {
 	XFS_ATTRUPDATE_UPSERT,	/* set value, replace any existing attr */
 	XFS_ATTRUPDATE_CREATE,	/* set value, fail if attr already exists */
 	XFS_ATTRUPDATE_REPLACE,	/* set value, fail if attr does not exist */
+	XFS_ATTRUPDATE_FLAGS,	/* update attribute flags and metadata */
 };
 
 int xfs_attr_set(struct xfs_da_args *args, enum xfs_attr_update op, bool rsvd);
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index 15dec19b6c32..9f1b02a599d2 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/libxfs/xfs_log_format.h
@@ -1035,6 +1035,7 @@  struct xfs_icreate_log {
 #define XFS_ATTRI_OP_FLAGS_PPTR_SET	4	/* Set parent pointer */
 #define XFS_ATTRI_OP_FLAGS_PPTR_REMOVE	5	/* Remove parent pointer */
 #define XFS_ATTRI_OP_FLAGS_PPTR_REPLACE	6	/* Replace parent pointer */
+#define XFS_ATTRI_OP_FLAGS_FLAGS_UPDATE	7	/* Update attribute flags */
 #define XFS_ATTRI_OP_FLAGS_TYPE_MASK	0xFF	/* Flags type mask */
 
 /*
diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c
index f683b7a9323f..f392c95905b5 100644
--- a/fs/xfs/xfs_attr_item.c
+++ b/fs/xfs/xfs_attr_item.c
@@ -908,6 +908,9 @@  xfs_attr_defer_add(
 		else
 			log_op = XFS_ATTRI_OP_FLAGS_REMOVE;
 		break;
+	case XFS_ATTR_DEFER_FLAGS:
+		log_op = XFS_ATTRI_OP_FLAGS_FLAGS_UPDATE;
+		break;
 	default:
 		ASSERT(0);
 		break;
@@ -931,6 +934,9 @@  xfs_attr_defer_add(
 	case XFS_ATTRI_OP_FLAGS_REMOVE:
 		new->xattri_dela_state = xfs_attr_init_remove_state(args);
 		break;
+	case XFS_ATTRI_OP_FLAGS_FLAGS_UPDATE:
+		new->xattri_dela_state = XFS_DAS_LEAF_FLAGS_UPDATE;
+		break;
 	}
 
 	xfs_defer_add(args->trans, &new->xattri_list, &xfs_attr_defer_type);
diff --git a/fs/xfs/xfs_attr_item.h b/fs/xfs/xfs_attr_item.h
index e74128cbb722..f6f169631eb7 100644
--- a/fs/xfs/xfs_attr_item.h
+++ b/fs/xfs/xfs_attr_item.h
@@ -57,6 +57,7 @@  enum xfs_attr_defer_op {
 	XFS_ATTR_DEFER_SET,
 	XFS_ATTR_DEFER_REMOVE,
 	XFS_ATTR_DEFER_REPLACE,
+	XFS_ATTR_DEFER_FLAGS,
 };
 
 void xfs_attr_defer_add(struct xfs_da_args *args, enum xfs_attr_defer_op op);
diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h
index a61fb56ed2e6..007c22e2cad2 100644
--- a/fs/xfs/xfs_stats.h
+++ b/fs/xfs/xfs_stats.h
@@ -96,6 +96,7 @@  struct __xfsstats {
 	uint32_t		xs_attr_get;
 	uint32_t		xs_attr_set;
 	uint32_t		xs_attr_remove;
+	uint32_t		xs_attr_flags;
 	uint32_t		xs_attr_list;
 	uint32_t		xs_iflush_count;
 	uint32_t		xs_icluster_flushcnt;