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