|
68 | 68 | xfs_inode_hasattr( |
69 | 69 | struct xfs_inode *ip) |
70 | 70 | { |
71 | | - if (!XFS_IFORK_Q(ip) || |
72 | | - (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS && |
73 | | - ip->i_afp->if_nextents == 0)) |
| 71 | + if (!XFS_IFORK_Q(ip)) |
| 72 | + return 0; |
| 73 | + if (!ip->i_afp) |
| 74 | + return 0; |
| 75 | + if (ip->i_afp->if_format == XFS_DINODE_FMT_EXTENTS && |
| 76 | + ip->i_afp->if_nextents == 0) |
74 | 77 | return 0; |
75 | 78 | return 1; |
76 | 79 | } |
@@ -408,23 +411,30 @@ xfs_attr_sf_addname( |
408 | 411 | } |
409 | 412 |
|
410 | 413 | /* |
411 | | - * When we bump the state to REPLACE, we may actually need to skip over the |
412 | | - * state. When LARP mode is enabled, we don't need to run the atomic flags flip, |
413 | | - * so we skip straight over the REPLACE state and go on to REMOVE_OLD. |
| 414 | + * Handle the state change on completion of a multi-state attr operation. |
| 415 | + * |
| 416 | + * If the XFS_DA_OP_REPLACE flag is set, this means the operation was the first |
| 417 | + * modification in a attr replace operation and we still have to do the second |
| 418 | + * state, indicated by @replace_state. |
| 419 | + * |
| 420 | + * We consume the XFS_DA_OP_REPLACE flag so that when we are called again on |
| 421 | + * completion of the second half of the attr replace operation we correctly |
| 422 | + * signal that it is done. |
414 | 423 | */ |
415 | | -static void |
416 | | -xfs_attr_dela_state_set_replace( |
| 424 | +static enum xfs_delattr_state |
| 425 | +xfs_attr_complete_op( |
417 | 426 | struct xfs_attr_item *attr, |
418 | | - enum xfs_delattr_state replace) |
| 427 | + enum xfs_delattr_state replace_state) |
419 | 428 | { |
420 | 429 | struct xfs_da_args *args = attr->xattri_da_args; |
| 430 | + bool do_replace = args->op_flags & XFS_DA_OP_REPLACE; |
421 | 431 |
|
422 | | - ASSERT(replace == XFS_DAS_LEAF_REPLACE || |
423 | | - replace == XFS_DAS_NODE_REPLACE); |
424 | | - |
425 | | - attr->xattri_dela_state = replace; |
426 | | - if (xfs_has_larp(args->dp->i_mount)) |
427 | | - attr->xattri_dela_state++; |
| 432 | + args->op_flags &= ~XFS_DA_OP_REPLACE; |
| 433 | + if (do_replace) { |
| 434 | + args->attr_filter &= ~XFS_ATTR_INCOMPLETE; |
| 435 | + return replace_state; |
| 436 | + } |
| 437 | + return XFS_DAS_DONE; |
428 | 438 | } |
429 | 439 |
|
430 | 440 | static int |
@@ -466,10 +476,9 @@ xfs_attr_leaf_addname( |
466 | 476 | */ |
467 | 477 | if (args->rmtblkno) |
468 | 478 | attr->xattri_dela_state = XFS_DAS_LEAF_SET_RMT; |
469 | | - else if (args->op_flags & XFS_DA_OP_REPLACE) |
470 | | - xfs_attr_dela_state_set_replace(attr, XFS_DAS_LEAF_REPLACE); |
471 | 479 | else |
472 | | - attr->xattri_dela_state = XFS_DAS_DONE; |
| 480 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 481 | + XFS_DAS_LEAF_REPLACE); |
473 | 482 | out: |
474 | 483 | trace_xfs_attr_leaf_addname_return(attr->xattri_dela_state, args->dp); |
475 | 484 | return error; |
@@ -511,10 +520,9 @@ xfs_attr_node_addname( |
511 | 520 |
|
512 | 521 | if (args->rmtblkno) |
513 | 522 | attr->xattri_dela_state = XFS_DAS_NODE_SET_RMT; |
514 | | - else if (args->op_flags & XFS_DA_OP_REPLACE) |
515 | | - xfs_attr_dela_state_set_replace(attr, XFS_DAS_NODE_REPLACE); |
516 | 523 | else |
517 | | - attr->xattri_dela_state = XFS_DAS_DONE; |
| 524 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 525 | + XFS_DAS_NODE_REPLACE); |
518 | 526 | out: |
519 | 527 | trace_xfs_attr_node_addname_return(attr->xattri_dela_state, args->dp); |
520 | 528 | return error; |
@@ -546,18 +554,15 @@ xfs_attr_rmtval_alloc( |
546 | 554 | if (error) |
547 | 555 | return error; |
548 | 556 |
|
549 | | - /* If this is not a rename, clear the incomplete flag and we're done. */ |
550 | | - if (!(args->op_flags & XFS_DA_OP_REPLACE)) { |
| 557 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 558 | + ++attr->xattri_dela_state); |
| 559 | + /* |
| 560 | + * If we are not doing a rename, we've finished the operation but still |
| 561 | + * have to clear the incomplete flag protecting the new attr from |
| 562 | + * exposing partially initialised state if we crash during creation. |
| 563 | + */ |
| 564 | + if (attr->xattri_dela_state == XFS_DAS_DONE) |
551 | 565 | error = xfs_attr3_leaf_clearflag(args); |
552 | | - attr->xattri_dela_state = XFS_DAS_DONE; |
553 | | - } else { |
554 | | - /* |
555 | | - * We are running a REPLACE operation, so we need to bump the |
556 | | - * state to the step in that operation. |
557 | | - */ |
558 | | - attr->xattri_dela_state++; |
559 | | - xfs_attr_dela_state_set_replace(attr, attr->xattri_dela_state); |
560 | | - } |
561 | 566 | out: |
562 | 567 | trace_xfs_attr_rmtval_alloc(attr->xattri_dela_state, args->dp); |
563 | 568 | return error; |
@@ -714,13 +719,24 @@ xfs_attr_set_iter( |
714 | 719 | return xfs_attr_node_addname(attr); |
715 | 720 |
|
716 | 721 | case XFS_DAS_SF_REMOVE: |
717 | | - attr->xattri_dela_state = XFS_DAS_DONE; |
718 | | - return xfs_attr_sf_removename(args); |
| 722 | + error = xfs_attr_sf_removename(args); |
| 723 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 724 | + xfs_attr_init_add_state(args)); |
| 725 | + break; |
719 | 726 | case XFS_DAS_LEAF_REMOVE: |
720 | | - attr->xattri_dela_state = XFS_DAS_DONE; |
721 | | - return xfs_attr_leaf_removename(args); |
| 727 | + error = xfs_attr_leaf_removename(args); |
| 728 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 729 | + xfs_attr_init_add_state(args)); |
| 730 | + break; |
722 | 731 | case XFS_DAS_NODE_REMOVE: |
723 | 732 | error = xfs_attr_node_removename_setup(attr); |
| 733 | + if (error == -ENOATTR && |
| 734 | + (args->op_flags & XFS_DA_OP_RECOVERY)) { |
| 735 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 736 | + xfs_attr_init_add_state(args)); |
| 737 | + error = 0; |
| 738 | + break; |
| 739 | + } |
724 | 740 | if (error) |
725 | 741 | return error; |
726 | 742 | attr->xattri_dela_state = XFS_DAS_NODE_REMOVE_RMT; |
@@ -806,14 +822,16 @@ xfs_attr_set_iter( |
806 | 822 |
|
807 | 823 | case XFS_DAS_LEAF_REMOVE_ATTR: |
808 | 824 | error = xfs_attr_leaf_remove_attr(attr); |
809 | | - attr->xattri_dela_state = XFS_DAS_DONE; |
| 825 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 826 | + xfs_attr_init_add_state(args)); |
810 | 827 | break; |
811 | 828 |
|
812 | 829 | case XFS_DAS_NODE_REMOVE_ATTR: |
813 | 830 | error = xfs_attr_node_remove_attr(attr); |
814 | 831 | if (!error) |
815 | 832 | error = xfs_attr_leaf_shrink(args); |
816 | | - attr->xattri_dela_state = XFS_DAS_DONE; |
| 833 | + attr->xattri_dela_state = xfs_attr_complete_op(attr, |
| 834 | + xfs_attr_init_add_state(args)); |
817 | 835 | break; |
818 | 836 | default: |
819 | 837 | ASSERT(0); |
@@ -1315,9 +1333,10 @@ xfs_attr_leaf_removename( |
1315 | 1333 | dp = args->dp; |
1316 | 1334 |
|
1317 | 1335 | error = xfs_attr_leaf_hasname(args, &bp); |
1318 | | - |
1319 | 1336 | if (error == -ENOATTR) { |
1320 | 1337 | xfs_trans_brelse(args->trans, bp); |
| 1338 | + if (args->op_flags & XFS_DA_OP_RECOVERY) |
| 1339 | + return 0; |
1321 | 1340 | return error; |
1322 | 1341 | } else if (error != -EEXIST) |
1323 | 1342 | return error; |
|
0 commit comments