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.c103
1 files changed, 70 insertions, 33 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index a67e1c828d0f..b5baf5bdc8e1 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -25,6 +25,7 @@
25#include "transaction.h" 25#include "transaction.h"
26#include "volumes.h" 26#include "volumes.h"
27#include "print-tree.h" 27#include "print-tree.h"
28#include "compression.h"
28 29
29#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \ 30#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \
30 sizeof(struct btrfs_item) * 2) / \ 31 sizeof(struct btrfs_item) * 2) / \
@@ -172,6 +173,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
172 u64 item_start_offset = 0; 173 u64 item_start_offset = 0;
173 u64 item_last_offset = 0; 174 u64 item_last_offset = 0;
174 u64 disk_bytenr; 175 u64 disk_bytenr;
176 u64 page_bytes_left;
175 u32 diff; 177 u32 diff;
176 int nblocks; 178 int nblocks;
177 int bio_index = 0; 179 int bio_index = 0;
@@ -220,6 +222,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
220 disk_bytenr = (u64)bio->bi_iter.bi_sector << 9; 222 disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
221 if (dio) 223 if (dio)
222 offset = logical_offset; 224 offset = logical_offset;
225
226 page_bytes_left = bvec->bv_len;
223 while (bio_index < bio->bi_vcnt) { 227 while (bio_index < bio->bi_vcnt) {
224 if (!dio) 228 if (!dio)
225 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 229 offset = page_offset(bvec->bv_page) + bvec->bv_offset;
@@ -243,7 +247,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
243 if (BTRFS_I(inode)->root->root_key.objectid == 247 if (BTRFS_I(inode)->root->root_key.objectid ==
244 BTRFS_DATA_RELOC_TREE_OBJECTID) { 248 BTRFS_DATA_RELOC_TREE_OBJECTID) {
245 set_extent_bits(io_tree, offset, 249 set_extent_bits(io_tree, offset,
246 offset + bvec->bv_len - 1, 250 offset + root->sectorsize - 1,
247 EXTENT_NODATASUM, GFP_NOFS); 251 EXTENT_NODATASUM, GFP_NOFS);
248 } else { 252 } else {
249 btrfs_info(BTRFS_I(inode)->root->fs_info, 253 btrfs_info(BTRFS_I(inode)->root->fs_info,
@@ -281,13 +285,29 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
281found: 285found:
282 csum += count * csum_size; 286 csum += count * csum_size;
283 nblocks -= count; 287 nblocks -= count;
284 bio_index += count; 288
285 while (count--) { 289 while (count--) {
286 disk_bytenr += bvec->bv_len; 290 disk_bytenr += root->sectorsize;
287 offset += bvec->bv_len; 291 offset += root->sectorsize;
288 bvec++; 292 page_bytes_left -= root->sectorsize;
293 if (!page_bytes_left) {
294 bio_index++;
295 /*
296 * make sure we're still inside the
297 * bio before we update page_bytes_left
298 */
299 if (bio_index >= bio->bi_vcnt) {
300 WARN_ON_ONCE(count);
301 goto done;
302 }
303 bvec++;
304 page_bytes_left = bvec->bv_len;
305 }
306
289 } 307 }
290 } 308 }
309
310done:
291 btrfs_free_path(path); 311 btrfs_free_path(path);
292 return 0; 312 return 0;
293} 313}
@@ -432,6 +452,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
432 struct bio_vec *bvec = bio->bi_io_vec; 452 struct bio_vec *bvec = bio->bi_io_vec;
433 int bio_index = 0; 453 int bio_index = 0;
434 int index; 454 int index;
455 int nr_sectors;
456 int i;
435 unsigned long total_bytes = 0; 457 unsigned long total_bytes = 0;
436 unsigned long this_sum_bytes = 0; 458 unsigned long this_sum_bytes = 0;
437 u64 offset; 459 u64 offset;
@@ -459,41 +481,56 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
459 if (!contig) 481 if (!contig)
460 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 482 offset = page_offset(bvec->bv_page) + bvec->bv_offset;
461 483
462 if (offset >= ordered->file_offset + ordered->len || 484 data = kmap_atomic(bvec->bv_page);
463 offset < ordered->file_offset) {
464 unsigned long bytes_left;
465 sums->len = this_sum_bytes;
466 this_sum_bytes = 0;
467 btrfs_add_ordered_sum(inode, ordered, sums);
468 btrfs_put_ordered_extent(ordered);
469 485
470 bytes_left = bio->bi_iter.bi_size - total_bytes; 486 nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
487 bvec->bv_len + root->sectorsize
488 - 1);
489
490 for (i = 0; i < nr_sectors; i++) {
491 if (offset >= ordered->file_offset + ordered->len ||
492 offset < ordered->file_offset) {
493 unsigned long bytes_left;
494
495 kunmap_atomic(data);
496 sums->len = this_sum_bytes;
497 this_sum_bytes = 0;
498 btrfs_add_ordered_sum(inode, ordered, sums);
499 btrfs_put_ordered_extent(ordered);
500
501 bytes_left = bio->bi_iter.bi_size - total_bytes;
502
503 sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
504 GFP_NOFS);
505 BUG_ON(!sums); /* -ENOMEM */
506 sums->len = bytes_left;
507 ordered = btrfs_lookup_ordered_extent(inode,
508 offset);
509 ASSERT(ordered); /* Logic error */
510 sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9)
511 + total_bytes;
512 index = 0;
513
514 data = kmap_atomic(bvec->bv_page);
515 }
471 516
472 sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), 517 sums->sums[index] = ~(u32)0;
473 GFP_NOFS); 518 sums->sums[index]
474 BUG_ON(!sums); /* -ENOMEM */ 519 = btrfs_csum_data(data + bvec->bv_offset
475 sums->len = bytes_left; 520 + (i * root->sectorsize),
476 ordered = btrfs_lookup_ordered_extent(inode, offset); 521 sums->sums[index],
477 BUG_ON(!ordered); /* Logic error */ 522 root->sectorsize);
478 sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) + 523 btrfs_csum_final(sums->sums[index],
479 total_bytes; 524 (char *)(sums->sums + index));
480 index = 0; 525 index++;
526 offset += root->sectorsize;
527 this_sum_bytes += root->sectorsize;
528 total_bytes += root->sectorsize;
481 } 529 }
482 530
483 data = kmap_atomic(bvec->bv_page);
484 sums->sums[index] = ~(u32)0;
485 sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset,
486 sums->sums[index],
487 bvec->bv_len);
488 kunmap_atomic(data); 531 kunmap_atomic(data);
489 btrfs_csum_final(sums->sums[index],
490 (char *)(sums->sums + index));
491 532
492 bio_index++; 533 bio_index++;
493 index++;
494 total_bytes += bvec->bv_len;
495 this_sum_bytes += bvec->bv_len;
496 offset += bvec->bv_len;
497 bvec++; 534 bvec++;
498 } 535 }
499 this_sum_bytes = 0; 536 this_sum_bytes = 0;