diff options
Diffstat (limited to 'fs/ext4/page-io.c')
-rw-r--r-- | fs/ext4/page-io.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 48786cdb5e6c..6625d210fb45 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/ratelimit.h> | ||
28 | 29 | ||
29 | #include "ext4_jbd2.h" | 30 | #include "ext4_jbd2.h" |
30 | #include "xattr.h" | 31 | #include "xattr.h" |
@@ -55,7 +56,7 @@ void ext4_exit_pageio(void) | |||
55 | static void buffer_io_error(struct buffer_head *bh) | 56 | static void buffer_io_error(struct buffer_head *bh) |
56 | { | 57 | { |
57 | char b[BDEVNAME_SIZE]; | 58 | char b[BDEVNAME_SIZE]; |
58 | printk(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", | 59 | printk_ratelimited(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", |
59 | bdevname(bh->b_bdev, b), | 60 | bdevname(bh->b_bdev, b), |
60 | (unsigned long long)bh->b_blocknr); | 61 | (unsigned long long)bh->b_blocknr); |
61 | } | 62 | } |
@@ -308,6 +309,7 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end) | |||
308 | return io_end; | 309 | return io_end; |
309 | } | 310 | } |
310 | 311 | ||
312 | /* BIO completion function for page writeback */ | ||
311 | static void ext4_end_bio(struct bio *bio, int error) | 313 | static void ext4_end_bio(struct bio *bio, int error) |
312 | { | 314 | { |
313 | ext4_io_end_t *io_end = bio->bi_private; | 315 | ext4_io_end_t *io_end = bio->bi_private; |
@@ -318,18 +320,6 @@ static void ext4_end_bio(struct bio *bio, int error) | |||
318 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) | 320 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) |
319 | error = 0; | 321 | error = 0; |
320 | 322 | ||
321 | if (io_end->flag & EXT4_IO_END_UNWRITTEN) { | ||
322 | /* | ||
323 | * Link bio into list hanging from io_end. We have to do it | ||
324 | * atomically as bio completions can be racing against each | ||
325 | * other. | ||
326 | */ | ||
327 | bio->bi_private = xchg(&io_end->bio, bio); | ||
328 | } else { | ||
329 | ext4_finish_bio(bio); | ||
330 | bio_put(bio); | ||
331 | } | ||
332 | |||
333 | if (error) { | 323 | if (error) { |
334 | struct inode *inode = io_end->inode; | 324 | struct inode *inode = io_end->inode; |
335 | 325 | ||
@@ -341,7 +331,24 @@ static void ext4_end_bio(struct bio *bio, int error) | |||
341 | (unsigned long long) | 331 | (unsigned long long) |
342 | bi_sector >> (inode->i_blkbits - 9)); | 332 | bi_sector >> (inode->i_blkbits - 9)); |
343 | } | 333 | } |
344 | ext4_put_io_end_defer(io_end); | 334 | |
335 | if (io_end->flag & EXT4_IO_END_UNWRITTEN) { | ||
336 | /* | ||
337 | * Link bio into list hanging from io_end. We have to do it | ||
338 | * atomically as bio completions can be racing against each | ||
339 | * other. | ||
340 | */ | ||
341 | bio->bi_private = xchg(&io_end->bio, bio); | ||
342 | ext4_put_io_end_defer(io_end); | ||
343 | } else { | ||
344 | /* | ||
345 | * Drop io_end reference early. Inode can get freed once | ||
346 | * we finish the bio. | ||
347 | */ | ||
348 | ext4_put_io_end_defer(io_end); | ||
349 | ext4_finish_bio(bio); | ||
350 | bio_put(bio); | ||
351 | } | ||
345 | } | 352 | } |
346 | 353 | ||
347 | void ext4_io_submit(struct ext4_io_submit *io) | 354 | void ext4_io_submit(struct ext4_io_submit *io) |