@@ -959,9 +959,13 @@ xfs_attr_defer_remove(
{
struct xfs_attr_intent *new;
+ int op_flag = XFS_ATTRI_OP_FLAGS_REMOVE;
int error;
- error = xfs_attr_intent_init(args, XFS_ATTRI_OP_FLAGS_REMOVE, &new);
+ if (args->op_flags & XFS_DA_OP_VLOOKUP)
+ op_flag = XFS_ATTRI_OP_FLAGS_NVREMOVE;
+
+ error = xfs_attr_intent_init(args, op_flag, &new);
if (error)
return error;
@@ -959,6 +959,7 @@ struct xfs_icreate_log {
#define XFS_ATTRI_OP_FLAGS_REMOVE 2 /* Remove the attribute */
#define XFS_ATTRI_OP_FLAGS_REPLACE 3 /* Replace the attribute */
#define XFS_ATTRI_OP_FLAGS_NVREPLACE 4 /* Replace attr name and val */
+#define XFS_ATTRI_OP_FLAGS_NVREMOVE 5 /* Remove attr w/ vlookup */
#define XFS_ATTRI_OP_FLAGS_TYPE_MASK 0xFF /* Flags type mask */
/*
@@ -549,6 +549,7 @@ xfs_attri_validate(
case XFS_ATTRI_OP_FLAGS_REPLACE:
case XFS_ATTRI_OP_FLAGS_REMOVE:
case XFS_ATTRI_OP_FLAGS_NVREPLACE:
+ case XFS_ATTRI_OP_FLAGS_NVREMOVE:
break;
default:
return false;
@@ -647,6 +648,9 @@ xfs_attri_item_recover(
else
attr->xattri_dela_state = xfs_attr_init_add_state(args);
break;
+ case XFS_ATTRI_OP_FLAGS_NVREMOVE:
+ args->op_flags |= XFS_DA_OP_VLOOKUP;
+ fallthrough;
case XFS_ATTRI_OP_FLAGS_REMOVE:
if (!xfs_inode_hasattr(args->dp))
goto out;
@@ -771,6 +775,14 @@ xlog_recover_attri_commit_pass2(
op = xfs_attr_log_item_op(attri_formatp);
switch (op) {
+ case XFS_ATTRI_OP_FLAGS_NVREMOVE:
+ /* Log item, attr name, optional attr value */
+ if (item->ri_total != 3 && item->ri_total != 2) {
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+ attri_formatp, len);
+ return -EFSCORRUPTED;
+ }
+ break;
case XFS_ATTRI_OP_FLAGS_SET:
case XFS_ATTRI_OP_FLAGS_REPLACE:
/* Log item, attr name, attr value */
@@ -874,12 +886,16 @@ xlog_recover_attri_commit_pass2(
return -EFSCORRUPTED;
}
fallthrough;
+ case XFS_ATTRI_OP_FLAGS_NVREMOVE:
case XFS_ATTRI_OP_FLAGS_SET:
case XFS_ATTRI_OP_FLAGS_REPLACE:
/*
* Regular xattr set/remove/replace operations require a name
* and do not take a newname. Values are optional for set and
* replace.
+ *
+ * Name-value remove operations must have a name, do not
+ * take a newname, and can take a value.
*/
if (attr_name == NULL || attri_formatp->alfi_name_len == 0) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,