diff options
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 2c8f7b204617..01c21b6c6d43 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "volumes.h" | 20 | #include "volumes.h" |
21 | #include "check-integrity.h" | 21 | #include "check-integrity.h" |
22 | #include "locking.h" | 22 | #include "locking.h" |
23 | #include "rcu-string.h" | ||
23 | 24 | ||
24 | static struct kmem_cache *extent_state_cache; | 25 | static struct kmem_cache *extent_state_cache; |
25 | static struct kmem_cache *extent_buffer_cache; | 26 | static struct kmem_cache *extent_buffer_cache; |
@@ -1917,9 +1918,9 @@ int repair_io_failure(struct btrfs_mapping_tree *map_tree, u64 start, | |||
1917 | return -EIO; | 1918 | return -EIO; |
1918 | } | 1919 | } |
1919 | 1920 | ||
1920 | printk(KERN_INFO "btrfs read error corrected: ino %lu off %llu (dev %s " | 1921 | printk_in_rcu(KERN_INFO "btrfs read error corrected: ino %lu off %llu " |
1921 | "sector %llu)\n", page->mapping->host->i_ino, start, | 1922 | "(dev %s sector %llu)\n", page->mapping->host->i_ino, |
1922 | dev->name, sector); | 1923 | start, rcu_str_deref(dev->name), sector); |
1923 | 1924 | ||
1924 | bio_put(bio); | 1925 | bio_put(bio); |
1925 | return 0; | 1926 | return 0; |
@@ -3323,6 +3324,7 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, | |||
3323 | writepage_t writepage, void *data, | 3324 | writepage_t writepage, void *data, |
3324 | void (*flush_fn)(void *)) | 3325 | void (*flush_fn)(void *)) |
3325 | { | 3326 | { |
3327 | struct inode *inode = mapping->host; | ||
3326 | int ret = 0; | 3328 | int ret = 0; |
3327 | int done = 0; | 3329 | int done = 0; |
3328 | int nr_to_write_done = 0; | 3330 | int nr_to_write_done = 0; |
@@ -3333,6 +3335,18 @@ static int extent_write_cache_pages(struct extent_io_tree *tree, | |||
3333 | int scanned = 0; | 3335 | int scanned = 0; |
3334 | int tag; | 3336 | int tag; |
3335 | 3337 | ||
3338 | /* | ||
3339 | * We have to hold onto the inode so that ordered extents can do their | ||
3340 | * work when the IO finishes. The alternative to this is failing to add | ||
3341 | * an ordered extent if the igrab() fails there and that is a huge pain | ||
3342 | * to deal with, so instead just hold onto the inode throughout the | ||
3343 | * writepages operation. If it fails here we are freeing up the inode | ||
3344 | * anyway and we'd rather not waste our time writing out stuff that is | ||
3345 | * going to be truncated anyway. | ||
3346 | */ | ||
3347 | if (!igrab(inode)) | ||
3348 | return 0; | ||
3349 | |||
3336 | pagevec_init(&pvec, 0); | 3350 | pagevec_init(&pvec, 0); |
3337 | if (wbc->range_cyclic) { | 3351 | if (wbc->range_cyclic) { |
3338 | index = mapping->writeback_index; /* Start from prev offset */ | 3352 | index = mapping->writeback_index; /* Start from prev offset */ |
@@ -3427,6 +3441,7 @@ retry: | |||
3427 | index = 0; | 3441 | index = 0; |
3428 | goto retry; | 3442 | goto retry; |
3429 | } | 3443 | } |
3444 | btrfs_add_delayed_iput(inode); | ||
3430 | return ret; | 3445 | return ret; |
3431 | } | 3446 | } |
3432 | 3447 | ||