diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-30 12:05:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-10-30 12:05:48 -0400 |
commit | 925d169f5b86fe57e2f5264ea574cce9a89b719d (patch) | |
tree | 241d3156b427c6398bd3fc5efa9108635d0e189b /fs/btrfs/extent_io.c | |
parent | cdf01dd5443d0befc8c6a32cb2e3d2f568fd2558 (diff) | |
parent | 6418c96107a2b399848bb8cfc6e29f11ca74fb94 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable: (39 commits)
Btrfs: deal with errors from updating the tree log
Btrfs: allow subvol deletion by unprivileged user with -o user_subvol_rm_allowed
Btrfs: make SNAP_DESTROY async
Btrfs: add SNAP_CREATE_ASYNC ioctl
Btrfs: add START_SYNC, WAIT_SYNC ioctls
Btrfs: async transaction commit
Btrfs: fix deadlock in btrfs_commit_transaction
Btrfs: fix lockdep warning on clone ioctl
Btrfs: fix clone ioctl where range is adjacent to extent
Btrfs: fix delalloc checks in clone ioctl
Btrfs: drop unused variable in block_alloc_rsv
Btrfs: cleanup warnings from gcc 4.6 (nonbugs)
Btrfs: Fix variables set but not read (bugs found by gcc 4.6)
Btrfs: Use ERR_CAST helpers
Btrfs: use memdup_user helpers
Btrfs: fix raid code for removing missing drives
Btrfs: Switch the extent buffer rbtree into a radix tree
Btrfs: restructure try_release_extent_buffer()
Btrfs: use the flusher threads for delalloc throttling
Btrfs: tune the chunk allocation to 5% of the FS as metadata
...
Fix up trivial conflicts in fs/btrfs/super.c and fs/fs-writeback.c, and
remove use of INIT_RCU_HEAD in fs/btrfs/extent_io.c (that init macro was
useless and removed in commit 5e8067adfdba: "rcu head remove init")
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 168 |
1 files changed, 83 insertions, 85 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index d74e6af9b53a..eac10e3260a9 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -104,7 +104,7 @@ void extent_io_tree_init(struct extent_io_tree *tree, | |||
104 | struct address_space *mapping, gfp_t mask) | 104 | struct address_space *mapping, gfp_t mask) |
105 | { | 105 | { |
106 | tree->state = RB_ROOT; | 106 | tree->state = RB_ROOT; |
107 | tree->buffer = RB_ROOT; | 107 | INIT_RADIX_TREE(&tree->buffer, GFP_ATOMIC); |
108 | tree->ops = NULL; | 108 | tree->ops = NULL; |
109 | tree->dirty_bytes = 0; | 109 | tree->dirty_bytes = 0; |
110 | spin_lock_init(&tree->lock); | 110 | spin_lock_init(&tree->lock); |
@@ -235,50 +235,6 @@ static inline struct rb_node *tree_search(struct extent_io_tree *tree, | |||
235 | return ret; | 235 | return ret; |
236 | } | 236 | } |
237 | 237 | ||
238 | static struct extent_buffer *buffer_tree_insert(struct extent_io_tree *tree, | ||
239 | u64 offset, struct rb_node *node) | ||
240 | { | ||
241 | struct rb_root *root = &tree->buffer; | ||
242 | struct rb_node **p = &root->rb_node; | ||
243 | struct rb_node *parent = NULL; | ||
244 | struct extent_buffer *eb; | ||
245 | |||
246 | while (*p) { | ||
247 | parent = *p; | ||
248 | eb = rb_entry(parent, struct extent_buffer, rb_node); | ||
249 | |||
250 | if (offset < eb->start) | ||
251 | p = &(*p)->rb_left; | ||
252 | else if (offset > eb->start) | ||
253 | p = &(*p)->rb_right; | ||
254 | else | ||
255 | return eb; | ||
256 | } | ||
257 | |||
258 | rb_link_node(node, parent, p); | ||
259 | rb_insert_color(node, root); | ||
260 | return NULL; | ||
261 | } | ||
262 | |||
263 | static struct extent_buffer *buffer_search(struct extent_io_tree *tree, | ||
264 | u64 offset) | ||
265 | { | ||
266 | struct rb_root *root = &tree->buffer; | ||
267 | struct rb_node *n = root->rb_node; | ||
268 | struct extent_buffer *eb; | ||
269 | |||
270 | while (n) { | ||
271 | eb = rb_entry(n, struct extent_buffer, rb_node); | ||
272 | if (offset < eb->start) | ||
273 | n = n->rb_left; | ||
274 | else if (offset > eb->start) | ||
275 | n = n->rb_right; | ||
276 | else | ||
277 | return eb; | ||
278 | } | ||
279 | return NULL; | ||
280 | } | ||
281 | |||
282 | static void merge_cb(struct extent_io_tree *tree, struct extent_state *new, | 238 | static void merge_cb(struct extent_io_tree *tree, struct extent_state *new, |
283 | struct extent_state *other) | 239 | struct extent_state *other) |
284 | { | 240 | { |
@@ -1901,10 +1857,8 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num, | |||
1901 | struct page *page = bvec->bv_page; | 1857 | struct page *page = bvec->bv_page; |
1902 | struct extent_io_tree *tree = bio->bi_private; | 1858 | struct extent_io_tree *tree = bio->bi_private; |
1903 | u64 start; | 1859 | u64 start; |
1904 | u64 end; | ||
1905 | 1860 | ||
1906 | start = ((u64)page->index << PAGE_CACHE_SHIFT) + bvec->bv_offset; | 1861 | start = ((u64)page->index << PAGE_CACHE_SHIFT) + bvec->bv_offset; |
1907 | end = start + bvec->bv_len - 1; | ||
1908 | 1862 | ||
1909 | bio->bi_private = NULL; | 1863 | bio->bi_private = NULL; |
1910 | 1864 | ||
@@ -2204,7 +2158,6 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2204 | u64 last_byte = i_size_read(inode); | 2158 | u64 last_byte = i_size_read(inode); |
2205 | u64 block_start; | 2159 | u64 block_start; |
2206 | u64 iosize; | 2160 | u64 iosize; |
2207 | u64 unlock_start; | ||
2208 | sector_t sector; | 2161 | sector_t sector; |
2209 | struct extent_state *cached_state = NULL; | 2162 | struct extent_state *cached_state = NULL; |
2210 | struct extent_map *em; | 2163 | struct extent_map *em; |
@@ -2329,7 +2282,6 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2329 | if (tree->ops && tree->ops->writepage_end_io_hook) | 2282 | if (tree->ops && tree->ops->writepage_end_io_hook) |
2330 | tree->ops->writepage_end_io_hook(page, start, | 2283 | tree->ops->writepage_end_io_hook(page, start, |
2331 | page_end, NULL, 1); | 2284 | page_end, NULL, 1); |
2332 | unlock_start = page_end + 1; | ||
2333 | goto done; | 2285 | goto done; |
2334 | } | 2286 | } |
2335 | 2287 | ||
@@ -2340,7 +2292,6 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2340 | if (tree->ops && tree->ops->writepage_end_io_hook) | 2292 | if (tree->ops && tree->ops->writepage_end_io_hook) |
2341 | tree->ops->writepage_end_io_hook(page, cur, | 2293 | tree->ops->writepage_end_io_hook(page, cur, |
2342 | page_end, NULL, 1); | 2294 | page_end, NULL, 1); |
2343 | unlock_start = page_end + 1; | ||
2344 | break; | 2295 | break; |
2345 | } | 2296 | } |
2346 | em = epd->get_extent(inode, page, pg_offset, cur, | 2297 | em = epd->get_extent(inode, page, pg_offset, cur, |
@@ -2387,7 +2338,6 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, | |||
2387 | 2338 | ||
2388 | cur += iosize; | 2339 | cur += iosize; |
2389 | pg_offset += iosize; | 2340 | pg_offset += iosize; |
2390 | unlock_start = cur; | ||
2391 | continue; | 2341 | continue; |
2392 | } | 2342 | } |
2393 | /* leave this out until we have a page_mkwrite call */ | 2343 | /* leave this out until we have a page_mkwrite call */ |
@@ -2473,7 +2423,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, | |||
2473 | pgoff_t index; | 2423 | pgoff_t index; |
2474 | pgoff_t end; /* Inclusive */ | 2424 | pgoff_t end; /* Inclusive */ |
2475 | int scanned = 0; | 2425 | int scanned = 0; |
2476 | int range_whole = 0; | ||
2477 | 2426 | ||
2478 | pagevec_init(&pvec, 0); | 2427 | pagevec_init(&pvec, 0); |
2479 | if (wbc->range_cyclic) { | 2428 | if (wbc->range_cyclic) { |
@@ -2482,8 +2431,6 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, | |||
2482 | } else { | 2431 | } else { |
2483 | index = wbc->range_start >> PAGE_CACHE_SHIFT; | 2432 | index = wbc->range_start >> PAGE_CACHE_SHIFT; |
2484 | end = wbc->range_end >> PAGE_CACHE_SHIFT; | 2433 | end = wbc->range_end >> PAGE_CACHE_SHIFT; |
2485 | if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) | ||
2486 | range_whole = 1; | ||
2487 | scanned = 1; | 2434 | scanned = 1; |
2488 | } | 2435 | } |
2489 | retry: | 2436 | retry: |
@@ -2823,6 +2770,8 @@ int extent_prepare_write(struct extent_io_tree *tree, | |||
2823 | NULL, 1, | 2770 | NULL, 1, |
2824 | end_bio_extent_preparewrite, 0, | 2771 | end_bio_extent_preparewrite, 0, |
2825 | 0, 0); | 2772 | 0, 0); |
2773 | if (ret && !err) | ||
2774 | err = ret; | ||
2826 | iocount++; | 2775 | iocount++; |
2827 | block_start = block_start + iosize; | 2776 | block_start = block_start + iosize; |
2828 | } else { | 2777 | } else { |
@@ -3104,6 +3053,39 @@ static void __free_extent_buffer(struct extent_buffer *eb) | |||
3104 | kmem_cache_free(extent_buffer_cache, eb); | 3053 | kmem_cache_free(extent_buffer_cache, eb); |
3105 | } | 3054 | } |
3106 | 3055 | ||
3056 | /* | ||
3057 | * Helper for releasing extent buffer page. | ||
3058 | */ | ||
3059 | static void btrfs_release_extent_buffer_page(struct extent_buffer *eb, | ||
3060 | unsigned long start_idx) | ||
3061 | { | ||
3062 | unsigned long index; | ||
3063 | struct page *page; | ||
3064 | |||
3065 | if (!eb->first_page) | ||
3066 | return; | ||
3067 | |||
3068 | index = num_extent_pages(eb->start, eb->len); | ||
3069 | if (start_idx >= index) | ||
3070 | return; | ||
3071 | |||
3072 | do { | ||
3073 | index--; | ||
3074 | page = extent_buffer_page(eb, index); | ||
3075 | if (page) | ||
3076 | page_cache_release(page); | ||
3077 | } while (index != start_idx); | ||
3078 | } | ||
3079 | |||
3080 | /* | ||
3081 | * Helper for releasing the extent buffer. | ||
3082 | */ | ||
3083 | static inline void btrfs_release_extent_buffer(struct extent_buffer *eb) | ||
3084 | { | ||
3085 | btrfs_release_extent_buffer_page(eb, 0); | ||
3086 | __free_extent_buffer(eb); | ||
3087 | } | ||
3088 | |||
3107 | struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | 3089 | struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, |
3108 | u64 start, unsigned long len, | 3090 | u64 start, unsigned long len, |
3109 | struct page *page0, | 3091 | struct page *page0, |
@@ -3117,16 +3099,16 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
3117 | struct page *p; | 3099 | struct page *p; |
3118 | struct address_space *mapping = tree->mapping; | 3100 | struct address_space *mapping = tree->mapping; |
3119 | int uptodate = 1; | 3101 | int uptodate = 1; |
3102 | int ret; | ||
3120 | 3103 | ||
3121 | spin_lock(&tree->buffer_lock); | 3104 | rcu_read_lock(); |
3122 | eb = buffer_search(tree, start); | 3105 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); |
3123 | if (eb) { | 3106 | if (eb && atomic_inc_not_zero(&eb->refs)) { |
3124 | atomic_inc(&eb->refs); | 3107 | rcu_read_unlock(); |
3125 | spin_unlock(&tree->buffer_lock); | ||
3126 | mark_page_accessed(eb->first_page); | 3108 | mark_page_accessed(eb->first_page); |
3127 | return eb; | 3109 | return eb; |
3128 | } | 3110 | } |
3129 | spin_unlock(&tree->buffer_lock); | 3111 | rcu_read_unlock(); |
3130 | 3112 | ||
3131 | eb = __alloc_extent_buffer(tree, start, len, mask); | 3113 | eb = __alloc_extent_buffer(tree, start, len, mask); |
3132 | if (!eb) | 3114 | if (!eb) |
@@ -3165,26 +3147,31 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, | |||
3165 | if (uptodate) | 3147 | if (uptodate) |
3166 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); | 3148 | set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); |
3167 | 3149 | ||
3150 | ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); | ||
3151 | if (ret) | ||
3152 | goto free_eb; | ||
3153 | |||
3168 | spin_lock(&tree->buffer_lock); | 3154 | spin_lock(&tree->buffer_lock); |
3169 | exists = buffer_tree_insert(tree, start, &eb->rb_node); | 3155 | ret = radix_tree_insert(&tree->buffer, start >> PAGE_CACHE_SHIFT, eb); |
3170 | if (exists) { | 3156 | if (ret == -EEXIST) { |
3157 | exists = radix_tree_lookup(&tree->buffer, | ||
3158 | start >> PAGE_CACHE_SHIFT); | ||
3171 | /* add one reference for the caller */ | 3159 | /* add one reference for the caller */ |
3172 | atomic_inc(&exists->refs); | 3160 | atomic_inc(&exists->refs); |
3173 | spin_unlock(&tree->buffer_lock); | 3161 | spin_unlock(&tree->buffer_lock); |
3162 | radix_tree_preload_end(); | ||
3174 | goto free_eb; | 3163 | goto free_eb; |
3175 | } | 3164 | } |
3176 | /* add one reference for the tree */ | 3165 | /* add one reference for the tree */ |
3177 | atomic_inc(&eb->refs); | 3166 | atomic_inc(&eb->refs); |
3178 | spin_unlock(&tree->buffer_lock); | 3167 | spin_unlock(&tree->buffer_lock); |
3168 | radix_tree_preload_end(); | ||
3179 | return eb; | 3169 | return eb; |
3180 | 3170 | ||
3181 | free_eb: | 3171 | free_eb: |
3182 | if (!atomic_dec_and_test(&eb->refs)) | 3172 | if (!atomic_dec_and_test(&eb->refs)) |
3183 | return exists; | 3173 | return exists; |
3184 | for (index = 1; index < i; index++) | 3174 | btrfs_release_extent_buffer(eb); |
3185 | page_cache_release(extent_buffer_page(eb, index)); | ||
3186 | page_cache_release(extent_buffer_page(eb, 0)); | ||
3187 | __free_extent_buffer(eb); | ||
3188 | return exists; | 3175 | return exists; |
3189 | } | 3176 | } |
3190 | 3177 | ||
@@ -3194,16 +3181,16 @@ struct extent_buffer *find_extent_buffer(struct extent_io_tree *tree, | |||
3194 | { | 3181 | { |
3195 | struct extent_buffer *eb; | 3182 | struct extent_buffer *eb; |
3196 | 3183 | ||
3197 | spin_lock(&tree->buffer_lock); | 3184 | rcu_read_lock(); |
3198 | eb = buffer_search(tree, start); | 3185 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); |
3199 | if (eb) | 3186 | if (eb && atomic_inc_not_zero(&eb->refs)) { |
3200 | atomic_inc(&eb->refs); | 3187 | rcu_read_unlock(); |
3201 | spin_unlock(&tree->buffer_lock); | ||
3202 | |||
3203 | if (eb) | ||
3204 | mark_page_accessed(eb->first_page); | 3188 | mark_page_accessed(eb->first_page); |
3189 | return eb; | ||
3190 | } | ||
3191 | rcu_read_unlock(); | ||
3205 | 3192 | ||
3206 | return eb; | 3193 | return NULL; |
3207 | } | 3194 | } |
3208 | 3195 | ||
3209 | void free_extent_buffer(struct extent_buffer *eb) | 3196 | void free_extent_buffer(struct extent_buffer *eb) |
@@ -3833,34 +3820,45 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset, | |||
3833 | } | 3820 | } |
3834 | } | 3821 | } |
3835 | 3822 | ||
3823 | static inline void btrfs_release_extent_buffer_rcu(struct rcu_head *head) | ||
3824 | { | ||
3825 | struct extent_buffer *eb = | ||
3826 | container_of(head, struct extent_buffer, rcu_head); | ||
3827 | |||
3828 | btrfs_release_extent_buffer(eb); | ||
3829 | } | ||
3830 | |||
3836 | int try_release_extent_buffer(struct extent_io_tree *tree, struct page *page) | 3831 | int try_release_extent_buffer(struct extent_io_tree *tree, struct page *page) |
3837 | { | 3832 | { |
3838 | u64 start = page_offset(page); | 3833 | u64 start = page_offset(page); |
3839 | struct extent_buffer *eb; | 3834 | struct extent_buffer *eb; |
3840 | int ret = 1; | 3835 | int ret = 1; |
3841 | unsigned long i; | ||
3842 | unsigned long num_pages; | ||
3843 | 3836 | ||
3844 | spin_lock(&tree->buffer_lock); | 3837 | spin_lock(&tree->buffer_lock); |
3845 | eb = buffer_search(tree, start); | 3838 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); |
3846 | if (!eb) | 3839 | if (!eb) |
3847 | goto out; | 3840 | goto out; |
3848 | 3841 | ||
3849 | if (atomic_read(&eb->refs) > 1) { | 3842 | if (test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { |
3850 | ret = 0; | 3843 | ret = 0; |
3851 | goto out; | 3844 | goto out; |
3852 | } | 3845 | } |
3853 | if (test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { | 3846 | |
3847 | /* | ||
3848 | * set @eb->refs to 0 if it is already 1, and then release the @eb. | ||
3849 | * Or go back. | ||
3850 | */ | ||
3851 | if (atomic_cmpxchg(&eb->refs, 1, 0) != 1) { | ||
3854 | ret = 0; | 3852 | ret = 0; |
3855 | goto out; | 3853 | goto out; |
3856 | } | 3854 | } |
3857 | /* at this point we can safely release the extent buffer */ | 3855 | |
3858 | num_pages = num_extent_pages(eb->start, eb->len); | 3856 | radix_tree_delete(&tree->buffer, start >> PAGE_CACHE_SHIFT); |
3859 | for (i = 0; i < num_pages; i++) | ||
3860 | page_cache_release(extent_buffer_page(eb, i)); | ||
3861 | rb_erase(&eb->rb_node, &tree->buffer); | ||
3862 | __free_extent_buffer(eb); | ||
3863 | out: | 3857 | out: |
3864 | spin_unlock(&tree->buffer_lock); | 3858 | spin_unlock(&tree->buffer_lock); |
3859 | |||
3860 | /* at this point we can safely release the extent buffer */ | ||
3861 | if (atomic_read(&eb->refs) == 0) | ||
3862 | call_rcu(&eb->rcu_head, btrfs_release_extent_buffer_rcu); | ||
3865 | return ret; | 3863 | return ret; |
3866 | } | 3864 | } |