aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file-item.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r--fs/btrfs/file-item.c102
1 files changed, 44 insertions, 58 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index c4628a201cb3..b193bf324a41 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -83,10 +83,11 @@ out:
83 return ret; 83 return ret;
84} 84}
85 85
86struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, 86static struct btrfs_csum_item *
87 struct btrfs_root *root, 87btrfs_lookup_csum(struct btrfs_trans_handle *trans,
88 struct btrfs_path *path, 88 struct btrfs_root *root,
89 u64 bytenr, int cow) 89 struct btrfs_path *path,
90 u64 bytenr, int cow)
90{ 91{
91 int ret; 92 int ret;
92 struct btrfs_key file_key; 93 struct btrfs_key file_key;
@@ -152,32 +153,12 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
152 return ret; 153 return ret;
153} 154}
154 155
155u64 btrfs_file_extent_length(struct btrfs_path *path)
156{
157 int extent_type;
158 struct btrfs_file_extent_item *fi;
159 u64 len;
160
161 fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
162 struct btrfs_file_extent_item);
163 extent_type = btrfs_file_extent_type(path->nodes[0], fi);
164
165 if (extent_type == BTRFS_FILE_EXTENT_REG ||
166 extent_type == BTRFS_FILE_EXTENT_PREALLOC)
167 len = btrfs_file_extent_num_bytes(path->nodes[0], fi);
168 else if (extent_type == BTRFS_FILE_EXTENT_INLINE)
169 len = btrfs_file_extent_inline_len(path->nodes[0], fi);
170 else
171 BUG();
172
173 return len;
174}
175
176static int __btrfs_lookup_bio_sums(struct btrfs_root *root, 156static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
177 struct inode *inode, struct bio *bio, 157 struct inode *inode, struct bio *bio,
178 u64 logical_offset, u32 *dst, int dio) 158 u64 logical_offset, u32 *dst, int dio)
179{ 159{
180 u32 sum; 160 u32 sum[16];
161 int len;
181 struct bio_vec *bvec = bio->bi_io_vec; 162 struct bio_vec *bvec = bio->bi_io_vec;
182 int bio_index = 0; 163 int bio_index = 0;
183 u64 offset = 0; 164 u64 offset = 0;
@@ -186,7 +167,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
186 u64 disk_bytenr; 167 u64 disk_bytenr;
187 u32 diff; 168 u32 diff;
188 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 169 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
189 int ret; 170 int count;
190 struct btrfs_path *path; 171 struct btrfs_path *path;
191 struct btrfs_csum_item *item = NULL; 172 struct btrfs_csum_item *item = NULL;
192 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; 173 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
@@ -214,10 +195,12 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
214 if (dio) 195 if (dio)
215 offset = logical_offset; 196 offset = logical_offset;
216 while (bio_index < bio->bi_vcnt) { 197 while (bio_index < bio->bi_vcnt) {
198 len = min_t(int, ARRAY_SIZE(sum), bio->bi_vcnt - bio_index);
217 if (!dio) 199 if (!dio)
218 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 200 offset = page_offset(bvec->bv_page) + bvec->bv_offset;
219 ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum); 201 count = btrfs_find_ordered_sum(inode, offset, disk_bytenr, sum,
220 if (ret == 0) 202 len);
203 if (count)
221 goto found; 204 goto found;
222 205
223 if (!item || disk_bytenr < item_start_offset || 206 if (!item || disk_bytenr < item_start_offset ||
@@ -230,10 +213,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
230 item = btrfs_lookup_csum(NULL, root->fs_info->csum_root, 213 item = btrfs_lookup_csum(NULL, root->fs_info->csum_root,
231 path, disk_bytenr, 0); 214 path, disk_bytenr, 0);
232 if (IS_ERR(item)) { 215 if (IS_ERR(item)) {
233 ret = PTR_ERR(item); 216 count = 1;
234 if (ret == -ENOENT || ret == -EFBIG) 217 sum[0] = 0;
235 ret = 0;
236 sum = 0;
237 if (BTRFS_I(inode)->root->root_key.objectid == 218 if (BTRFS_I(inode)->root->root_key.objectid ==
238 BTRFS_DATA_RELOC_TREE_OBJECTID) { 219 BTRFS_DATA_RELOC_TREE_OBJECTID) {
239 set_extent_bits(io_tree, offset, 220 set_extent_bits(io_tree, offset,
@@ -269,19 +250,29 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
269 diff = disk_bytenr - item_start_offset; 250 diff = disk_bytenr - item_start_offset;
270 diff = diff / root->sectorsize; 251 diff = diff / root->sectorsize;
271 diff = diff * csum_size; 252 diff = diff * csum_size;
272 253 count = min_t(int, len, (item_last_offset - disk_bytenr) >>
273 read_extent_buffer(path->nodes[0], &sum, 254 inode->i_sb->s_blocksize_bits);
255 read_extent_buffer(path->nodes[0], sum,
274 ((unsigned long)item) + diff, 256 ((unsigned long)item) + diff,
275 csum_size); 257 csum_size * count);
276found: 258found:
277 if (dst) 259 if (dst) {
278 *dst++ = sum; 260 memcpy(dst, sum, count * csum_size);
279 else 261 dst += count;
280 set_state_private(io_tree, offset, sum); 262 } else {
281 disk_bytenr += bvec->bv_len; 263 if (dio)
282 offset += bvec->bv_len; 264 extent_cache_csums_dio(io_tree, offset, sum,
283 bio_index++; 265 count);
284 bvec++; 266 else
267 extent_cache_csums(io_tree, bio, bio_index, sum,
268 count);
269 }
270 while (count--) {
271 disk_bytenr += bvec->bv_len;
272 offset += bvec->bv_len;
273 bio_index++;
274 bvec++;
275 }
285 } 276 }
286 btrfs_free_path(path); 277 btrfs_free_path(path);
287 return 0; 278 return 0;
@@ -358,11 +349,8 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
358 349
359 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); 350 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
360 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || 351 if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
361 key.type != BTRFS_EXTENT_CSUM_KEY) 352 key.type != BTRFS_EXTENT_CSUM_KEY ||
362 break; 353 key.offset > end)
363
364 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
365 if (key.offset > end)
366 break; 354 break;
367 355
368 if (key.offset > start) 356 if (key.offset > start)
@@ -484,8 +472,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
484 472
485 data = kmap_atomic(bvec->bv_page); 473 data = kmap_atomic(bvec->bv_page);
486 sector_sum->sum = ~(u32)0; 474 sector_sum->sum = ~(u32)0;
487 sector_sum->sum = btrfs_csum_data(root, 475 sector_sum->sum = btrfs_csum_data(data + bvec->bv_offset,
488 data + bvec->bv_offset,
489 sector_sum->sum, 476 sector_sum->sum,
490 bvec->bv_len); 477 bvec->bv_len);
491 kunmap_atomic(data); 478 kunmap_atomic(data);
@@ -518,8 +505,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
518 * This calls btrfs_truncate_item with the correct args based on the 505 * This calls btrfs_truncate_item with the correct args based on the
519 * overlap, and fixes up the key as required. 506 * overlap, and fixes up the key as required.
520 */ 507 */
521static noinline void truncate_one_csum(struct btrfs_trans_handle *trans, 508static noinline void truncate_one_csum(struct btrfs_root *root,
522 struct btrfs_root *root,
523 struct btrfs_path *path, 509 struct btrfs_path *path,
524 struct btrfs_key *key, 510 struct btrfs_key *key,
525 u64 bytenr, u64 len) 511 u64 bytenr, u64 len)
@@ -544,7 +530,7 @@ static noinline void truncate_one_csum(struct btrfs_trans_handle *trans,
544 */ 530 */
545 u32 new_size = (bytenr - key->offset) >> blocksize_bits; 531 u32 new_size = (bytenr - key->offset) >> blocksize_bits;
546 new_size *= csum_size; 532 new_size *= csum_size;
547 btrfs_truncate_item(trans, root, path, new_size, 1); 533 btrfs_truncate_item(root, path, new_size, 1);
548 } else if (key->offset >= bytenr && csum_end > end_byte && 534 } else if (key->offset >= bytenr && csum_end > end_byte &&
549 end_byte > key->offset) { 535 end_byte > key->offset) {
550 /* 536 /*
@@ -556,10 +542,10 @@ static noinline void truncate_one_csum(struct btrfs_trans_handle *trans,
556 u32 new_size = (csum_end - end_byte) >> blocksize_bits; 542 u32 new_size = (csum_end - end_byte) >> blocksize_bits;
557 new_size *= csum_size; 543 new_size *= csum_size;
558 544
559 btrfs_truncate_item(trans, root, path, new_size, 0); 545 btrfs_truncate_item(root, path, new_size, 0);
560 546
561 key->offset = end_byte; 547 key->offset = end_byte;
562 btrfs_set_item_key_safe(trans, root, path, key); 548 btrfs_set_item_key_safe(root, path, key);
563 } else { 549 } else {
564 BUG(); 550 BUG();
565 } 551 }
@@ -674,7 +660,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
674 660
675 key.offset = end_byte - 1; 661 key.offset = end_byte - 1;
676 } else { 662 } else {
677 truncate_one_csum(trans, root, path, &key, bytenr, len); 663 truncate_one_csum(root, path, &key, bytenr, len);
678 if (key.offset < bytenr) 664 if (key.offset < bytenr)
679 break; 665 break;
680 } 666 }
@@ -835,7 +821,7 @@ again:
835 diff /= csum_size; 821 diff /= csum_size;
836 diff *= csum_size; 822 diff *= csum_size;
837 823
838 btrfs_extend_item(trans, root, path, diff); 824 btrfs_extend_item(root, path, diff);
839 goto csum; 825 goto csum;
840 } 826 }
841 827