diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 64 |
1 files changed, 43 insertions, 21 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1669c3b4be2f..d59dddfb1f96 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -6927,7 +6927,11 @@ struct btrfs_dio_private { | |||
6927 | /* IO errors */ | 6927 | /* IO errors */ |
6928 | int errors; | 6928 | int errors; |
6929 | 6929 | ||
6930 | /* orig_bio is our btrfs_io_bio */ | ||
6930 | struct bio *orig_bio; | 6931 | struct bio *orig_bio; |
6932 | |||
6933 | /* dio_bio came from fs/direct-io.c */ | ||
6934 | struct bio *dio_bio; | ||
6931 | }; | 6935 | }; |
6932 | 6936 | ||
6933 | static void btrfs_endio_direct_read(struct bio *bio, int err) | 6937 | static void btrfs_endio_direct_read(struct bio *bio, int err) |
@@ -6937,6 +6941,7 @@ static void btrfs_endio_direct_read(struct bio *bio, int err) | |||
6937 | struct bio_vec *bvec = bio->bi_io_vec; | 6941 | struct bio_vec *bvec = bio->bi_io_vec; |
6938 | struct inode *inode = dip->inode; | 6942 | struct inode *inode = dip->inode; |
6939 | struct btrfs_root *root = BTRFS_I(inode)->root; | 6943 | struct btrfs_root *root = BTRFS_I(inode)->root; |
6944 | struct bio *dio_bio; | ||
6940 | u64 start; | 6945 | u64 start; |
6941 | 6946 | ||
6942 | start = dip->logical_offset; | 6947 | start = dip->logical_offset; |
@@ -6976,14 +6981,15 @@ failed: | |||
6976 | 6981 | ||
6977 | unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, | 6982 | unlock_extent(&BTRFS_I(inode)->io_tree, dip->logical_offset, |
6978 | dip->logical_offset + dip->bytes - 1); | 6983 | dip->logical_offset + dip->bytes - 1); |
6979 | bio->bi_private = dip->private; | 6984 | dio_bio = dip->dio_bio; |
6980 | 6985 | ||
6981 | kfree(dip); | 6986 | kfree(dip); |
6982 | 6987 | ||
6983 | /* If we had a csum failure make sure to clear the uptodate flag */ | 6988 | /* If we had a csum failure make sure to clear the uptodate flag */ |
6984 | if (err) | 6989 | if (err) |
6985 | clear_bit(BIO_UPTODATE, &bio->bi_flags); | 6990 | clear_bit(BIO_UPTODATE, &dio_bio->bi_flags); |
6986 | dio_end_io(bio, err); | 6991 | dio_end_io(dio_bio, err); |
6992 | bio_put(bio); | ||
6987 | } | 6993 | } |
6988 | 6994 | ||
6989 | static void btrfs_endio_direct_write(struct bio *bio, int err) | 6995 | static void btrfs_endio_direct_write(struct bio *bio, int err) |
@@ -6994,6 +7000,7 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) | |||
6994 | struct btrfs_ordered_extent *ordered = NULL; | 7000 | struct btrfs_ordered_extent *ordered = NULL; |
6995 | u64 ordered_offset = dip->logical_offset; | 7001 | u64 ordered_offset = dip->logical_offset; |
6996 | u64 ordered_bytes = dip->bytes; | 7002 | u64 ordered_bytes = dip->bytes; |
7003 | struct bio *dio_bio; | ||
6997 | int ret; | 7004 | int ret; |
6998 | 7005 | ||
6999 | if (err) | 7006 | if (err) |
@@ -7021,14 +7028,15 @@ out_test: | |||
7021 | goto again; | 7028 | goto again; |
7022 | } | 7029 | } |
7023 | out_done: | 7030 | out_done: |
7024 | bio->bi_private = dip->private; | 7031 | dio_bio = dip->dio_bio; |
7025 | 7032 | ||
7026 | kfree(dip); | 7033 | kfree(dip); |
7027 | 7034 | ||
7028 | /* If we had an error make sure to clear the uptodate flag */ | 7035 | /* If we had an error make sure to clear the uptodate flag */ |
7029 | if (err) | 7036 | if (err) |
7030 | clear_bit(BIO_UPTODATE, &bio->bi_flags); | 7037 | clear_bit(BIO_UPTODATE, &dio_bio->bi_flags); |
7031 | dio_end_io(bio, err); | 7038 | dio_end_io(dio_bio, err); |
7039 | bio_put(bio); | ||
7032 | } | 7040 | } |
7033 | 7041 | ||
7034 | static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw, | 7042 | static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw, |
@@ -7064,10 +7072,10 @@ static void btrfs_end_dio_bio(struct bio *bio, int err) | |||
7064 | if (!atomic_dec_and_test(&dip->pending_bios)) | 7072 | if (!atomic_dec_and_test(&dip->pending_bios)) |
7065 | goto out; | 7073 | goto out; |
7066 | 7074 | ||
7067 | if (dip->errors) | 7075 | if (dip->errors) { |
7068 | bio_io_error(dip->orig_bio); | 7076 | bio_io_error(dip->orig_bio); |
7069 | else { | 7077 | } else { |
7070 | set_bit(BIO_UPTODATE, &dip->orig_bio->bi_flags); | 7078 | set_bit(BIO_UPTODATE, &dip->dio_bio->bi_flags); |
7071 | bio_endio(dip->orig_bio, 0); | 7079 | bio_endio(dip->orig_bio, 0); |
7072 | } | 7080 | } |
7073 | out: | 7081 | out: |
@@ -7242,25 +7250,34 @@ out_err: | |||
7242 | return 0; | 7250 | return 0; |
7243 | } | 7251 | } |
7244 | 7252 | ||
7245 | static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | 7253 | static void btrfs_submit_direct(int rw, struct bio *dio_bio, |
7246 | loff_t file_offset) | 7254 | struct inode *inode, loff_t file_offset) |
7247 | { | 7255 | { |
7248 | struct btrfs_root *root = BTRFS_I(inode)->root; | 7256 | struct btrfs_root *root = BTRFS_I(inode)->root; |
7249 | struct btrfs_dio_private *dip; | 7257 | struct btrfs_dio_private *dip; |
7250 | struct bio_vec *bvec = bio->bi_io_vec; | 7258 | struct bio_vec *bvec = dio_bio->bi_io_vec; |
7259 | struct bio *io_bio; | ||
7251 | int skip_sum; | 7260 | int skip_sum; |
7252 | int write = rw & REQ_WRITE; | 7261 | int write = rw & REQ_WRITE; |
7253 | int ret = 0; | 7262 | int ret = 0; |
7254 | 7263 | ||
7255 | skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; | 7264 | skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; |
7256 | 7265 | ||
7266 | io_bio = btrfs_bio_clone(dio_bio, GFP_NOFS); | ||
7267 | |||
7268 | if (!io_bio) { | ||
7269 | ret = -ENOMEM; | ||
7270 | goto free_ordered; | ||
7271 | } | ||
7272 | |||
7257 | dip = kmalloc(sizeof(*dip), GFP_NOFS); | 7273 | dip = kmalloc(sizeof(*dip), GFP_NOFS); |
7258 | if (!dip) { | 7274 | if (!dip) { |
7259 | ret = -ENOMEM; | 7275 | ret = -ENOMEM; |
7260 | goto free_ordered; | 7276 | goto free_io_bio; |
7261 | } | 7277 | } |
7262 | 7278 | ||
7263 | dip->private = bio->bi_private; | 7279 | dip->private = dio_bio->bi_private; |
7280 | io_bio->bi_private = dio_bio->bi_private; | ||
7264 | dip->inode = inode; | 7281 | dip->inode = inode; |
7265 | dip->logical_offset = file_offset; | 7282 | dip->logical_offset = file_offset; |
7266 | 7283 | ||
@@ -7268,22 +7285,27 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | |||
7268 | do { | 7285 | do { |
7269 | dip->bytes += bvec->bv_len; | 7286 | dip->bytes += bvec->bv_len; |
7270 | bvec++; | 7287 | bvec++; |
7271 | } while (bvec <= (bio->bi_io_vec + bio->bi_vcnt - 1)); | 7288 | } while (bvec <= (dio_bio->bi_io_vec + dio_bio->bi_vcnt - 1)); |
7272 | 7289 | ||
7273 | dip->disk_bytenr = (u64)bio->bi_sector << 9; | 7290 | dip->disk_bytenr = (u64)dio_bio->bi_sector << 9; |
7274 | bio->bi_private = dip; | 7291 | io_bio->bi_private = dip; |
7275 | dip->errors = 0; | 7292 | dip->errors = 0; |
7276 | dip->orig_bio = bio; | 7293 | dip->orig_bio = io_bio; |
7294 | dip->dio_bio = dio_bio; | ||
7277 | atomic_set(&dip->pending_bios, 0); | 7295 | atomic_set(&dip->pending_bios, 0); |
7278 | 7296 | ||
7279 | if (write) | 7297 | if (write) |
7280 | bio->bi_end_io = btrfs_endio_direct_write; | 7298 | io_bio->bi_end_io = btrfs_endio_direct_write; |
7281 | else | 7299 | else |
7282 | bio->bi_end_io = btrfs_endio_direct_read; | 7300 | io_bio->bi_end_io = btrfs_endio_direct_read; |
7283 | 7301 | ||
7284 | ret = btrfs_submit_direct_hook(rw, dip, skip_sum); | 7302 | ret = btrfs_submit_direct_hook(rw, dip, skip_sum); |
7285 | if (!ret) | 7303 | if (!ret) |
7286 | return; | 7304 | return; |
7305 | |||
7306 | free_io_bio: | ||
7307 | bio_put(io_bio); | ||
7308 | |||
7287 | free_ordered: | 7309 | free_ordered: |
7288 | /* | 7310 | /* |
7289 | * If this is a write, we need to clean up the reserved space and kill | 7311 | * If this is a write, we need to clean up the reserved space and kill |
@@ -7299,7 +7321,7 @@ free_ordered: | |||
7299 | btrfs_put_ordered_extent(ordered); | 7321 | btrfs_put_ordered_extent(ordered); |
7300 | btrfs_put_ordered_extent(ordered); | 7322 | btrfs_put_ordered_extent(ordered); |
7301 | } | 7323 | } |
7302 | bio_endio(bio, ret); | 7324 | bio_endio(dio_bio, ret); |
7303 | } | 7325 | } |
7304 | 7326 | ||
7305 | static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb, | 7327 | static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *iocb, |