From: Darrick J. Wong Date: Mon, 29 Jul 2024 23:22:43 +0000 (-0700) Subject: xfs: make attr removal an explicit operation X-Git-Tag: v6.10.0~24^2~71 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f07219cfee0a30c8ba024e2a296c083fc357dbb;p=thirdparty%2Fxfsprogs-dev.git xfs: make attr removal an explicit operation Source kernel commit: c27411d4c640037d70e2fa5751616e175e52ca5e Parent pointers match attrs on name+value, unlike everything else which matches on only the name. Therefore, we cannot keep using the heuristic that !value means remove. Make this an explicit operation code. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- diff --git a/db/attrset.c b/db/attrset.c index 736482fe..a59d5473 100644 --- a/db/attrset.c +++ b/db/attrset.c @@ -69,7 +69,7 @@ attr_set_f( { struct xfs_da_args args = { }; char *sp; - enum xfs_attr_update op = XFS_ATTRUPDATE_UPSERTR; + enum xfs_attr_update op = XFS_ATTRUPDATE_UPSERT; int c; if (cur_typ == NULL) { @@ -247,7 +247,7 @@ attr_remove_f( goto out; } - if (libxfs_attr_set(&args, XFS_ATTRUPDATE_UPSERTR)) { + if (libxfs_attr_set(&args, XFS_ATTRUPDATE_REMOVE)) { dbprintf(_("failed to remove attr %s from inode %llu\n"), (unsigned char *)args.name, (unsigned long long)iocur_top->ino); diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 9a678762..5249f9be 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -914,10 +914,6 @@ xfs_attr_defer_add( trace_xfs_attr_defer_add(new->xattri_dela_state, args->dp); } -/* - * Note: If args->value is NULL the attribute will be removed, just like the - * Linux ->setattr API. - */ int xfs_attr_set( struct xfs_da_args *args, @@ -953,7 +949,10 @@ xfs_attr_set( args->op_flags = XFS_DA_OP_OKNOENT | (args->op_flags & XFS_DA_OP_LOGGED); - if (args->value) { + switch (op) { + case XFS_ATTRUPDATE_UPSERT: + case XFS_ATTRUPDATE_CREATE: + case XFS_ATTRUPDATE_REPLACE: XFS_STATS_INC(mp, xs_attr_set); args->total = xfs_attr_calc_size(args, &local); @@ -973,9 +972,11 @@ xfs_attr_set( if (!local) rmt_blks = xfs_attr3_rmt_blocks(mp, args->valuelen); - } else { + break; + case XFS_ATTRUPDATE_REMOVE: XFS_STATS_INC(mp, xs_attr_remove); rmt_blks = xfs_attr3_rmt_blocks(mp, XFS_XATTR_SIZE_MAX); + break; } /* @@ -987,7 +988,7 @@ xfs_attr_set( if (error) return error; - if (args->value || xfs_inode_hasattr(dp)) { + if (op != XFS_ATTRUPDATE_REMOVE || xfs_inode_hasattr(dp)) { error = xfs_iext_count_may_overflow(dp, XFS_ATTR_FORK, XFS_IEXT_ATTR_MANIP_CNT(rmt_blks)); if (error == -EFBIG) @@ -1000,7 +1001,7 @@ xfs_attr_set( error = xfs_attr_lookup(args); switch (error) { case -EEXIST: - if (!args->value) { + if (op == XFS_ATTRUPDATE_REMOVE) { /* if no value, we are performing a remove operation */ xfs_attr_defer_add(args, XFS_ATTRI_OP_FLAGS_REMOVE); break; @@ -1013,7 +1014,7 @@ xfs_attr_set( break; case -ENOATTR: /* Can't remove what isn't there. */ - if (!args->value) + if (op == XFS_ATTRUPDATE_REMOVE) goto out_trans_cancel; /* Pure replace fails if no existing attr to replace. */ diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h index 228360f7..c8005f52 100644 --- a/libxfs/xfs_attr.h +++ b/libxfs/xfs_attr.h @@ -546,7 +546,8 @@ int xfs_attr_get_ilocked(struct xfs_da_args *args); int xfs_attr_get(struct xfs_da_args *args); enum xfs_attr_update { - XFS_ATTRUPDATE_UPSERTR, /* set/remove value, replace any existing attr */ + XFS_ATTRUPDATE_REMOVE, /* remove attr */ + 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 */ };