diff options
author | Brian Foster <bfoster@redhat.com> | 2013-09-20 11:06:09 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2013-10-08 15:53:02 -0400 |
commit | 36b21dde6e899d2f25077b7c239d2d6bcff17d73 (patch) | |
tree | 34470b5c788b4db47002d891aa7f8d065aabd3df /fs/xfs/xfs_symlink.c | |
parent | 2900a579abcea13e4e77c40f89eb16eeecb5508e (diff) |
xfs: push down inactive transaction mgmt for remote symlinks
Push down the transaction management for remote symlinks from
xfs_inactive() down to xfs_inactive_symlink_rmt(). The latter is
cleaned up to avoid transaction management intended for the
calling context (i.e., trans duplication, reservation, item
attachment).
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_symlink.c')
-rw-r--r-- | fs/xfs/xfs_symlink.c | 86 |
1 files changed, 40 insertions, 46 deletions
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index f622a97a7e33..ded282b10bc2 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c | |||
@@ -424,8 +424,7 @@ xfs_symlink( | |||
424 | */ | 424 | */ |
425 | STATIC int | 425 | STATIC int |
426 | xfs_inactive_symlink_rmt( | 426 | xfs_inactive_symlink_rmt( |
427 | xfs_inode_t *ip, | 427 | struct xfs_inode *ip) |
428 | xfs_trans_t **tpp) | ||
429 | { | 428 | { |
430 | xfs_buf_t *bp; | 429 | xfs_buf_t *bp; |
431 | int committed; | 430 | int committed; |
@@ -437,11 +436,9 @@ xfs_inactive_symlink_rmt( | |||
437 | xfs_mount_t *mp; | 436 | xfs_mount_t *mp; |
438 | xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; | 437 | xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; |
439 | int nmaps; | 438 | int nmaps; |
440 | xfs_trans_t *ntp; | ||
441 | int size; | 439 | int size; |
442 | xfs_trans_t *tp; | 440 | xfs_trans_t *tp; |
443 | 441 | ||
444 | tp = *tpp; | ||
445 | mp = ip->i_mount; | 442 | mp = ip->i_mount; |
446 | ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS); | 443 | ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS); |
447 | /* | 444 | /* |
@@ -453,6 +450,16 @@ xfs_inactive_symlink_rmt( | |||
453 | */ | 450 | */ |
454 | ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); | 451 | ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); |
455 | 452 | ||
453 | tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); | ||
454 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); | ||
455 | if (error) { | ||
456 | xfs_trans_cancel(tp, 0); | ||
457 | return error; | ||
458 | } | ||
459 | |||
460 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
461 | xfs_trans_ijoin(tp, ip, 0); | ||
462 | |||
456 | /* | 463 | /* |
457 | * Lock the inode, fix the size, and join it to the transaction. | 464 | * Lock the inode, fix the size, and join it to the transaction. |
458 | * Hold it so in the normal path, we still have it locked for | 465 | * Hold it so in the normal path, we still have it locked for |
@@ -471,7 +478,7 @@ xfs_inactive_symlink_rmt( | |||
471 | error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), | 478 | error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), |
472 | mval, &nmaps, 0); | 479 | mval, &nmaps, 0); |
473 | if (error) | 480 | if (error) |
474 | goto error0; | 481 | goto error_trans_cancel; |
475 | /* | 482 | /* |
476 | * Invalidate the block(s). No validation is done. | 483 | * Invalidate the block(s). No validation is done. |
477 | */ | 484 | */ |
@@ -481,22 +488,24 @@ xfs_inactive_symlink_rmt( | |||
481 | XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0); | 488 | XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0); |
482 | if (!bp) { | 489 | if (!bp) { |
483 | error = ENOMEM; | 490 | error = ENOMEM; |
484 | goto error1; | 491 | goto error_bmap_cancel; |
485 | } | 492 | } |
486 | xfs_trans_binval(tp, bp); | 493 | xfs_trans_binval(tp, bp); |
487 | } | 494 | } |
488 | /* | 495 | /* |
489 | * Unmap the dead block(s) to the free_list. | 496 | * Unmap the dead block(s) to the free_list. |
490 | */ | 497 | */ |
491 | if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, | 498 | error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, |
492 | &first_block, &free_list, &done))) | 499 | &first_block, &free_list, &done); |
493 | goto error1; | 500 | if (error) |
501 | goto error_bmap_cancel; | ||
494 | ASSERT(done); | 502 | ASSERT(done); |
495 | /* | 503 | /* |
496 | * Commit the first transaction. This logs the EFI and the inode. | 504 | * Commit the first transaction. This logs the EFI and the inode. |
497 | */ | 505 | */ |
498 | if ((error = xfs_bmap_finish(&tp, &free_list, &committed))) | 506 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
499 | goto error1; | 507 | if (error) |
508 | goto error_bmap_cancel; | ||
500 | /* | 509 | /* |
501 | * The transaction must have been committed, since there were | 510 | * The transaction must have been committed, since there were |
502 | * actually extents freed by xfs_bunmapi. See xfs_bmap_finish. | 511 | * actually extents freed by xfs_bunmapi. See xfs_bmap_finish. |
@@ -511,26 +520,13 @@ xfs_inactive_symlink_rmt( | |||
511 | xfs_trans_ijoin(tp, ip, 0); | 520 | xfs_trans_ijoin(tp, ip, 0); |
512 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 521 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
513 | /* | 522 | /* |
514 | * Get a new, empty transaction to return to our caller. | ||
515 | */ | ||
516 | ntp = xfs_trans_dup(tp); | ||
517 | /* | ||
518 | * Commit the transaction containing extent freeing and EFDs. | 523 | * Commit the transaction containing extent freeing and EFDs. |
519 | * If we get an error on the commit here or on the reserve below, | ||
520 | * we need to unlock the inode since the new transaction doesn't | ||
521 | * have the inode attached. | ||
522 | */ | 524 | */ |
523 | error = xfs_trans_commit(tp, 0); | 525 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
524 | tp = ntp; | ||
525 | if (error) { | 526 | if (error) { |
526 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | 527 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); |
527 | goto error0; | 528 | goto error_unlock; |
528 | } | 529 | } |
529 | /* | ||
530 | * transaction commit worked ok so we can drop the extra ticket | ||
531 | * reference that we gained in xfs_trans_dup() | ||
532 | */ | ||
533 | xfs_log_ticket_put(tp->t_ticket); | ||
534 | 530 | ||
535 | /* | 531 | /* |
536 | * Remove the memory for extent descriptions (just bookkeeping). | 532 | * Remove the memory for extent descriptions (just bookkeeping). |
@@ -538,23 +534,16 @@ xfs_inactive_symlink_rmt( | |||
538 | if (ip->i_df.if_bytes) | 534 | if (ip->i_df.if_bytes) |
539 | xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK); | 535 | xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK); |
540 | ASSERT(ip->i_df.if_bytes == 0); | 536 | ASSERT(ip->i_df.if_bytes == 0); |
541 | /* | ||
542 | * Put an itruncate log reservation in the new transaction | ||
543 | * for our caller. | ||
544 | */ | ||
545 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); | ||
546 | if (error) { | ||
547 | ASSERT(XFS_FORCED_SHUTDOWN(mp)); | ||
548 | goto error0; | ||
549 | } | ||
550 | 537 | ||
551 | xfs_trans_ijoin(tp, ip, 0); | 538 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
552 | *tpp = tp; | ||
553 | return 0; | 539 | return 0; |
554 | 540 | ||
555 | error1: | 541 | error_bmap_cancel: |
556 | xfs_bmap_cancel(&free_list); | 542 | xfs_bmap_cancel(&free_list); |
557 | error0: | 543 | error_trans_cancel: |
544 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
545 | error_unlock: | ||
546 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
558 | return error; | 547 | return error; |
559 | } | 548 | } |
560 | 549 | ||
@@ -563,41 +552,46 @@ xfs_inactive_symlink_rmt( | |||
563 | */ | 552 | */ |
564 | int | 553 | int |
565 | xfs_inactive_symlink( | 554 | xfs_inactive_symlink( |
566 | struct xfs_inode *ip, | 555 | struct xfs_inode *ip) |
567 | struct xfs_trans **tp) | ||
568 | { | 556 | { |
569 | struct xfs_mount *mp = ip->i_mount; | 557 | struct xfs_mount *mp = ip->i_mount; |
570 | int pathlen; | 558 | int pathlen; |
571 | 559 | ||
572 | trace_xfs_inactive_symlink(ip); | 560 | trace_xfs_inactive_symlink(ip); |
573 | 561 | ||
574 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
575 | |||
576 | if (XFS_FORCED_SHUTDOWN(mp)) | 562 | if (XFS_FORCED_SHUTDOWN(mp)) |
577 | return XFS_ERROR(EIO); | 563 | return XFS_ERROR(EIO); |
578 | 564 | ||
565 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
566 | |||
579 | /* | 567 | /* |
580 | * Zero length symlinks _can_ exist. | 568 | * Zero length symlinks _can_ exist. |
581 | */ | 569 | */ |
582 | pathlen = (int)ip->i_d.di_size; | 570 | pathlen = (int)ip->i_d.di_size; |
583 | if (!pathlen) | 571 | if (!pathlen) { |
572 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
584 | return 0; | 573 | return 0; |
574 | } | ||
585 | 575 | ||
586 | if (pathlen < 0 || pathlen > MAXPATHLEN) { | 576 | if (pathlen < 0 || pathlen > MAXPATHLEN) { |
587 | xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", | 577 | xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", |
588 | __func__, (unsigned long long)ip->i_ino, pathlen); | 578 | __func__, (unsigned long long)ip->i_ino, pathlen); |
579 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
589 | ASSERT(0); | 580 | ASSERT(0); |
590 | return XFS_ERROR(EFSCORRUPTED); | 581 | return XFS_ERROR(EFSCORRUPTED); |
591 | } | 582 | } |
592 | 583 | ||
593 | if (ip->i_df.if_flags & XFS_IFINLINE) { | 584 | if (ip->i_df.if_flags & XFS_IFINLINE) { |
594 | if (ip->i_df.if_bytes > 0) | 585 | if (ip->i_df.if_bytes > 0) |
595 | xfs_idata_realloc(ip, -(ip->i_df.if_bytes), | 586 | xfs_idata_realloc(ip, -(ip->i_df.if_bytes), |
596 | XFS_DATA_FORK); | 587 | XFS_DATA_FORK); |
588 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
597 | ASSERT(ip->i_df.if_bytes == 0); | 589 | ASSERT(ip->i_df.if_bytes == 0); |
598 | return 0; | 590 | return 0; |
599 | } | 591 | } |
600 | 592 | ||
593 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
594 | |||
601 | /* remove the remote symlink */ | 595 | /* remove the remote symlink */ |
602 | return xfs_inactive_symlink_rmt(ip, tp); | 596 | return xfs_inactive_symlink_rmt(ip); |
603 | } | 597 | } |