aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent_io.c20
-rw-r--r--fs/btrfs/extent_io.h1
-rw-r--r--fs/btrfs/extent_map.c9
-rw-r--r--fs/btrfs/extent_map.h1
-rw-r--r--fs/btrfs/file.c15
-rw-r--r--fs/btrfs/inode.c54
-rw-r--r--fs/btrfs/ordered-data.c115
-rw-r--r--fs/btrfs/ordered-data.h4
-rw-r--r--fs/btrfs/transaction.c2
10 files changed, 140 insertions, 83 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 96ab2797c09..f8fccdac305 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 */
1593int btrfs_writepages(struct address_space *mapping,
1594 struct writeback_control *wbc);
1593int btrfs_create_subvol_root(struct btrfs_root *new_root, 1595int 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 7380449cb5b..9965993748d 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}
102EXPORT_SYMBOL(extent_io_tree_init); 101EXPORT_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 6c03e6a1993..315cfceae31 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
66struct extent_state { 65struct extent_state {
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 71b1ac15535..8a502ee2f23 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -42,7 +42,6 @@ void extent_map_exit(void)
42void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask) 42void 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}
48EXPORT_SYMBOL(extent_map_tree_init); 47EXPORT_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;
243out: 241out:
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
306found: 300found:
307 atomic_inc(&em->refs); 301 atomic_inc(&em->refs);
308 tree->last = em;
309out: 302out:
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}
334EXPORT_SYMBOL(remove_extent_mapping); 325EXPORT_SYMBOL(remove_extent_mapping);
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index a3978ec2784..26ac6fe0b26 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -26,7 +26,6 @@ struct extent_map {
26 26
27struct extent_map_tree { 27struct 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 591a30208ac..e5ffb66ad32 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 60852ada658..3da12a4d913 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;
488printk("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
2334again: 2333again:
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);
2532out: 2537out:
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
2646static int btrfs_writepages(struct address_space *mapping, 2652int 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 0d87795fdd8..830dbaea685 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;
339again: 336again:
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 */
581int 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 */
605int 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 1794efd13ca..8e8e3c0404f 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);
132int btrfs_ordered_update_i_size(struct inode *inode, 132int btrfs_ordered_update_i_size(struct inode *inode,
133 struct btrfs_ordered_extent *ordered); 133 struct btrfs_ordered_extent *ordered);
134int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum); 134int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum);
135int btrfs_wait_on_page_writeback_range(struct address_space *mapping,
136 pgoff_t start, pgoff_t end);
137int 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 05823904ecb..38c75a0256c 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
652printk("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);
748printk("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) {