diff options
author | Zheng Yan <zheng.yan@oracle.com> | 2008-09-26 10:05:38 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-26 10:05:38 -0400 |
commit | 5b21f2ed3f2947b5195b65c9fdbdd9e52904cc03 (patch) | |
tree | 9af8f539ac487c163f3207bc065767c3c8b37ae7 /fs/btrfs/inode.c | |
parent | e465768938f95388723b0fd3c50a0ae48173edb9 (diff) |
Btrfs: extent_map and data=ordered fixes for space balancing
* Add an EXTENT_BOUNDARY state bit to keep the writepage code
from merging data extents that are in the process of being
relocated. This allows us to do accounting for them properly.
* The balancing code relocates data extents indepdent of the underlying
inode. The extent_map code was modified to properly account for
things moving around (invalidating extent_map caches in the inode).
* Don't take the drop_mutex in the create_subvol ioctl. It isn't
required.
* Fix walking of the ordered extent list to avoid races with sys_unlink
* Change the lock ordering rules. Transaction start goes outside
the drop_mutex. This allows btrfs_commit_transaction to directly
drop the relocation trees.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 48a3dc030807..4516fbf01671 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -135,7 +135,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
135 | 135 | ||
136 | BUG_ON(num_bytes > btrfs_super_total_bytes(&root->fs_info->super_copy)); | 136 | BUG_ON(num_bytes > btrfs_super_total_bytes(&root->fs_info->super_copy)); |
137 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | 137 | mutex_lock(&BTRFS_I(inode)->extent_mutex); |
138 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1); | 138 | btrfs_drop_extent_cache(inode, start, start + num_bytes - 1, 0); |
139 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | 139 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); |
140 | 140 | ||
141 | while(num_bytes > 0) { | 141 | while(num_bytes > 0) { |
@@ -163,7 +163,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
163 | break; | 163 | break; |
164 | } | 164 | } |
165 | btrfs_drop_extent_cache(inode, start, | 165 | btrfs_drop_extent_cache(inode, start, |
166 | start + ins.offset - 1); | 166 | start + ins.offset - 1, 0); |
167 | } | 167 | } |
168 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | 168 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); |
169 | 169 | ||
@@ -587,7 +587,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
587 | 587 | ||
588 | btrfs_drop_extent_cache(inode, ordered_extent->file_offset, | 588 | btrfs_drop_extent_cache(inode, ordered_extent->file_offset, |
589 | ordered_extent->file_offset + | 589 | ordered_extent->file_offset + |
590 | ordered_extent->len - 1); | 590 | ordered_extent->len - 1, 0); |
591 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | 591 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); |
592 | 592 | ||
593 | ins.objectid = ordered_extent->start; | 593 | ins.objectid = ordered_extent->start; |
@@ -880,7 +880,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
880 | int ret = 0, nr_unlink = 0, nr_truncate = 0; | 880 | int ret = 0, nr_unlink = 0, nr_truncate = 0; |
881 | 881 | ||
882 | /* don't do orphan cleanup if the fs is readonly. */ | 882 | /* don't do orphan cleanup if the fs is readonly. */ |
883 | if (root->inode->i_sb->s_flags & MS_RDONLY) | 883 | if (root->fs_info->sb->s_flags & MS_RDONLY) |
884 | return; | 884 | return; |
885 | 885 | ||
886 | path = btrfs_alloc_path(); | 886 | path = btrfs_alloc_path(); |
@@ -892,8 +892,6 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
892 | btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY); | 892 | btrfs_set_key_type(&key, BTRFS_ORPHAN_ITEM_KEY); |
893 | key.offset = (u64)-1; | 893 | key.offset = (u64)-1; |
894 | 894 | ||
895 | trans = btrfs_start_transaction(root, 1); | ||
896 | btrfs_set_trans_block_group(trans, root->inode); | ||
897 | 895 | ||
898 | while (1) { | 896 | while (1) { |
899 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 897 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
@@ -933,7 +931,7 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
933 | * crossing root thing. we store the inode number in the | 931 | * crossing root thing. we store the inode number in the |
934 | * offset of the orphan item. | 932 | * offset of the orphan item. |
935 | */ | 933 | */ |
936 | inode = btrfs_iget_locked(root->inode->i_sb, | 934 | inode = btrfs_iget_locked(root->fs_info->sb, |
937 | found_key.offset, root); | 935 | found_key.offset, root); |
938 | if (!inode) | 936 | if (!inode) |
939 | break; | 937 | break; |
@@ -965,7 +963,9 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
965 | * do a destroy_inode | 963 | * do a destroy_inode |
966 | */ | 964 | */ |
967 | if (is_bad_inode(inode)) { | 965 | if (is_bad_inode(inode)) { |
966 | trans = btrfs_start_transaction(root, 1); | ||
968 | btrfs_orphan_del(trans, inode); | 967 | btrfs_orphan_del(trans, inode); |
968 | btrfs_end_transaction(trans, root); | ||
969 | iput(inode); | 969 | iput(inode); |
970 | continue; | 970 | continue; |
971 | } | 971 | } |
@@ -988,7 +988,6 @@ void btrfs_orphan_cleanup(struct btrfs_root *root) | |||
988 | printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate); | 988 | printk(KERN_INFO "btrfs: truncated %d orphans\n", nr_truncate); |
989 | 989 | ||
990 | btrfs_free_path(path); | 990 | btrfs_free_path(path); |
991 | btrfs_end_transaction(trans, root); | ||
992 | } | 991 | } |
993 | 992 | ||
994 | void btrfs_read_locked_inode(struct inode *inode) | 993 | void btrfs_read_locked_inode(struct inode *inode) |
@@ -1343,8 +1342,7 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
1343 | u64 mask = root->sectorsize - 1; | 1342 | u64 mask = root->sectorsize - 1; |
1344 | 1343 | ||
1345 | if (root->ref_cows) | 1344 | if (root->ref_cows) |
1346 | btrfs_drop_extent_cache(inode, | 1345 | btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0); |
1347 | new_size & (~mask), (u64)-1); | ||
1348 | path = btrfs_alloc_path(); | 1346 | path = btrfs_alloc_path(); |
1349 | path->reada = -1; | 1347 | path->reada = -1; |
1350 | BUG_ON(!path); | 1348 | BUG_ON(!path); |
@@ -1677,7 +1675,7 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
1677 | hole_start, 0, 0, | 1675 | hole_start, 0, 0, |
1678 | hole_size, 0); | 1676 | hole_size, 0); |
1679 | btrfs_drop_extent_cache(inode, hole_start, | 1677 | btrfs_drop_extent_cache(inode, hole_start, |
1680 | (u64)-1); | 1678 | (u64)-1, 0); |
1681 | btrfs_check_file(root, inode); | 1679 | btrfs_check_file(root, inode); |
1682 | } | 1680 | } |
1683 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | 1681 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); |
@@ -1843,6 +1841,24 @@ static int btrfs_find_actor(struct inode *inode, void *opaque) | |||
1843 | args->root == BTRFS_I(inode)->root); | 1841 | args->root == BTRFS_I(inode)->root); |
1844 | } | 1842 | } |
1845 | 1843 | ||
1844 | struct inode *btrfs_ilookup(struct super_block *s, u64 objectid, | ||
1845 | struct btrfs_root *root, int wait) | ||
1846 | { | ||
1847 | struct inode *inode; | ||
1848 | struct btrfs_iget_args args; | ||
1849 | args.ino = objectid; | ||
1850 | args.root = root; | ||
1851 | |||
1852 | if (wait) { | ||
1853 | inode = ilookup5(s, objectid, btrfs_find_actor, | ||
1854 | (void *)&args); | ||
1855 | } else { | ||
1856 | inode = ilookup5_nowait(s, objectid, btrfs_find_actor, | ||
1857 | (void *)&args); | ||
1858 | } | ||
1859 | return inode; | ||
1860 | } | ||
1861 | |||
1846 | struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid, | 1862 | struct inode *btrfs_iget_locked(struct super_block *s, u64 objectid, |
1847 | struct btrfs_root *root) | 1863 | struct btrfs_root *root) |
1848 | { | 1864 | { |
@@ -3266,7 +3282,7 @@ void btrfs_destroy_inode(struct inode *inode) | |||
3266 | btrfs_put_ordered_extent(ordered); | 3282 | btrfs_put_ordered_extent(ordered); |
3267 | } | 3283 | } |
3268 | } | 3284 | } |
3269 | btrfs_drop_extent_cache(inode, 0, (u64)-1); | 3285 | btrfs_drop_extent_cache(inode, 0, (u64)-1, 0); |
3270 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); | 3286 | kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode)); |
3271 | } | 3287 | } |
3272 | 3288 | ||
@@ -3412,16 +3428,22 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root) | |||
3412 | { | 3428 | { |
3413 | struct list_head *head = &root->fs_info->delalloc_inodes; | 3429 | struct list_head *head = &root->fs_info->delalloc_inodes; |
3414 | struct btrfs_inode *binode; | 3430 | struct btrfs_inode *binode; |
3431 | struct inode *inode; | ||
3415 | unsigned long flags; | 3432 | unsigned long flags; |
3416 | 3433 | ||
3417 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); | 3434 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); |
3418 | while(!list_empty(head)) { | 3435 | while(!list_empty(head)) { |
3419 | binode = list_entry(head->next, struct btrfs_inode, | 3436 | binode = list_entry(head->next, struct btrfs_inode, |
3420 | delalloc_inodes); | 3437 | delalloc_inodes); |
3421 | atomic_inc(&binode->vfs_inode.i_count); | 3438 | inode = igrab(&binode->vfs_inode); |
3439 | if (!inode) | ||
3440 | list_del_init(&binode->delalloc_inodes); | ||
3422 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | 3441 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); |
3423 | filemap_write_and_wait(binode->vfs_inode.i_mapping); | 3442 | if (inode) { |
3424 | iput(&binode->vfs_inode); | 3443 | filemap_write_and_wait(inode->i_mapping); |
3444 | iput(inode); | ||
3445 | } | ||
3446 | cond_resched(); | ||
3425 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); | 3447 | spin_lock_irqsave(&root->fs_info->delalloc_lock, flags); |
3426 | } | 3448 | } |
3427 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); | 3449 | spin_unlock_irqrestore(&root->fs_info->delalloc_lock, flags); |