aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_symlink.c
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2013-09-20 11:06:09 -0400
committerBen Myers <bpm@sgi.com>2013-10-08 15:53:02 -0400
commit36b21dde6e899d2f25077b7c239d2d6bcff17d73 (patch)
tree34470b5c788b4db47002d891aa7f8d065aabd3df /fs/xfs/xfs_symlink.c
parent2900a579abcea13e4e77c40f89eb16eeecb5508e (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.c86
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 */
425STATIC int 425STATIC int
426xfs_inactive_symlink_rmt( 426xfs_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: 541error_bmap_cancel:
556 xfs_bmap_cancel(&free_list); 542 xfs_bmap_cancel(&free_list);
557 error0: 543error_trans_cancel:
544 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
545error_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 */
564int 553int
565xfs_inactive_symlink( 554xfs_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}