@@ -926,6 +926,7 @@ xfs_attr_set(
struct xfs_mount *mp = dp->i_mount;
struct xfs_trans_res tres;
bool rsvd = (args->attr_filter & XFS_ATTR_ROOT);
+ bool is_remove = args->op_flags & XFS_DA_OP_REMOVE;
int error, local;
int rmt_blks = 0;
unsigned int total;
@@ -950,7 +951,7 @@ xfs_attr_set(
args->op_flags = XFS_DA_OP_OKNOENT |
(args->op_flags & XFS_DA_OP_LOGGED);
- if (args->value) {
+ if (!is_remove) {
XFS_STATS_INC(mp, xs_attr_set);
args->total = xfs_attr_calc_size(args, &local);
@@ -984,7 +985,7 @@ xfs_attr_set(
if (error)
return error;
- if (args->value || xfs_inode_hasattr(dp)) {
+ if (!is_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)
@@ -997,8 +998,7 @@ xfs_attr_set(
error = xfs_attr_lookup(args);
switch (error) {
case -EEXIST:
- if (!args->value) {
- /* if no value, we are performing a remove operation */
+ if (is_remove) {
xfs_attr_defer_add(args, XFS_ATTRI_OP_FLAGS_REMOVE);
break;
}
@@ -1010,7 +1010,7 @@ xfs_attr_set(
break;
case -ENOATTR:
/* Can't remove what isn't there. */
- if (!args->value)
+ if (is_remove)
goto out_trans_cancel;
/* Pure replace fails if no existing attr to replace. */
@@ -122,6 +122,11 @@ xfs_attr_change(
use_logging = true;
}
+ if (args->value)
+ args->op_flags &= ~XFS_DA_OP_REMOVE;
+ else
+ args->op_flags |= XFS_DA_OP_REMOVE;
+
error = xfs_attr_set(args);
if (use_logging)