Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Brian Foster and committed by
Ben Myers
36b21dde 2900a579

+49 -54
+8 -7
fs/xfs/xfs_inode.c
··· 1724 1724 if (error) 1725 1725 return VN_INACTIVE_CACHE; 1726 1726 1727 + if (S_ISLNK(ip->i_d.di_mode)) { 1728 + error = xfs_inactive_symlink(ip); 1729 + if (error) 1730 + goto out; 1731 + } 1732 + 1727 1733 tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 1728 - resp = (truncate || S_ISLNK(ip->i_d.di_mode)) ? 1729 - &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree; 1734 + resp = truncate ? &M_RES(mp)->tr_itruncate : &M_RES(mp)->tr_ifree; 1730 1735 1731 1736 error = xfs_trans_reserve(tp, resp, 0, 0); 1732 1737 if (error) { ··· 1743 1738 xfs_ilock(ip, XFS_ILOCK_EXCL); 1744 1739 xfs_trans_ijoin(tp, ip, 0); 1745 1740 1746 - if (S_ISLNK(ip->i_d.di_mode)) { 1747 - error = xfs_inactive_symlink(ip, &tp); 1748 - if (error) 1749 - goto out_cancel; 1750 - } else if (truncate) { 1741 + if (truncate) { 1751 1742 ip->i_d.di_size = 0; 1752 1743 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 1753 1744
+40 -46
fs/xfs/xfs_symlink.c
··· 424 424 */ 425 425 STATIC int 426 426 xfs_inactive_symlink_rmt( 427 - xfs_inode_t *ip, 428 - xfs_trans_t **tpp) 427 + struct xfs_inode *ip) 429 428 { 430 429 xfs_buf_t *bp; 431 430 int committed; ··· 436 437 xfs_mount_t *mp; 437 438 xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; 438 439 int nmaps; 439 - xfs_trans_t *ntp; 440 440 int size; 441 441 xfs_trans_t *tp; 442 442 443 - tp = *tpp; 444 443 mp = ip->i_mount; 445 444 ASSERT(ip->i_df.if_flags & XFS_IFEXTENTS); 446 445 /* ··· 449 452 * free them all in one bunmapi call. 450 453 */ 451 454 ASSERT(ip->i_d.di_nextents > 0 && ip->i_d.di_nextents <= 2); 455 + 456 + tp = xfs_trans_alloc(mp, XFS_TRANS_INACTIVE); 457 + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); 458 + if (error) { 459 + xfs_trans_cancel(tp, 0); 460 + return error; 461 + } 462 + 463 + xfs_ilock(ip, XFS_ILOCK_EXCL); 464 + xfs_trans_ijoin(tp, ip, 0); 452 465 453 466 /* 454 467 * Lock the inode, fix the size, and join it to the transaction. ··· 478 471 error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), 479 472 mval, &nmaps, 0); 480 473 if (error) 481 - goto error0; 474 + goto error_trans_cancel; 482 475 /* 483 476 * Invalidate the block(s). No validation is done. 484 477 */ ··· 488 481 XFS_FSB_TO_BB(mp, mval[i].br_blockcount), 0); 489 482 if (!bp) { 490 483 error = ENOMEM; 491 - goto error1; 484 + goto error_bmap_cancel; 492 485 } 493 486 xfs_trans_binval(tp, bp); 494 487 } 495 488 /* 496 489 * Unmap the dead block(s) to the free_list. 497 490 */ 498 - if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, 499 - &first_block, &free_list, &done))) 500 - goto error1; 491 + error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, 492 + &first_block, &free_list, &done); 493 + if (error) 494 + goto error_bmap_cancel; 501 495 ASSERT(done); 502 496 /* 503 497 * Commit the first transaction. This logs the EFI and the inode. 504 498 */ 505 - if ((error = xfs_bmap_finish(&tp, &free_list, &committed))) 506 - goto error1; 499 + error = xfs_bmap_finish(&tp, &free_list, &committed); 500 + if (error) 501 + goto error_bmap_cancel; 507 502 /* 508 503 * The transaction must have been committed, since there were 509 504 * actually extents freed by xfs_bunmapi. See xfs_bmap_finish. ··· 520 511 xfs_trans_ijoin(tp, ip, 0); 521 512 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); 522 513 /* 523 - * Get a new, empty transaction to return to our caller. 524 - */ 525 - ntp = xfs_trans_dup(tp); 526 - /* 527 514 * Commit the transaction containing extent freeing and EFDs. 528 - * If we get an error on the commit here or on the reserve below, 529 - * we need to unlock the inode since the new transaction doesn't 530 - * have the inode attached. 531 515 */ 532 - error = xfs_trans_commit(tp, 0); 533 - tp = ntp; 516 + error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 534 517 if (error) { 535 518 ASSERT(XFS_FORCED_SHUTDOWN(mp)); 536 - goto error0; 519 + goto error_unlock; 537 520 } 538 - /* 539 - * transaction commit worked ok so we can drop the extra ticket 540 - * reference that we gained in xfs_trans_dup() 541 - */ 542 - xfs_log_ticket_put(tp->t_ticket); 543 521 544 522 /* 545 523 * Remove the memory for extent descriptions (just bookkeeping). ··· 534 538 if (ip->i_df.if_bytes) 535 539 xfs_idata_realloc(ip, -ip->i_df.if_bytes, XFS_DATA_FORK); 536 540 ASSERT(ip->i_df.if_bytes == 0); 537 - /* 538 - * Put an itruncate log reservation in the new transaction 539 - * for our caller. 540 - */ 541 - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_itruncate, 0, 0); 542 - if (error) { 543 - ASSERT(XFS_FORCED_SHUTDOWN(mp)); 544 - goto error0; 545 - } 546 541 547 - xfs_trans_ijoin(tp, ip, 0); 548 - *tpp = tp; 542 + xfs_iunlock(ip, XFS_ILOCK_EXCL); 549 543 return 0; 550 544 551 - error1: 545 + error_bmap_cancel: 552 546 xfs_bmap_cancel(&free_list); 553 - error0: 547 + error_trans_cancel: 548 + xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 549 + error_unlock: 550 + xfs_iunlock(ip, XFS_ILOCK_EXCL); 554 551 return error; 555 552 } 556 553 ··· 552 563 */ 553 564 int 554 565 xfs_inactive_symlink( 555 - struct xfs_inode *ip, 556 - struct xfs_trans **tp) 566 + struct xfs_inode *ip) 557 567 { 558 568 struct xfs_mount *mp = ip->i_mount; 559 569 int pathlen; 560 570 561 571 trace_xfs_inactive_symlink(ip); 562 572 563 - ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 564 - 565 573 if (XFS_FORCED_SHUTDOWN(mp)) 566 574 return XFS_ERROR(EIO); 575 + 576 + xfs_ilock(ip, XFS_ILOCK_EXCL); 567 577 568 578 /* 569 579 * Zero length symlinks _can_ exist. 570 580 */ 571 581 pathlen = (int)ip->i_d.di_size; 572 - if (!pathlen) 582 + if (!pathlen) { 583 + xfs_iunlock(ip, XFS_ILOCK_EXCL); 573 584 return 0; 585 + } 574 586 575 587 if (pathlen < 0 || pathlen > MAXPATHLEN) { 576 588 xfs_alert(mp, "%s: inode (0x%llx) bad symlink length (%d)", 577 589 __func__, (unsigned long long)ip->i_ino, pathlen); 590 + xfs_iunlock(ip, XFS_ILOCK_EXCL); 578 591 ASSERT(0); 579 592 return XFS_ERROR(EFSCORRUPTED); 580 593 } 581 594 582 595 if (ip->i_df.if_flags & XFS_IFINLINE) { 583 - if (ip->i_df.if_bytes > 0) 596 + if (ip->i_df.if_bytes > 0) 584 597 xfs_idata_realloc(ip, -(ip->i_df.if_bytes), 585 598 XFS_DATA_FORK); 599 + xfs_iunlock(ip, XFS_ILOCK_EXCL); 586 600 ASSERT(ip->i_df.if_bytes == 0); 587 601 return 0; 588 602 } 589 603 604 + xfs_iunlock(ip, XFS_ILOCK_EXCL); 605 + 590 606 /* remove the remote symlink */ 591 - return xfs_inactive_symlink_rmt(ip, tp); 607 + return xfs_inactive_symlink_rmt(ip); 592 608 }
+1 -1
fs/xfs/xfs_symlink.h
··· 22 22 int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, 23 23 const char *target_path, umode_t mode, struct xfs_inode **ipp); 24 24 int xfs_readlink(struct xfs_inode *ip, char *link); 25 - int xfs_inactive_symlink(struct xfs_inode *ip, struct xfs_trans **tpp); 25 + int xfs_inactive_symlink(struct xfs_inode *ip); 26 26 27 27 #endif /* __XFS_SYMLINK_H */