diff options
-rw-r--r-- | fs/btrfs/ctree.h | 2 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 20 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 1 | ||||
-rw-r--r-- | fs/btrfs/extent_map.c | 9 | ||||
-rw-r--r-- | fs/btrfs/extent_map.h | 1 | ||||
-rw-r--r-- | fs/btrfs/file.c | 15 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 54 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.c | 115 | ||||
-rw-r--r-- | fs/btrfs/ordered-data.h | 4 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 |
10 files changed, 140 insertions, 83 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 96ab2797c09a..f8fccdac3055 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -1590,6 +1590,8 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | |||
1590 | struct btrfs_root *root, struct btrfs_path *path, | 1590 | struct btrfs_root *root, struct btrfs_path *path, |
1591 | u64 isize); | 1591 | u64 isize); |
1592 | /* inode.c */ | 1592 | /* inode.c */ |
1593 | int btrfs_writepages(struct address_space *mapping, | ||
1594 | struct writeback_control *wbc); | ||
1593 | int btrfs_create_subvol_root(struct btrfs_root *new_root, | 1595 | int btrfs_create_subvol_root(struct btrfs_root *new_root, |
1594 | struct btrfs_trans_handle *trans, u64 new_dirid, | 1596 | struct btrfs_trans_handle *trans, u64 new_dirid, |
1595 | struct btrfs_block_group_cache *block_group); | 1597 | struct btrfs_block_group_cache *block_group); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 7380449cb5b3..9965993748d0 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -97,7 +97,6 @@ void extent_io_tree_init(struct extent_io_tree *tree, | |||
97 | spin_lock_init(&tree->lock); | 97 | spin_lock_init(&tree->lock); |
98 | spin_lock_init(&tree->buffer_lock); | 98 | spin_lock_init(&tree->buffer_lock); |
99 | tree->mapping = mapping; | 99 | tree->mapping = mapping; |
100 | tree->last = NULL; | ||
101 | } | 100 | } |
102 | EXPORT_SYMBOL(extent_io_tree_init); | 101 | EXPORT_SYMBOL(extent_io_tree_init); |
103 | 102 | ||
@@ -173,12 +172,6 @@ static struct rb_node *__etree_search(struct extent_io_tree *tree, u64 offset, | |||
173 | struct tree_entry *entry; | 172 | struct tree_entry *entry; |
174 | struct tree_entry *prev_entry = NULL; | 173 | struct tree_entry *prev_entry = NULL; |
175 | 174 | ||
176 | if (tree->last) { | ||
177 | struct extent_state *state; | ||
178 | state = tree->last; | ||
179 | if (state->start <= offset && offset <= state->end) | ||
180 | return &tree->last->rb_node; | ||
181 | } | ||
182 | while(n) { | 175 | while(n) { |
183 | entry = rb_entry(n, struct tree_entry, rb_node); | 176 | entry = rb_entry(n, struct tree_entry, rb_node); |
184 | prev = n; | 177 | prev = n; |
@@ -189,7 +182,6 @@ static struct rb_node *__etree_search(struct extent_io_tree *tree, u64 offset, | |||
189 | else if (offset > entry->end) | 182 | else if (offset > entry->end) |
190 | n = n->rb_right; | 183 | n = n->rb_right; |
191 | else { | 184 | else { |
192 | tree->last = rb_entry(n, struct extent_state, rb_node); | ||
193 | return n; | 185 | return n; |
194 | } | 186 | } |
195 | } | 187 | } |
@@ -223,10 +215,6 @@ static inline struct rb_node *tree_search(struct extent_io_tree *tree, | |||
223 | 215 | ||
224 | ret = __etree_search(tree, offset, &prev, NULL); | 216 | ret = __etree_search(tree, offset, &prev, NULL); |
225 | if (!ret) { | 217 | if (!ret) { |
226 | if (prev) { | ||
227 | tree->last = rb_entry(prev, struct extent_state, | ||
228 | rb_node); | ||
229 | } | ||
230 | return prev; | 218 | return prev; |
231 | } | 219 | } |
232 | return ret; | 220 | return ret; |
@@ -301,8 +289,6 @@ static int merge_state(struct extent_io_tree *tree, | |||
301 | other->state == state->state) { | 289 | other->state == state->state) { |
302 | state->start = other->start; | 290 | state->start = other->start; |
303 | other->tree = NULL; | 291 | other->tree = NULL; |
304 | if (tree->last == other) | ||
305 | tree->last = state; | ||
306 | rb_erase(&other->rb_node, &tree->state); | 292 | rb_erase(&other->rb_node, &tree->state); |
307 | free_extent_state(other); | 293 | free_extent_state(other); |
308 | } | 294 | } |
@@ -314,8 +300,6 @@ static int merge_state(struct extent_io_tree *tree, | |||
314 | other->state == state->state) { | 300 | other->state == state->state) { |
315 | other->start = state->start; | 301 | other->start = state->start; |
316 | state->tree = NULL; | 302 | state->tree = NULL; |
317 | if (tree->last == state) | ||
318 | tree->last = other; | ||
319 | rb_erase(&state->rb_node, &tree->state); | 303 | rb_erase(&state->rb_node, &tree->state); |
320 | free_extent_state(state); | 304 | free_extent_state(state); |
321 | } | 305 | } |
@@ -378,7 +362,6 @@ static int insert_state(struct extent_io_tree *tree, | |||
378 | return -EEXIST; | 362 | return -EEXIST; |
379 | } | 363 | } |
380 | state->tree = tree; | 364 | state->tree = tree; |
381 | tree->last = state; | ||
382 | merge_state(tree, state); | 365 | merge_state(tree, state); |
383 | return 0; | 366 | return 0; |
384 | } | 367 | } |
@@ -444,9 +427,6 @@ static int clear_state_bit(struct extent_io_tree *tree, | |||
444 | if (delete || state->state == 0) { | 427 | if (delete || state->state == 0) { |
445 | if (state->tree) { | 428 | if (state->tree) { |
446 | clear_state_cb(tree, state, state->state); | 429 | clear_state_cb(tree, state, state->state); |
447 | if (tree->last == state) { | ||
448 | tree->last = extent_state_next(state); | ||
449 | } | ||
450 | rb_erase(&state->rb_node, &tree->state); | 430 | rb_erase(&state->rb_node, &tree->state); |
451 | state->tree = NULL; | 431 | state->tree = NULL; |
452 | free_extent_state(state); | 432 | free_extent_state(state); |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 6c03e6a19938..315cfceae312 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -60,7 +60,6 @@ struct extent_io_tree { | |||
60 | spinlock_t lock; | 60 | spinlock_t lock; |
61 | spinlock_t buffer_lock; | 61 | spinlock_t buffer_lock; |
62 | struct extent_io_ops *ops; | 62 | struct extent_io_ops *ops; |
63 | struct extent_state *last; | ||
64 | }; | 63 | }; |
65 | 64 | ||
66 | struct extent_state { | 65 | struct extent_state { |
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 71b1ac155355..8a502ee2f231 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c | |||
@@ -42,7 +42,6 @@ void extent_map_exit(void) | |||
42 | void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask) | 42 | void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask) |
43 | { | 43 | { |
44 | tree->map.rb_node = NULL; | 44 | tree->map.rb_node = NULL; |
45 | tree->last = NULL; | ||
46 | spin_lock_init(&tree->lock); | 45 | spin_lock_init(&tree->lock); |
47 | } | 46 | } |
48 | EXPORT_SYMBOL(extent_map_tree_init); | 47 | EXPORT_SYMBOL(extent_map_tree_init); |
@@ -239,7 +238,6 @@ int add_extent_mapping(struct extent_map_tree *tree, | |||
239 | merge->in_tree = 0; | 238 | merge->in_tree = 0; |
240 | free_extent_map(merge); | 239 | free_extent_map(merge); |
241 | } | 240 | } |
242 | tree->last = em; | ||
243 | out: | 241 | out: |
244 | return ret; | 242 | return ret; |
245 | } | 243 | } |
@@ -273,10 +271,6 @@ struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, | |||
273 | u64 end = range_end(start, len); | 271 | u64 end = range_end(start, len); |
274 | 272 | ||
275 | BUG_ON(spin_trylock(&tree->lock)); | 273 | BUG_ON(spin_trylock(&tree->lock)); |
276 | em = tree->last; | ||
277 | if (em && end > em->start && start < extent_map_end(em)) | ||
278 | goto found; | ||
279 | |||
280 | rb_node = __tree_search(&tree->map, start, &prev, &next); | 274 | rb_node = __tree_search(&tree->map, start, &prev, &next); |
281 | if (!rb_node && prev) { | 275 | if (!rb_node && prev) { |
282 | em = rb_entry(prev, struct extent_map, rb_node); | 276 | em = rb_entry(prev, struct extent_map, rb_node); |
@@ -305,7 +299,6 @@ struct extent_map *lookup_extent_mapping(struct extent_map_tree *tree, | |||
305 | 299 | ||
306 | found: | 300 | found: |
307 | atomic_inc(&em->refs); | 301 | atomic_inc(&em->refs); |
308 | tree->last = em; | ||
309 | out: | 302 | out: |
310 | return em; | 303 | return em; |
311 | } | 304 | } |
@@ -327,8 +320,6 @@ int remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em) | |||
327 | BUG_ON(spin_trylock(&tree->lock)); | 320 | BUG_ON(spin_trylock(&tree->lock)); |
328 | rb_erase(&em->rb_node, &tree->map); | 321 | rb_erase(&em->rb_node, &tree->map); |
329 | em->in_tree = 0; | 322 | em->in_tree = 0; |
330 | if (tree->last == em) | ||
331 | tree->last = NULL; | ||
332 | return ret; | 323 | return ret; |
333 | } | 324 | } |
334 | EXPORT_SYMBOL(remove_extent_mapping); | 325 | EXPORT_SYMBOL(remove_extent_mapping); |
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index a3978ec27846..26ac6fe0b268 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h | |||
@@ -26,7 +26,6 @@ struct extent_map { | |||
26 | 26 | ||
27 | struct extent_map_tree { | 27 | struct extent_map_tree { |
28 | struct rb_root map; | 28 | struct rb_root map; |
29 | struct extent_map *last; | ||
30 | spinlock_t lock; | 29 | spinlock_t lock; |
31 | }; | 30 | }; |
32 | 31 | ||
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 591a30208acd..e5ffb66ad320 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -381,14 +381,13 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end) | |||
381 | break; | 381 | break; |
382 | } | 382 | } |
383 | if (test_bit(EXTENT_FLAG_PINNED, &em->flags)) { | 383 | if (test_bit(EXTENT_FLAG_PINNED, &em->flags)) { |
384 | start = em->start + em->len; | 384 | printk(KERN_CRIT "inode %lu trying to drop pinned " |
385 | free_extent_map(em); | 385 | "extent start %llu end %llu, em [%llu %llu]\n", |
386 | spin_unlock(&em_tree->lock); | 386 | inode->i_ino, |
387 | if (start < end) { | 387 | (unsigned long long)start, |
388 | len = end - start + 1; | 388 | (unsigned long long)end, |
389 | continue; | 389 | (unsigned long long)em->start, |
390 | } | 390 | (unsigned long long)em->len); |
391 | break; | ||
392 | } | 391 | } |
393 | remove_extent_mapping(em_tree, em); | 392 | remove_extent_mapping(em_tree, em); |
394 | 393 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 60852ada658e..3da12a4d913d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -485,7 +485,7 @@ int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end) | |||
485 | fixup = kzalloc(sizeof(*fixup), GFP_NOFS); | 485 | fixup = kzalloc(sizeof(*fixup), GFP_NOFS); |
486 | if (!fixup) | 486 | if (!fixup) |
487 | return -EAGAIN; | 487 | return -EAGAIN; |
488 | printk("queueing worker to fixup page %lu %Lu\n", inode->i_ino, page_offset(page)); | 488 | |
489 | SetPageChecked(page); | 489 | SetPageChecked(page); |
490 | page_cache_get(page); | 490 | page_cache_get(page); |
491 | fixup->work.func = btrfs_writepage_fixup_worker; | 491 | fixup->work.func = btrfs_writepage_fixup_worker; |
@@ -502,11 +502,13 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
502 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 502 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
503 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 503 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
504 | struct extent_map *em; | 504 | struct extent_map *em; |
505 | struct extent_map *em_orig; | ||
505 | u64 alloc_hint = 0; | 506 | u64 alloc_hint = 0; |
506 | u64 clear_start; | 507 | u64 clear_start; |
507 | u64 clear_end; | 508 | u64 clear_end; |
508 | struct list_head list; | 509 | struct list_head list; |
509 | struct btrfs_key ins; | 510 | struct btrfs_key ins; |
511 | struct rb_node *rb; | ||
510 | int ret; | 512 | int ret; |
511 | 513 | ||
512 | ret = btrfs_dec_test_ordered_pending(inode, start, end - start + 1); | 514 | ret = btrfs_dec_test_ordered_pending(inode, start, end - start + 1); |
@@ -535,6 +537,22 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
535 | 537 | ||
536 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | 538 | mutex_lock(&BTRFS_I(inode)->extent_mutex); |
537 | 539 | ||
540 | spin_lock(&em_tree->lock); | ||
541 | clear_start = ordered_extent->file_offset; | ||
542 | clear_end = ordered_extent->file_offset + ordered_extent->len; | ||
543 | em = lookup_extent_mapping(em_tree, clear_start, | ||
544 | ordered_extent->len); | ||
545 | em_orig = em; | ||
546 | while(em && clear_start < extent_map_end(em) && clear_end > em->start) { | ||
547 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); | ||
548 | rb = rb_next(&em->rb_node); | ||
549 | if (!rb) | ||
550 | break; | ||
551 | em = rb_entry(rb, struct extent_map, rb_node); | ||
552 | } | ||
553 | free_extent_map(em_orig); | ||
554 | spin_unlock(&em_tree->lock); | ||
555 | |||
538 | ret = btrfs_drop_extents(trans, root, inode, | 556 | ret = btrfs_drop_extents(trans, root, inode, |
539 | ordered_extent->file_offset, | 557 | ordered_extent->file_offset, |
540 | ordered_extent->file_offset + | 558 | ordered_extent->file_offset + |
@@ -548,22 +566,6 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
548 | ordered_extent->len, 0); | 566 | ordered_extent->len, 0); |
549 | BUG_ON(ret); | 567 | BUG_ON(ret); |
550 | 568 | ||
551 | spin_lock(&em_tree->lock); | ||
552 | clear_start = ordered_extent->file_offset; | ||
553 | clear_end = ordered_extent->file_offset + ordered_extent->len; | ||
554 | while(clear_start < clear_end) { | ||
555 | em = lookup_extent_mapping(em_tree, clear_start, | ||
556 | clear_end - clear_start); | ||
557 | if (em) { | ||
558 | clear_bit(EXTENT_FLAG_PINNED, &em->flags); | ||
559 | clear_start = em->start + em->len; | ||
560 | free_extent_map(em); | ||
561 | } else { | ||
562 | break; | ||
563 | } | ||
564 | } | ||
565 | spin_unlock(&em_tree->lock); | ||
566 | |||
567 | btrfs_drop_extent_cache(inode, ordered_extent->file_offset, | 569 | btrfs_drop_extent_cache(inode, ordered_extent->file_offset, |
568 | ordered_extent->file_offset + | 570 | ordered_extent->file_offset + |
569 | ordered_extent->len - 1); | 571 | ordered_extent->len - 1); |
@@ -2318,7 +2320,7 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
2318 | u64 extent_end = 0; | 2320 | u64 extent_end = 0; |
2319 | u64 objectid = inode->i_ino; | 2321 | u64 objectid = inode->i_ino; |
2320 | u32 found_type; | 2322 | u32 found_type; |
2321 | struct btrfs_path *path; | 2323 | struct btrfs_path *path = NULL; |
2322 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2324 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2323 | struct btrfs_file_extent_item *item; | 2325 | struct btrfs_file_extent_item *item; |
2324 | struct extent_buffer *leaf; | 2326 | struct extent_buffer *leaf; |
@@ -2328,9 +2330,6 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
2328 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 2330 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
2329 | struct btrfs_trans_handle *trans = NULL; | 2331 | struct btrfs_trans_handle *trans = NULL; |
2330 | 2332 | ||
2331 | path = btrfs_alloc_path(); | ||
2332 | BUG_ON(!path); | ||
2333 | |||
2334 | again: | 2333 | again: |
2335 | spin_lock(&em_tree->lock); | 2334 | spin_lock(&em_tree->lock); |
2336 | em = lookup_extent_mapping(em_tree, start, len); | 2335 | em = lookup_extent_mapping(em_tree, start, len); |
@@ -2354,6 +2353,12 @@ again: | |||
2354 | em->bdev = root->fs_info->fs_devices->latest_bdev; | 2353 | em->bdev = root->fs_info->fs_devices->latest_bdev; |
2355 | em->start = EXTENT_MAP_HOLE; | 2354 | em->start = EXTENT_MAP_HOLE; |
2356 | em->len = (u64)-1; | 2355 | em->len = (u64)-1; |
2356 | |||
2357 | if (!path) { | ||
2358 | path = btrfs_alloc_path(); | ||
2359 | BUG_ON(!path); | ||
2360 | } | ||
2361 | |||
2357 | ret = btrfs_lookup_file_extent(trans, root, path, | 2362 | ret = btrfs_lookup_file_extent(trans, root, path, |
2358 | objectid, start, trans != NULL); | 2363 | objectid, start, trans != NULL); |
2359 | if (ret < 0) { | 2364 | if (ret < 0) { |
@@ -2530,7 +2535,8 @@ insert: | |||
2530 | } | 2535 | } |
2531 | spin_unlock(&em_tree->lock); | 2536 | spin_unlock(&em_tree->lock); |
2532 | out: | 2537 | out: |
2533 | btrfs_free_path(path); | 2538 | if (path) |
2539 | btrfs_free_path(path); | ||
2534 | if (trans) { | 2540 | if (trans) { |
2535 | ret = btrfs_end_transaction(trans, root); | 2541 | ret = btrfs_end_transaction(trans, root); |
2536 | if (!err) { | 2542 | if (!err) { |
@@ -2643,8 +2649,8 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc) | |||
2643 | return extent_write_full_page(tree, page, btrfs_get_extent, wbc); | 2649 | return extent_write_full_page(tree, page, btrfs_get_extent, wbc); |
2644 | } | 2650 | } |
2645 | 2651 | ||
2646 | static int btrfs_writepages(struct address_space *mapping, | 2652 | int btrfs_writepages(struct address_space *mapping, |
2647 | struct writeback_control *wbc) | 2653 | struct writeback_control *wbc) |
2648 | { | 2654 | { |
2649 | struct extent_io_tree *tree; | 2655 | struct extent_io_tree *tree; |
2650 | tree = &BTRFS_I(mapping->host)->io_tree; | 2656 | tree = &BTRFS_I(mapping->host)->io_tree; |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 0d87795fdd8f..830dbaea6853 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/gfp.h> | 19 | #include <linux/gfp.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
22 | #include <linux/writeback.h> | ||
23 | #include <linux/pagevec.h> | ||
22 | #include "ctree.h" | 24 | #include "ctree.h" |
23 | #include "transaction.h" | 25 | #include "transaction.h" |
24 | #include "btrfs_inode.h" | 26 | #include "btrfs_inode.h" |
@@ -307,12 +309,7 @@ void btrfs_start_ordered_extent(struct inode *inode, | |||
307 | * start IO on any dirty ones so the wait doesn't stall waiting | 309 | * start IO on any dirty ones so the wait doesn't stall waiting |
308 | * for pdflush to find them | 310 | * for pdflush to find them |
309 | */ | 311 | */ |
310 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) | 312 | btrfs_fdatawrite_range(inode->i_mapping, start, end, WB_SYNC_NONE); |
311 | do_sync_file_range(file, start, end, SYNC_FILE_RANGE_WRITE); | ||
312 | #else | ||
313 | do_sync_mapping_range(inode->i_mapping, start, end, | ||
314 | SYNC_FILE_RANGE_WRITE); | ||
315 | #endif | ||
316 | if (wait) | 313 | if (wait) |
317 | wait_event(entry->wait, test_bit(BTRFS_ORDERED_COMPLETE, | 314 | wait_event(entry->wait, test_bit(BTRFS_ORDERED_COMPLETE, |
318 | &entry->flags)); | 315 | &entry->flags)); |
@@ -327,28 +324,26 @@ void btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len) | |||
327 | u64 orig_end; | 324 | u64 orig_end; |
328 | u64 wait_end; | 325 | u64 wait_end; |
329 | struct btrfs_ordered_extent *ordered; | 326 | struct btrfs_ordered_extent *ordered; |
330 | u64 mask = BTRFS_I(inode)->root->sectorsize - 1; | ||
331 | 327 | ||
332 | if (start + len < start) { | 328 | if (start + len < start) { |
333 | wait_end = (inode->i_size + mask) & ~mask; | 329 | orig_end = INT_LIMIT(loff_t); |
334 | orig_end = (u64)-1; | ||
335 | } else { | 330 | } else { |
336 | orig_end = start + len - 1; | 331 | orig_end = start + len - 1; |
337 | wait_end = orig_end; | 332 | if (orig_end > INT_LIMIT(loff_t)) |
333 | orig_end = INT_LIMIT(loff_t); | ||
338 | } | 334 | } |
335 | wait_end = orig_end; | ||
339 | again: | 336 | again: |
340 | /* start IO across the range first to instantiate any delalloc | 337 | /* start IO across the range first to instantiate any delalloc |
341 | * extents | 338 | * extents |
342 | */ | 339 | */ |
343 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) | 340 | btrfs_fdatawrite_range(inode->i_mapping, start, orig_end, WB_SYNC_NONE); |
344 | do_sync_file_range(file, start, wait_end, SYNC_FILE_RANGE_WRITE); | 341 | |
345 | #else | 342 | btrfs_wait_on_page_writeback_range(inode->i_mapping, |
346 | do_sync_mapping_range(inode->i_mapping, start, wait_end, | 343 | start >> PAGE_CACHE_SHIFT, |
347 | SYNC_FILE_RANGE_WRITE); | 344 | orig_end >> PAGE_CACHE_SHIFT); |
348 | #endif | ||
349 | end = orig_end; | ||
350 | wait_on_extent_writeback(&BTRFS_I(inode)->io_tree, start, orig_end); | ||
351 | 345 | ||
346 | end = orig_end; | ||
352 | while(1) { | 347 | while(1) { |
353 | ordered = btrfs_lookup_first_ordered_extent(inode, end); | 348 | ordered = btrfs_lookup_first_ordered_extent(inode, end); |
354 | if (!ordered) { | 349 | if (!ordered) { |
@@ -565,3 +560,87 @@ out: | |||
565 | return ret; | 560 | return ret; |
566 | } | 561 | } |
567 | 562 | ||
563 | |||
564 | /** | ||
565 | * taken from mm/filemap.c because it isn't exported | ||
566 | * | ||
567 | * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range | ||
568 | * @mapping: address space structure to write | ||
569 | * @start: offset in bytes where the range starts | ||
570 | * @end: offset in bytes where the range ends (inclusive) | ||
571 | * @sync_mode: enable synchronous operation | ||
572 | * | ||
573 | * Start writeback against all of a mapping's dirty pages that lie | ||
574 | * within the byte offsets <start, end> inclusive. | ||
575 | * | ||
576 | * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as | ||
577 | * opposed to a regular memory cleansing writeback. The difference between | ||
578 | * these two operations is that if a dirty page/buffer is encountered, it must | ||
579 | * be waited upon, and not just skipped over. | ||
580 | */ | ||
581 | int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start, | ||
582 | loff_t end, int sync_mode) | ||
583 | { | ||
584 | struct writeback_control wbc = { | ||
585 | .sync_mode = sync_mode, | ||
586 | .nr_to_write = mapping->nrpages * 2, | ||
587 | .range_start = start, | ||
588 | .range_end = end, | ||
589 | .for_writepages = 1, | ||
590 | }; | ||
591 | return btrfs_writepages(mapping, &wbc); | ||
592 | } | ||
593 | |||
594 | /** | ||
595 | * taken from mm/filemap.c because it isn't exported | ||
596 | * | ||
597 | * wait_on_page_writeback_range - wait for writeback to complete | ||
598 | * @mapping: target address_space | ||
599 | * @start: beginning page index | ||
600 | * @end: ending page index | ||
601 | * | ||
602 | * Wait for writeback to complete against pages indexed by start->end | ||
603 | * inclusive | ||
604 | */ | ||
605 | int btrfs_wait_on_page_writeback_range(struct address_space *mapping, | ||
606 | pgoff_t start, pgoff_t end) | ||
607 | { | ||
608 | struct pagevec pvec; | ||
609 | int nr_pages; | ||
610 | int ret = 0; | ||
611 | pgoff_t index; | ||
612 | |||
613 | if (end < start) | ||
614 | return 0; | ||
615 | |||
616 | pagevec_init(&pvec, 0); | ||
617 | index = start; | ||
618 | while ((index <= end) && | ||
619 | (nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, | ||
620 | PAGECACHE_TAG_WRITEBACK, | ||
621 | min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1)) != 0) { | ||
622 | unsigned i; | ||
623 | |||
624 | for (i = 0; i < nr_pages; i++) { | ||
625 | struct page *page = pvec.pages[i]; | ||
626 | |||
627 | /* until radix tree lookup accepts end_index */ | ||
628 | if (page->index > end) | ||
629 | continue; | ||
630 | |||
631 | wait_on_page_writeback(page); | ||
632 | if (PageError(page)) | ||
633 | ret = -EIO; | ||
634 | } | ||
635 | pagevec_release(&pvec); | ||
636 | cond_resched(); | ||
637 | } | ||
638 | |||
639 | /* Check for outstanding write errors */ | ||
640 | if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) | ||
641 | ret = -ENOSPC; | ||
642 | if (test_and_clear_bit(AS_EIO, &mapping->flags)) | ||
643 | ret = -EIO; | ||
644 | |||
645 | return ret; | ||
646 | } | ||
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 1794efd13ca3..8e8e3c0404f3 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
@@ -132,4 +132,8 @@ btrfs_lookup_first_ordered_extent(struct inode * inode, u64 file_offset); | |||
132 | int btrfs_ordered_update_i_size(struct inode *inode, | 132 | int btrfs_ordered_update_i_size(struct inode *inode, |
133 | struct btrfs_ordered_extent *ordered); | 133 | struct btrfs_ordered_extent *ordered); |
134 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum); | 134 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum); |
135 | int btrfs_wait_on_page_writeback_range(struct address_space *mapping, | ||
136 | pgoff_t start, pgoff_t end); | ||
137 | int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start, | ||
138 | loff_t end, int sync_mode); | ||
135 | #endif | 139 | #endif |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 05823904ecba..38c75a0256cb 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -649,7 +649,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
649 | extent_io_tree_init(pinned_copy, | 649 | extent_io_tree_init(pinned_copy, |
650 | root->fs_info->btree_inode->i_mapping, GFP_NOFS); | 650 | root->fs_info->btree_inode->i_mapping, GFP_NOFS); |
651 | 651 | ||
652 | printk("commit trans %Lu\n", trans->transid); | ||
653 | trans->transaction->in_commit = 1; | 652 | trans->transaction->in_commit = 1; |
654 | trans->transaction->blocked = 1; | 653 | trans->transaction->blocked = 1; |
655 | cur_trans = trans->transaction; | 654 | cur_trans = trans->transaction; |
@@ -745,7 +744,6 @@ printk("commit trans %Lu\n", trans->transid); | |||
745 | list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots); | 744 | list_splice_init(&dirty_fs_roots, &root->fs_info->dead_roots); |
746 | 745 | ||
747 | mutex_unlock(&root->fs_info->trans_mutex); | 746 | mutex_unlock(&root->fs_info->trans_mutex); |
748 | printk("done commit trans %Lu\n", trans->transid); | ||
749 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 747 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
750 | 748 | ||
751 | if (root->fs_info->closing) { | 749 | if (root->fs_info->closing) { |