diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2013-08-29 09:46:30 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2013-08-29 09:46:30 +0200 |
commit | 6ad30ce046aefbdc3848232c665a728860d7bb68 (patch) | |
tree | 34af8fc78b28281fcfe531a26401b440c078038e /fs/ext4/page-io.c | |
parent | 0351c287952483dafa904f84496631198465fbf4 (diff) | |
parent | d8dfad3876e4386666b759da3c833d62fb8b2267 (diff) |
Merge tag 'v3.11-rc7' into devel
Merged in this to avoid conflicts with the big locking fixes
from upstream.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Conflicts:
drivers/pinctrl/pinctrl-sunxi.c
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 48786cdb5e6..6625d210fb4 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -25,6 +25,7 @@ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/mm.h> +#include <linux/ratelimit.h> #include "ext4_jbd2.h" #include "xattr.h" @@ -55,7 +56,7 @@ void ext4_exit_pageio(void) static void buffer_io_error(struct buffer_head *bh) { char b[BDEVNAME_SIZE]; - printk(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", + printk_ratelimited(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", bdevname(bh->b_bdev, b), (unsigned long long)bh->b_blocknr); } @@ -308,6 +309,7 @@ ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end) return io_end; } +/* BIO completion function for page writeback */ static void ext4_end_bio(struct bio *bio, int error) { ext4_io_end_t *io_end = bio->bi_private; @@ -318,18 +320,6 @@ static void ext4_end_bio(struct bio *bio, int error) if (test_bit(BIO_UPTODATE, &bio->bi_flags)) error = 0; - if (io_end->flag & EXT4_IO_END_UNWRITTEN) { - /* - * Link bio into list hanging from io_end. We have to do it - * atomically as bio completions can be racing against each - * other. - */ - bio->bi_private = xchg(&io_end->bio, bio); - } else { - ext4_finish_bio(bio); - bio_put(bio); - } - if (error) { struct inode *inode = io_end->inode; @@ -341,7 +331,24 @@ static void ext4_end_bio(struct bio *bio, int error) (unsigned long long) bi_sector >> (inode->i_blkbits - 9)); } - ext4_put_io_end_defer(io_end); + + if (io_end->flag & EXT4_IO_END_UNWRITTEN) { + /* + * Link bio into list hanging from io_end. We have to do it + * atomically as bio completions can be racing against each + * other. + */ + bio->bi_private = xchg(&io_end->bio, bio); + ext4_put_io_end_defer(io_end); + } else { + /* + * Drop io_end reference early. Inode can get freed once + * we finish the bio. + */ + ext4_put_io_end_defer(io_end); + ext4_finish_bio(bio); + bio_put(bio); + } } void ext4_io_submit(struct ext4_io_submit *io) |