diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-07-22 11:18:08 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:05 -0400 |
commit | a61e6f29dc7c9d56a776a518eed92bbc61848263 (patch) | |
tree | 6856ad3e5822eacfc2ac94693b6023ef81567fd2 /fs | |
parent | 6af118ce51b52ceda357c671550c79628b9c4a65 (diff) |
Btrfs: Use a mutex in the extent buffer for tree block locking
This replaces the use of the page cache lock bit for locking, which wasn't
suitable for block size < page size and couldn't be used recursively.
The mutexes alone don't fix either problem, but they are the first step.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 7 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 9 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/locking.c | 13 |
4 files changed, 17 insertions, 13 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index ccd49322f793..c51cd11de206 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -1451,7 +1451,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | |||
1451 | struct extent_buffer *buf; | 1451 | struct extent_buffer *buf; |
1452 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); | 1452 | buf = btrfs_find_tree_block(root, bytenr, num_bytes); |
1453 | if (buf) { | 1453 | if (buf) { |
1454 | if (!btrfs_try_tree_lock(buf) && | 1454 | if (btrfs_try_tree_lock(buf) && |
1455 | btrfs_buffer_uptodate(buf, 0)) { | 1455 | btrfs_buffer_uptodate(buf, 0)) { |
1456 | u64 transid = | 1456 | u64 transid = |
1457 | root->fs_info->running_transaction->transid; | 1457 | root->fs_info->running_transaction->transid; |
@@ -3345,11 +3345,6 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
3345 | set_state_private(block_group_cache, found_key.objectid, | 3345 | set_state_private(block_group_cache, found_key.objectid, |
3346 | (unsigned long)cache); | 3346 | (unsigned long)cache); |
3347 | 3347 | ||
3348 | /* hack for now */ | ||
3349 | if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) { | ||
3350 | cache_block_group(root->fs_info->extent_root, | ||
3351 | cache); | ||
3352 | } | ||
3353 | if (key.objectid >= | 3348 | if (key.objectid >= |
3354 | btrfs_super_total_bytes(&info->super_copy)) | 3349 | btrfs_super_total_bytes(&info->super_copy)) |
3355 | break; | 3350 | break; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 32bb4ed3723d..7380449cb5b3 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -2690,6 +2690,7 @@ static struct extent_buffer *__alloc_extent_buffer(struct extent_io_tree *tree, | |||
2690 | eb = kmem_cache_zalloc(extent_buffer_cache, mask); | 2690 | eb = kmem_cache_zalloc(extent_buffer_cache, mask); |
2691 | eb->start = start; | 2691 | eb->start = start; |
2692 | eb->len = len; | 2692 | eb->len = len; |
2693 | mutex_init(&eb->mutex); | ||
2693 | spin_lock_irqsave(&leak_lock, flags); | 2694 | spin_lock_irqsave(&leak_lock, flags); |
2694 | list_add(&eb->leak_list, &buffers); | 2695 | list_add(&eb->leak_list, &buffers); |
2695 | spin_unlock_irqrestore(&leak_lock, flags); | 2696 | spin_unlock_irqrestore(&leak_lock, flags); |
@@ -2837,6 +2838,7 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2837 | 2838 | ||
2838 | for (i = 0; i < num_pages; i++) { | 2839 | for (i = 0; i < num_pages; i++) { |
2839 | page = extent_buffer_page(eb, i); | 2840 | page = extent_buffer_page(eb, i); |
2841 | lock_page(page); | ||
2840 | if (i == 0) | 2842 | if (i == 0) |
2841 | set_page_extent_head(page, eb->len); | 2843 | set_page_extent_head(page, eb->len); |
2842 | else | 2844 | else |
@@ -2854,6 +2856,7 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2854 | end = start + PAGE_CACHE_SIZE - 1; | 2856 | end = start + PAGE_CACHE_SIZE - 1; |
2855 | if (test_range_bit(tree, start, end, | 2857 | if (test_range_bit(tree, start, end, |
2856 | EXTENT_DIRTY, 0)) { | 2858 | EXTENT_DIRTY, 0)) { |
2859 | unlock_page(page); | ||
2857 | continue; | 2860 | continue; |
2858 | } | 2861 | } |
2859 | } | 2862 | } |
@@ -2865,6 +2868,7 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2865 | PAGECACHE_TAG_DIRTY); | 2868 | PAGECACHE_TAG_DIRTY); |
2866 | } | 2869 | } |
2867 | read_unlock_irq(&page->mapping->tree_lock); | 2870 | read_unlock_irq(&page->mapping->tree_lock); |
2871 | unlock_page(page); | ||
2868 | } | 2872 | } |
2869 | return 0; | 2873 | return 0; |
2870 | } | 2874 | } |
@@ -2893,12 +2897,17 @@ int set_extent_buffer_dirty(struct extent_io_tree *tree, | |||
2893 | * on us if the page isn't already dirty. | 2897 | * on us if the page isn't already dirty. |
2894 | */ | 2898 | */ |
2895 | if (i == 0) { | 2899 | if (i == 0) { |
2900 | lock_page(page); | ||
2896 | set_page_extent_head(page, eb->len); | 2901 | set_page_extent_head(page, eb->len); |
2897 | } else if (PagePrivate(page) && | 2902 | } else if (PagePrivate(page) && |
2898 | page->private != EXTENT_PAGE_PRIVATE) { | 2903 | page->private != EXTENT_PAGE_PRIVATE) { |
2904 | lock_page(page); | ||
2899 | set_page_extent_mapped(page); | 2905 | set_page_extent_mapped(page); |
2906 | unlock_page(page); | ||
2900 | } | 2907 | } |
2901 | __set_page_dirty_nobuffers(extent_buffer_page(eb, i)); | 2908 | __set_page_dirty_nobuffers(extent_buffer_page(eb, i)); |
2909 | if (i == 0) | ||
2910 | unlock_page(page); | ||
2902 | } | 2911 | } |
2903 | return set_extent_dirty(tree, eb->start, | 2912 | return set_extent_dirty(tree, eb->start, |
2904 | eb->start + eb->len - 1, GFP_NOFS); | 2913 | eb->start + eb->len - 1, GFP_NOFS); |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index dd367617d780..6c03e6a19938 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -90,6 +90,7 @@ struct extent_buffer { | |||
90 | int flags; | 90 | int flags; |
91 | struct list_head leak_list; | 91 | struct list_head leak_list; |
92 | struct rb_node rb_node; | 92 | struct rb_node rb_node; |
93 | struct mutex mutex; | ||
93 | }; | 94 | }; |
94 | 95 | ||
95 | struct extent_map_tree; | 96 | struct extent_map_tree; |
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c index 058a506a0dd8..01a9ac2be3f7 100644 --- a/fs/btrfs/locking.c +++ b/fs/btrfs/locking.c | |||
@@ -29,32 +29,31 @@ int btrfs_tree_lock(struct extent_buffer *eb) | |||
29 | { | 29 | { |
30 | int i; | 30 | int i; |
31 | 31 | ||
32 | if (!TestSetPageLocked(eb->first_page)) | 32 | if (mutex_trylock(&eb->mutex)) |
33 | return 0; | 33 | return 0; |
34 | for (i = 0; i < 512; i++) { | 34 | for (i = 0; i < 512; i++) { |
35 | cpu_relax(); | 35 | cpu_relax(); |
36 | if (!TestSetPageLocked(eb->first_page)) | 36 | if (mutex_trylock(&eb->mutex)) |
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | cpu_relax(); | 39 | cpu_relax(); |
40 | lock_page(eb->first_page); | 40 | mutex_lock(&eb->mutex); |
41 | return 0; | 41 | return 0; |
42 | } | 42 | } |
43 | 43 | ||
44 | int btrfs_try_tree_lock(struct extent_buffer *eb) | 44 | int btrfs_try_tree_lock(struct extent_buffer *eb) |
45 | { | 45 | { |
46 | return TestSetPageLocked(eb->first_page); | 46 | return mutex_trylock(&eb->mutex); |
47 | } | 47 | } |
48 | 48 | ||
49 | int btrfs_tree_unlock(struct extent_buffer *eb) | 49 | int btrfs_tree_unlock(struct extent_buffer *eb) |
50 | { | 50 | { |
51 | WARN_ON(!PageLocked(eb->first_page)); | 51 | mutex_unlock(&eb->mutex); |
52 | unlock_page(eb->first_page); | ||
53 | return 0; | 52 | return 0; |
54 | } | 53 | } |
55 | 54 | ||
56 | int btrfs_tree_locked(struct extent_buffer *eb) | 55 | int btrfs_tree_locked(struct extent_buffer *eb) |
57 | { | 56 | { |
58 | return PageLocked(eb->first_page); | 57 | return mutex_is_locked(&eb->mutex); |
59 | } | 58 | } |
60 | 59 | ||