diff options
author | Yan, Zheng <zheng.yan@oracle.com> | 2009-11-12 04:35:36 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-12-17 12:33:34 -0500 |
commit | 8082510e7124cc50d728f1b875639cb4e22312cc (patch) | |
tree | e9f0a0a4504a87689b4765368b508fff5ae2ddf8 /fs/btrfs/relocation.c | |
parent | 5a303d5d4b8055d2e5a03e92d04745bfc5881a22 (diff) |
Btrfs: Make truncate(2) more ENOSPC friendly
truncating and deleting regular files are unbound operations,
so it's not good to do them in a single transaction. This
patch makes btrfs_truncate and btrfs_delete_inode start a
new transaction after all items in a tree leaf are deleted.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/relocation.c')
-rw-r--r-- | fs/btrfs/relocation.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 975fdd33ac41..f2aa53d2f944 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -1561,6 +1561,20 @@ static int invalidate_extent_cache(struct btrfs_root *root, | |||
1561 | return 0; | 1561 | return 0; |
1562 | } | 1562 | } |
1563 | 1563 | ||
1564 | static void put_inodes(struct list_head *list) | ||
1565 | { | ||
1566 | struct inodevec *ivec; | ||
1567 | while (!list_empty(list)) { | ||
1568 | ivec = list_entry(list->next, struct inodevec, list); | ||
1569 | list_del(&ivec->list); | ||
1570 | while (ivec->nr > 0) { | ||
1571 | ivec->nr--; | ||
1572 | iput(ivec->inode[ivec->nr]); | ||
1573 | } | ||
1574 | kfree(ivec); | ||
1575 | } | ||
1576 | } | ||
1577 | |||
1564 | static int find_next_key(struct btrfs_path *path, int level, | 1578 | static int find_next_key(struct btrfs_path *path, int level, |
1565 | struct btrfs_key *key) | 1579 | struct btrfs_key *key) |
1566 | 1580 | ||
@@ -1723,6 +1737,11 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc, | |||
1723 | 1737 | ||
1724 | btrfs_btree_balance_dirty(root, nr); | 1738 | btrfs_btree_balance_dirty(root, nr); |
1725 | 1739 | ||
1740 | /* | ||
1741 | * put inodes outside transaction, otherwise we may deadlock. | ||
1742 | */ | ||
1743 | put_inodes(&inode_list); | ||
1744 | |||
1726 | if (replaced && rc->stage == UPDATE_DATA_PTRS) | 1745 | if (replaced && rc->stage == UPDATE_DATA_PTRS) |
1727 | invalidate_extent_cache(root, &key, &next_key); | 1746 | invalidate_extent_cache(root, &key, &next_key); |
1728 | } | 1747 | } |
@@ -1752,19 +1771,7 @@ out: | |||
1752 | 1771 | ||
1753 | btrfs_btree_balance_dirty(root, nr); | 1772 | btrfs_btree_balance_dirty(root, nr); |
1754 | 1773 | ||
1755 | /* | 1774 | put_inodes(&inode_list); |
1756 | * put inodes while we aren't holding the tree locks | ||
1757 | */ | ||
1758 | while (!list_empty(&inode_list)) { | ||
1759 | struct inodevec *ivec; | ||
1760 | ivec = list_entry(inode_list.next, struct inodevec, list); | ||
1761 | list_del(&ivec->list); | ||
1762 | while (ivec->nr > 0) { | ||
1763 | ivec->nr--; | ||
1764 | iput(ivec->inode[ivec->nr]); | ||
1765 | } | ||
1766 | kfree(ivec); | ||
1767 | } | ||
1768 | 1775 | ||
1769 | if (replaced && rc->stage == UPDATE_DATA_PTRS) | 1776 | if (replaced && rc->stage == UPDATE_DATA_PTRS) |
1770 | invalidate_extent_cache(root, &key, &next_key); | 1777 | invalidate_extent_cache(root, &key, &next_key); |