diff options
Diffstat (limited to 'fs/btrfs/file-item.c')
| -rw-r--r-- | fs/btrfs/file-item.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 9b99886562d0..a562a250ae77 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/bio.h> | 19 | #include <linux/bio.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
| 21 | #include <linux/highmem.h> | 22 | #include <linux/highmem.h> |
| 22 | #include "ctree.h" | 23 | #include "ctree.h" |
| @@ -148,13 +149,14 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
| 148 | } | 149 | } |
| 149 | 150 | ||
| 150 | 151 | ||
| 151 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | 152 | static int __btrfs_lookup_bio_sums(struct btrfs_root *root, |
| 152 | struct bio *bio, u32 *dst) | 153 | struct inode *inode, struct bio *bio, |
| 154 | u64 logical_offset, u32 *dst, int dio) | ||
| 153 | { | 155 | { |
| 154 | u32 sum; | 156 | u32 sum; |
| 155 | struct bio_vec *bvec = bio->bi_io_vec; | 157 | struct bio_vec *bvec = bio->bi_io_vec; |
| 156 | int bio_index = 0; | 158 | int bio_index = 0; |
| 157 | u64 offset; | 159 | u64 offset = 0; |
| 158 | u64 item_start_offset = 0; | 160 | u64 item_start_offset = 0; |
| 159 | u64 item_last_offset = 0; | 161 | u64 item_last_offset = 0; |
| 160 | u64 disk_bytenr; | 162 | u64 disk_bytenr; |
| @@ -173,8 +175,11 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | |||
| 173 | WARN_ON(bio->bi_vcnt <= 0); | 175 | WARN_ON(bio->bi_vcnt <= 0); |
| 174 | 176 | ||
| 175 | disk_bytenr = (u64)bio->bi_sector << 9; | 177 | disk_bytenr = (u64)bio->bi_sector << 9; |
| 178 | if (dio) | ||
| 179 | offset = logical_offset; | ||
| 176 | while (bio_index < bio->bi_vcnt) { | 180 | while (bio_index < bio->bi_vcnt) { |
| 177 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 181 | if (!dio) |
| 182 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | ||
| 178 | ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum); | 183 | ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum); |
| 179 | if (ret == 0) | 184 | if (ret == 0) |
| 180 | goto found; | 185 | goto found; |
| @@ -237,6 +242,7 @@ found: | |||
| 237 | else | 242 | else |
| 238 | set_state_private(io_tree, offset, sum); | 243 | set_state_private(io_tree, offset, sum); |
| 239 | disk_bytenr += bvec->bv_len; | 244 | disk_bytenr += bvec->bv_len; |
| 245 | offset += bvec->bv_len; | ||
| 240 | bio_index++; | 246 | bio_index++; |
| 241 | bvec++; | 247 | bvec++; |
| 242 | } | 248 | } |
| @@ -244,6 +250,18 @@ found: | |||
| 244 | return 0; | 250 | return 0; |
| 245 | } | 251 | } |
| 246 | 252 | ||
| 253 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | ||
| 254 | struct bio *bio, u32 *dst) | ||
| 255 | { | ||
| 256 | return __btrfs_lookup_bio_sums(root, inode, bio, 0, dst, 0); | ||
| 257 | } | ||
| 258 | |||
| 259 | int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode, | ||
| 260 | struct bio *bio, u64 offset, u32 *dst) | ||
| 261 | { | ||
| 262 | return __btrfs_lookup_bio_sums(root, inode, bio, offset, dst, 1); | ||
| 263 | } | ||
| 264 | |||
| 247 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | 265 | int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, |
| 248 | struct list_head *list) | 266 | struct list_head *list) |
| 249 | { | 267 | { |
| @@ -656,6 +674,9 @@ again: | |||
| 656 | goto found; | 674 | goto found; |
| 657 | } | 675 | } |
| 658 | ret = PTR_ERR(item); | 676 | ret = PTR_ERR(item); |
| 677 | if (ret != -EFBIG && ret != -ENOENT) | ||
| 678 | goto fail_unlock; | ||
| 679 | |||
| 659 | if (ret == -EFBIG) { | 680 | if (ret == -EFBIG) { |
| 660 | u32 item_size; | 681 | u32 item_size; |
| 661 | /* we found one, but it isn't big enough yet */ | 682 | /* we found one, but it isn't big enough yet */ |
