Skip to content

Commit b11fa61

Browse files
Dave Chinnerdchinner
authored andcommitted
xfs: clean up final attr removal in xfs_attr_set_iter
Clean up the final leaf/node states in xfs_attr_set_iter() to further simplify the high level state machine and to set the completion state correctly. As we are adding a separate state for node format removal, we need to ensure that node formats are collapsed back to shortform or empty correctly. Signed-off-by: Dave Chinner <[email protected]> Reviewed-by: Allison Henderson<[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Signed-off-by: Dave Chinner <[email protected]>
1 parent 2e7ef21 commit b11fa61

File tree

3 files changed

+94
-72
lines changed

3 files changed

+94
-72
lines changed

fs/xfs/libxfs/xfs_attr.c

Lines changed: 85 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ STATIC int xfs_attr_node_get(xfs_da_args_t *args);
6060
STATIC void xfs_attr_restore_rmt_blk(struct xfs_da_args *args);
6161
static int xfs_attr_node_try_addname(struct xfs_attr_item *attr);
6262
STATIC int xfs_attr_node_addname_find_attr(struct xfs_attr_item *attr);
63-
STATIC int xfs_attr_node_addname_clear_incomplete(struct xfs_attr_item *attr);
63+
STATIC int xfs_attr_node_remove_attr(struct xfs_attr_item *attr);
6464
STATIC int xfs_attr_node_hasname(xfs_da_args_t *args,
6565
struct xfs_da_state **state);
6666
STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
@@ -443,6 +443,77 @@ xfs_attr_rmtval_alloc(
443443
return error;
444444
}
445445

446+
/*
447+
* Remove the original attr we have just replaced. This is dependent on the
448+
* original lookup and insert placing the old attr in args->blkno/args->index
449+
* and the new attr in args->blkno2/args->index2.
450+
*/
451+
static int
452+
xfs_attr_leaf_remove_attr(
453+
struct xfs_attr_item *attr)
454+
{
455+
struct xfs_da_args *args = attr->xattri_da_args;
456+
struct xfs_inode *dp = args->dp;
457+
struct xfs_buf *bp = NULL;
458+
int forkoff;
459+
int error;
460+
461+
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
462+
&bp);
463+
if (error)
464+
return error;
465+
466+
xfs_attr3_leaf_remove(bp, args);
467+
468+
forkoff = xfs_attr_shortform_allfit(bp, dp);
469+
if (forkoff)
470+
error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
471+
/* bp is gone due to xfs_da_shrink_inode */
472+
473+
return error;
474+
}
475+
476+
/*
477+
* Shrink an attribute from leaf to shortform. Used by the node format remove
478+
* path when the node format collapses to a single block and so we have to check
479+
* if it can be collapsed further.
480+
*/
481+
static int
482+
xfs_attr_leaf_shrink(
483+
struct xfs_da_args *args,
484+
struct xfs_da_state *state)
485+
{
486+
struct xfs_inode *dp = args->dp;
487+
int error, forkoff;
488+
struct xfs_buf *bp;
489+
490+
if (!xfs_attr_is_leaf(dp))
491+
return 0;
492+
493+
/*
494+
* Have to get rid of the copy of this dabuf in the state.
495+
*/
496+
if (state) {
497+
ASSERT(state->path.active == 1);
498+
ASSERT(state->path.blk[0].bp);
499+
state->path.blk[0].bp = NULL;
500+
}
501+
502+
error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
503+
if (error)
504+
return error;
505+
506+
forkoff = xfs_attr_shortform_allfit(bp, dp);
507+
if (forkoff) {
508+
error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
509+
/* bp is gone due to xfs_da_shrink_inode */
510+
} else {
511+
xfs_trans_brelse(args->trans, bp);
512+
}
513+
514+
return error;
515+
}
516+
446517
/*
447518
* Set the attribute specified in @args.
448519
* This routine is meant to function as a delayed operation, and may return
@@ -455,9 +526,7 @@ xfs_attr_set_iter(
455526
struct xfs_attr_item *attr)
456527
{
457528
struct xfs_da_args *args = attr->xattri_da_args;
458-
struct xfs_inode *dp = args->dp;
459-
struct xfs_buf *bp = NULL;
460-
int forkoff, error = 0;
529+
int error = 0;
461530

462531
/* State machine switch */
463532
next_state:
@@ -548,32 +617,16 @@ xfs_attr_set_iter(
548617
attr->xattri_dela_state++;
549618
break;
550619

551-
case XFS_DAS_RD_LEAF:
552-
/*
553-
* This is the last step for leaf format. Read the block with
554-
* the old attr, remove the old attr, check for shortform
555-
* conversion and return.
556-
*/
557-
error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno,
558-
&bp);
559-
if (error)
560-
return error;
561-
562-
xfs_attr3_leaf_remove(bp, args);
563-
564-
forkoff = xfs_attr_shortform_allfit(bp, dp);
565-
if (forkoff)
566-
error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
567-
/* bp is gone due to xfs_da_shrink_inode */
568-
569-
return error;
620+
case XFS_DAS_LEAF_REMOVE_ATTR:
621+
error = xfs_attr_leaf_remove_attr(attr);
622+
attr->xattri_dela_state = XFS_DAS_DONE;
623+
break;
570624

571-
case XFS_DAS_CLR_FLAG:
572-
/*
573-
* The last state for node format. Look up the old attr and
574-
* remove it.
575-
*/
576-
error = xfs_attr_node_addname_clear_incomplete(attr);
625+
case XFS_DAS_NODE_REMOVE_ATTR:
626+
error = xfs_attr_node_remove_attr(attr);
627+
if (!error)
628+
error = xfs_attr_leaf_shrink(args, NULL);
629+
attr->xattri_dela_state = XFS_DAS_DONE;
577630
break;
578631
default:
579632
ASSERT(0);
@@ -1268,8 +1321,8 @@ xfs_attr_node_try_addname(
12681321
}
12691322

12701323

1271-
STATIC int
1272-
xfs_attr_node_addname_clear_incomplete(
1324+
static int
1325+
xfs_attr_node_remove_attr(
12731326
struct xfs_attr_item *attr)
12741327
{
12751328
struct xfs_da_args *args = attr->xattri_da_args;
@@ -1310,38 +1363,6 @@ xfs_attr_node_addname_clear_incomplete(
13101363
return retval;
13111364
}
13121365

1313-
/*
1314-
* Shrink an attribute from leaf to shortform
1315-
*/
1316-
STATIC int
1317-
xfs_attr_node_shrink(
1318-
struct xfs_da_args *args,
1319-
struct xfs_da_state *state)
1320-
{
1321-
struct xfs_inode *dp = args->dp;
1322-
int error, forkoff;
1323-
struct xfs_buf *bp;
1324-
1325-
/*
1326-
* Have to get rid of the copy of this dabuf in the state.
1327-
*/
1328-
ASSERT(state->path.active == 1);
1329-
ASSERT(state->path.blk[0].bp);
1330-
state->path.blk[0].bp = NULL;
1331-
1332-
error = xfs_attr3_leaf_read(args->trans, args->dp, 0, &bp);
1333-
if (error)
1334-
return error;
1335-
1336-
forkoff = xfs_attr_shortform_allfit(bp, dp);
1337-
if (forkoff) {
1338-
error = xfs_attr3_leaf_to_shortform(bp, args, forkoff);
1339-
/* bp is gone due to xfs_da_shrink_inode */
1340-
} else
1341-
xfs_trans_brelse(args->trans, bp);
1342-
1343-
return error;
1344-
}
13451366

13461367
/*
13471368
* Mark an attribute entry INCOMPLETE and save pointers to the relevant buffers
@@ -1550,7 +1571,7 @@ xfs_attr_remove_iter(
15501571
* transaction.
15511572
*/
15521573
if (xfs_attr_is_leaf(dp))
1553-
error = xfs_attr_node_shrink(args, state);
1574+
error = xfs_attr_leaf_shrink(args, state);
15541575
ASSERT(error != -EAGAIN);
15551576
break;
15561577
default:

fs/xfs/libxfs/xfs_attr.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -451,21 +451,21 @@ enum xfs_delattr_state {
451451
XFS_DAS_RM_NAME, /* Remove attr name */
452452
XFS_DAS_RM_SHRINK, /* We are shrinking the tree */
453453

454-
/* Leaf state set sequence */
454+
/* Leaf state set/replace sequence */
455455
XFS_DAS_LEAF_SET_RMT, /* set a remote xattr from a leaf */
456456
XFS_DAS_LEAF_ALLOC_RMT, /* We are allocating remote blocks */
457457
XFS_DAS_LEAF_REPLACE, /* Perform replace ops on a leaf */
458458
XFS_DAS_LEAF_REMOVE_OLD, /* Start removing old attr from leaf */
459459
XFS_DAS_LEAF_REMOVE_RMT, /* A rename is removing remote blocks */
460-
XFS_DAS_RD_LEAF, /* Read in the new leaf */
460+
XFS_DAS_LEAF_REMOVE_ATTR, /* Remove the old attr from a leaf */
461461

462-
/* Node state set sequence, must match leaf state above */
462+
/* Node state set/replace sequence, must match leaf state above */
463463
XFS_DAS_NODE_SET_RMT, /* set a remote xattr from a node */
464464
XFS_DAS_NODE_ALLOC_RMT, /* We are allocating remote blocks */
465465
XFS_DAS_NODE_REPLACE, /* Perform replace ops on a node */
466466
XFS_DAS_NODE_REMOVE_OLD, /* Start removing old attr from node */
467467
XFS_DAS_NODE_REMOVE_RMT, /* A rename is removing remote blocks */
468-
XFS_DAS_CLR_FLAG, /* Clear incomplete flag */
468+
XFS_DAS_NODE_REMOVE_ATTR, /* Remove the old attr from a node */
469469

470470
XFS_DAS_DONE, /* finished operation */
471471
};
@@ -483,13 +483,13 @@ enum xfs_delattr_state {
483483
{ XFS_DAS_LEAF_REPLACE, "XFS_DAS_LEAF_REPLACE" }, \
484484
{ XFS_DAS_LEAF_REMOVE_OLD, "XFS_DAS_LEAF_REMOVE_OLD" }, \
485485
{ XFS_DAS_LEAF_REMOVE_RMT, "XFS_DAS_LEAF_REMOVE_RMT" }, \
486-
{ XFS_DAS_RD_LEAF, "XFS_DAS_RD_LEAF" }, \
486+
{ XFS_DAS_LEAF_REMOVE_ATTR, "XFS_DAS_LEAF_REMOVE_ATTR" }, \
487487
{ XFS_DAS_NODE_SET_RMT, "XFS_DAS_NODE_SET_RMT" }, \
488488
{ XFS_DAS_NODE_ALLOC_RMT, "XFS_DAS_NODE_ALLOC_RMT" }, \
489489
{ XFS_DAS_NODE_REPLACE, "XFS_DAS_NODE_REPLACE" }, \
490490
{ XFS_DAS_NODE_REMOVE_OLD, "XFS_DAS_NODE_REMOVE_OLD" }, \
491491
{ XFS_DAS_NODE_REMOVE_RMT, "XFS_DAS_NODE_REMOVE_RMT" }, \
492-
{ XFS_DAS_CLR_FLAG, "XFS_DAS_CLR_FLAG" }, \
492+
{ XFS_DAS_NODE_REMOVE_ATTR, "XFS_DAS_NODE_REMOVE_ATTR" }, \
493493
{ XFS_DAS_DONE, "XFS_DAS_DONE" }
494494

495495
/*

fs/xfs/xfs_trace.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4141,13 +4141,14 @@ TRACE_DEFINE_ENUM(XFS_DAS_LEAF_ALLOC_RMT);
41414141
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_REPLACE);
41424142
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_REMOVE_OLD);
41434143
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_REMOVE_RMT);
4144-
TRACE_DEFINE_ENUM(XFS_DAS_RD_LEAF);
4144+
TRACE_DEFINE_ENUM(XFS_DAS_LEAF_REMOVE_ATTR);
41454145
TRACE_DEFINE_ENUM(XFS_DAS_NODE_SET_RMT);
41464146
TRACE_DEFINE_ENUM(XFS_DAS_NODE_ALLOC_RMT);
41474147
TRACE_DEFINE_ENUM(XFS_DAS_NODE_REPLACE);
41484148
TRACE_DEFINE_ENUM(XFS_DAS_NODE_REMOVE_OLD);
41494149
TRACE_DEFINE_ENUM(XFS_DAS_NODE_REMOVE_RMT);
4150-
TRACE_DEFINE_ENUM(XFS_DAS_CLR_FLAG);
4150+
TRACE_DEFINE_ENUM(XFS_DAS_NODE_REMOVE_ATTR);
4151+
TRACE_DEFINE_ENUM(XFS_DAS_DONE);
41514152

41524153
DECLARE_EVENT_CLASS(xfs_das_state_class,
41534154
TP_PROTO(int das, struct xfs_inode *ip),

0 commit comments

Comments
 (0)