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 @@  #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) |