diff options
author | David Chinner <dgc@sgi.com> | 2008-04-17 02:50:04 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-04-17 22:03:26 -0400 |
commit | f6485057c5cfbc84e5eff639ddea1ce0d668607b (patch) | |
tree | 5366b91b26379b32e900fdccbac26edf71bca1b9 | |
parent | 7e20694d91f817f8e9f62404aca793ae0df4d98a (diff) |
[XFS] Ensure the inode is joined in xfs_itruncate_finish
On success, we still need to join the inode to the current transaction in
xfs_itruncate_finish(). Fixes regression from error handling changes.
SGI-PV: 980084
SGI-Modid: xfs-linux-melb:xfs-kern:30845a
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
-rw-r--r-- | fs/xfs/xfs_inode.c | 137 |
1 files changed, 65 insertions, 72 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 2bc22790d65a..ca12acb90394 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1464,51 +1464,50 @@ xfs_itruncate_start( | |||
1464 | } | 1464 | } |
1465 | 1465 | ||
1466 | /* | 1466 | /* |
1467 | * Shrink the file to the given new_size. The new | 1467 | * Shrink the file to the given new_size. The new size must be smaller than |
1468 | * size must be smaller than the current size. | 1468 | * the current size. This will free up the underlying blocks in the removed |
1469 | * This will free up the underlying blocks | 1469 | * range after a call to xfs_itruncate_start() or xfs_atruncate_start(). |
1470 | * in the removed range after a call to xfs_itruncate_start() | ||
1471 | * or xfs_atruncate_start(). | ||
1472 | * | 1470 | * |
1473 | * The transaction passed to this routine must have made | 1471 | * The transaction passed to this routine must have made a permanent log |
1474 | * a permanent log reservation of at least XFS_ITRUNCATE_LOG_RES. | 1472 | * reservation of at least XFS_ITRUNCATE_LOG_RES. This routine may commit the |
1475 | * This routine may commit the given transaction and | 1473 | * given transaction and start new ones, so make sure everything involved in |
1476 | * start new ones, so make sure everything involved in | 1474 | * the transaction is tidy before calling here. Some transaction will be |
1477 | * the transaction is tidy before calling here. | 1475 | * returned to the caller to be committed. The incoming transaction must |
1478 | * Some transaction will be returned to the caller to be | 1476 | * already include the inode, and both inode locks must be held exclusively. |
1479 | * committed. The incoming transaction must already include | 1477 | * The inode must also be "held" within the transaction. On return the inode |
1480 | * the inode, and both inode locks must be held exclusively. | 1478 | * will be "held" within the returned transaction. This routine does NOT |
1481 | * The inode must also be "held" within the transaction. On | 1479 | * require any disk space to be reserved for it within the transaction. |
1482 | * return the inode will be "held" within the returned transaction. | ||
1483 | * This routine does NOT require any disk space to be reserved | ||
1484 | * for it within the transaction. | ||
1485 | * | 1480 | * |
1486 | * The fork parameter must be either xfs_attr_fork or xfs_data_fork, | 1481 | * The fork parameter must be either xfs_attr_fork or xfs_data_fork, and it |
1487 | * and it indicates the fork which is to be truncated. For the | 1482 | * indicates the fork which is to be truncated. For the attribute fork we only |
1488 | * attribute fork we only support truncation to size 0. | 1483 | * support truncation to size 0. |
1489 | * | 1484 | * |
1490 | * We use the sync parameter to indicate whether or not the first | 1485 | * We use the sync parameter to indicate whether or not the first transaction |
1491 | * transaction we perform might have to be synchronous. For the attr fork, | 1486 | * we perform might have to be synchronous. For the attr fork, it needs to be |
1492 | * it needs to be so if the unlink of the inode is not yet known to be | 1487 | * so if the unlink of the inode is not yet known to be permanent in the log. |
1493 | * permanent in the log. This keeps us from freeing and reusing the | 1488 | * This keeps us from freeing and reusing the blocks of the attribute fork |
1494 | * blocks of the attribute fork before the unlink of the inode becomes | 1489 | * before the unlink of the inode becomes permanent. |
1495 | * permanent. | ||
1496 | * | 1490 | * |
1497 | * For the data fork, we normally have to run synchronously if we're | 1491 | * For the data fork, we normally have to run synchronously if we're being |
1498 | * being called out of the inactive path or we're being called | 1492 | * called out of the inactive path or we're being called out of the create path |
1499 | * out of the create path where we're truncating an existing file. | 1493 | * where we're truncating an existing file. Either way, the truncate needs to |
1500 | * Either way, the truncate needs to be sync so blocks don't reappear | 1494 | * be sync so blocks don't reappear in the file with altered data in case of a |
1501 | * in the file with altered data in case of a crash. wsync filesystems | 1495 | * crash. wsync filesystems can run the first case async because anything that |
1502 | * can run the first case async because anything that shrinks the inode | 1496 | * shrinks the inode has to run sync so by the time we're called here from |
1503 | * has to run sync so by the time we're called here from inactive, the | 1497 | * inactive, the inode size is permanently set to 0. |
1504 | * inode size is permanently set to 0. | ||
1505 | * | 1498 | * |
1506 | * Calls from the truncate path always need to be sync unless we're | 1499 | * Calls from the truncate path always need to be sync unless we're in a wsync |
1507 | * in a wsync filesystem and the file has already been unlinked. | 1500 | * filesystem and the file has already been unlinked. |
1508 | * | 1501 | * |
1509 | * The caller is responsible for correctly setting the sync parameter. | 1502 | * The caller is responsible for correctly setting the sync parameter. It gets |
1510 | * It gets too hard for us to guess here which path we're being called | 1503 | * too hard for us to guess here which path we're being called out of just |
1511 | * out of just based on inode state. | 1504 | * based on inode state. |
1505 | * | ||
1506 | * If we get an error, we must return with the inode locked and linked into the | ||
1507 | * current transaction. This keeps things simple for the higher level code, | ||
1508 | * because it always knows that the inode is locked and held in the transaction | ||
1509 | * that returns to it whether errors occur or not. We don't mark the inode | ||
1510 | * dirty on error so that transactions can be easily aborted if possible. | ||
1512 | */ | 1511 | */ |
1513 | int | 1512 | int |
1514 | xfs_itruncate_finish( | 1513 | xfs_itruncate_finish( |
@@ -1687,45 +1686,51 @@ xfs_itruncate_finish( | |||
1687 | */ | 1686 | */ |
1688 | error = xfs_bmap_finish(tp, &free_list, &committed); | 1687 | error = xfs_bmap_finish(tp, &free_list, &committed); |
1689 | ntp = *tp; | 1688 | ntp = *tp; |
1689 | if (committed) { | ||
1690 | /* link the inode into the next xact in the chain */ | ||
1691 | xfs_trans_ijoin(ntp, ip, | ||
1692 | XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
1693 | xfs_trans_ihold(ntp, ip); | ||
1694 | } | ||
1695 | |||
1690 | if (error) { | 1696 | if (error) { |
1691 | /* | 1697 | /* |
1692 | * If the bmap finish call encounters an error, | 1698 | * If the bmap finish call encounters an error, return |
1693 | * return to the caller where the transaction | 1699 | * to the caller where the transaction can be properly |
1694 | * can be properly aborted. We just need to | 1700 | * aborted. We just need to make sure we're not |
1695 | * make sure we're not holding any resources | 1701 | * holding any resources that we were not when we came |
1696 | * that we were not when we came in. | 1702 | * in. |
1697 | * | 1703 | * |
1698 | * Aborting from this point might lose some | 1704 | * Aborting from this point might lose some blocks in |
1699 | * blocks in the file system, but oh well. | 1705 | * the file system, but oh well. |
1700 | */ | 1706 | */ |
1701 | xfs_bmap_cancel(&free_list); | 1707 | xfs_bmap_cancel(&free_list); |
1702 | if (committed) | ||
1703 | goto error_join; | ||
1704 | return error; | 1708 | return error; |
1705 | } | 1709 | } |
1706 | 1710 | ||
1707 | if (committed) { | 1711 | if (committed) { |
1708 | /* | 1712 | /* |
1709 | * The first xact was committed, so add the inode to | 1713 | * Mark the inode dirty so it will be logged and |
1710 | * the new one. Mark it dirty so it will be logged and | ||
1711 | * moved forward in the log as part of every commit. | 1714 | * moved forward in the log as part of every commit. |
1712 | */ | 1715 | */ |
1713 | xfs_trans_ijoin(ntp, ip, | ||
1714 | XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
1715 | xfs_trans_ihold(ntp, ip); | ||
1716 | xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE); | 1716 | xfs_trans_log_inode(ntp, ip, XFS_ILOG_CORE); |
1717 | } | 1717 | } |
1718 | |||
1718 | ntp = xfs_trans_dup(ntp); | 1719 | ntp = xfs_trans_dup(ntp); |
1719 | error = xfs_trans_commit(*tp, 0); | 1720 | error = xfs_trans_commit(*tp, 0); |
1720 | *tp = ntp; | 1721 | *tp = ntp; |
1721 | if (error) | ||
1722 | goto error_join; | ||
1723 | error = xfs_trans_reserve(ntp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, | ||
1724 | XFS_TRANS_PERM_LOG_RES, | ||
1725 | XFS_ITRUNCATE_LOG_COUNT); | ||
1726 | if (error) | ||
1727 | goto error_join; | ||
1728 | 1722 | ||
1723 | /* link the inode into the next transaction in the chain */ | ||
1724 | xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
1725 | xfs_trans_ihold(ntp, ip); | ||
1726 | |||
1727 | if (!error) | ||
1728 | error = xfs_trans_reserve(ntp, 0, | ||
1729 | XFS_ITRUNCATE_LOG_RES(mp), 0, | ||
1730 | XFS_TRANS_PERM_LOG_RES, | ||
1731 | XFS_ITRUNCATE_LOG_COUNT); | ||
1732 | if (error) | ||
1733 | return error; | ||
1729 | } | 1734 | } |
1730 | /* | 1735 | /* |
1731 | * Only update the size in the case of the data fork, but | 1736 | * Only update the size in the case of the data fork, but |
@@ -1757,18 +1762,6 @@ xfs_itruncate_finish( | |||
1757 | (ip->i_d.di_nextents == 0)); | 1762 | (ip->i_d.di_nextents == 0)); |
1758 | xfs_itrunc_trace(XFS_ITRUNC_FINISH2, ip, 0, new_size, 0, 0); | 1763 | xfs_itrunc_trace(XFS_ITRUNC_FINISH2, ip, 0, new_size, 0, 0); |
1759 | return 0; | 1764 | return 0; |
1760 | |||
1761 | error_join: | ||
1762 | /* | ||
1763 | * Add the inode being truncated to the next chained transaction. This | ||
1764 | * keeps things simple for the higher level code, because it always | ||
1765 | * knows that the inode is locked and held in the transaction that | ||
1766 | * returns to it whether errors occur or not. We don't mark the inode | ||
1767 | * dirty so that this transaction can be easily aborted if possible. | ||
1768 | */ | ||
1769 | xfs_trans_ijoin(ntp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); | ||
1770 | xfs_trans_ihold(ntp, ip); | ||
1771 | return error; | ||
1772 | } | 1765 | } |
1773 | 1766 | ||
1774 | 1767 | ||