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.c57
1 files changed, 34 insertions, 23 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 078b4fd54500..5d158d320233 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -25,10 +25,12 @@
25#include "transaction.h" 25#include "transaction.h"
26#include "print-tree.h" 26#include "print-tree.h"
27 27
28#define MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r) - \ 28#define __MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r) - \
29 sizeof(struct btrfs_item) * 2) / \ 29 sizeof(struct btrfs_item) * 2) / \
30 size) - 1)) 30 size) - 1))
31 31
32#define MAX_CSUM_ITEMS(r, size) (min(__MAX_CSUM_ITEMS(r, size), PAGE_CACHE_SIZE))
33
32#define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \ 34#define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \
33 sizeof(struct btrfs_ordered_sum)) / \ 35 sizeof(struct btrfs_ordered_sum)) / \
34 sizeof(struct btrfs_sector_sum) * \ 36 sizeof(struct btrfs_sector_sum) * \
@@ -59,7 +61,7 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
59 sizeof(*item)); 61 sizeof(*item));
60 if (ret < 0) 62 if (ret < 0)
61 goto out; 63 goto out;
62 BUG_ON(ret); 64 BUG_ON(ret); /* Can't happen */
63 leaf = path->nodes[0]; 65 leaf = path->nodes[0];
64 item = btrfs_item_ptr(leaf, path->slots[0], 66 item = btrfs_item_ptr(leaf, path->slots[0],
65 struct btrfs_file_extent_item); 67 struct btrfs_file_extent_item);
@@ -284,6 +286,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
284 struct btrfs_ordered_sum *sums; 286 struct btrfs_ordered_sum *sums;
285 struct btrfs_sector_sum *sector_sum; 287 struct btrfs_sector_sum *sector_sum;
286 struct btrfs_csum_item *item; 288 struct btrfs_csum_item *item;
289 LIST_HEAD(tmplist);
287 unsigned long offset; 290 unsigned long offset;
288 int ret; 291 int ret;
289 size_t size; 292 size_t size;
@@ -358,7 +361,10 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
358 MAX_ORDERED_SUM_BYTES(root)); 361 MAX_ORDERED_SUM_BYTES(root));
359 sums = kzalloc(btrfs_ordered_sum_size(root, size), 362 sums = kzalloc(btrfs_ordered_sum_size(root, size),
360 GFP_NOFS); 363 GFP_NOFS);
361 BUG_ON(!sums); 364 if (!sums) {
365 ret = -ENOMEM;
366 goto fail;
367 }
362 368
363 sector_sum = sums->sums; 369 sector_sum = sums->sums;
364 sums->bytenr = start; 370 sums->bytenr = start;
@@ -380,12 +386,19 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
380 offset += csum_size; 386 offset += csum_size;
381 sector_sum++; 387 sector_sum++;
382 } 388 }
383 list_add_tail(&sums->list, list); 389 list_add_tail(&sums->list, &tmplist);
384 } 390 }
385 path->slots[0]++; 391 path->slots[0]++;
386 } 392 }
387 ret = 0; 393 ret = 0;
388fail: 394fail:
395 while (ret < 0 && !list_empty(&tmplist)) {
396 sums = list_entry(&tmplist, struct btrfs_ordered_sum, list);
397 list_del(&sums->list);
398 kfree(sums);
399 }
400 list_splice_tail(&tmplist, list);
401
389 btrfs_free_path(path); 402 btrfs_free_path(path);
390 return ret; 403 return ret;
391} 404}
@@ -420,7 +433,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
420 offset = page_offset(bvec->bv_page) + bvec->bv_offset; 433 offset = page_offset(bvec->bv_page) + bvec->bv_offset;
421 434
422 ordered = btrfs_lookup_ordered_extent(inode, offset); 435 ordered = btrfs_lookup_ordered_extent(inode, offset);
423 BUG_ON(!ordered); 436 BUG_ON(!ordered); /* Logic error */
424 sums->bytenr = ordered->start; 437 sums->bytenr = ordered->start;
425 438
426 while (bio_index < bio->bi_vcnt) { 439 while (bio_index < bio->bi_vcnt) {
@@ -439,11 +452,11 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
439 452
440 sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), 453 sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
441 GFP_NOFS); 454 GFP_NOFS);
442 BUG_ON(!sums); 455 BUG_ON(!sums); /* -ENOMEM */
443 sector_sum = sums->sums; 456 sector_sum = sums->sums;
444 sums->len = bytes_left; 457 sums->len = bytes_left;
445 ordered = btrfs_lookup_ordered_extent(inode, offset); 458 ordered = btrfs_lookup_ordered_extent(inode, offset);
446 BUG_ON(!ordered); 459 BUG_ON(!ordered); /* Logic error */
447 sums->bytenr = ordered->start; 460 sums->bytenr = ordered->start;
448 } 461 }
449 462
@@ -483,18 +496,17 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
483 * This calls btrfs_truncate_item with the correct args based on the 496 * This calls btrfs_truncate_item with the correct args based on the
484 * overlap, and fixes up the key as required. 497 * overlap, and fixes up the key as required.
485 */ 498 */
486static noinline int truncate_one_csum(struct btrfs_trans_handle *trans, 499static noinline void truncate_one_csum(struct btrfs_trans_handle *trans,
487 struct btrfs_root *root, 500 struct btrfs_root *root,
488 struct btrfs_path *path, 501 struct btrfs_path *path,
489 struct btrfs_key *key, 502 struct btrfs_key *key,
490 u64 bytenr, u64 len) 503 u64 bytenr, u64 len)
491{ 504{
492 struct extent_buffer *leaf; 505 struct extent_buffer *leaf;
493 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); 506 u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
494 u64 csum_end; 507 u64 csum_end;
495 u64 end_byte = bytenr + len; 508 u64 end_byte = bytenr + len;
496 u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits; 509 u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits;
497 int ret;
498 510
499 leaf = path->nodes[0]; 511 leaf = path->nodes[0];
500 csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size; 512 csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
@@ -510,7 +522,7 @@ static noinline int truncate_one_csum(struct btrfs_trans_handle *trans,
510 */ 522 */
511 u32 new_size = (bytenr - key->offset) >> blocksize_bits; 523 u32 new_size = (bytenr - key->offset) >> blocksize_bits;
512 new_size *= csum_size; 524 new_size *= csum_size;
513 ret = btrfs_truncate_item(trans, root, path, new_size, 1); 525 btrfs_truncate_item(trans, root, path, new_size, 1);
514 } else if (key->offset >= bytenr && csum_end > end_byte && 526 } else if (key->offset >= bytenr && csum_end > end_byte &&
515 end_byte > key->offset) { 527 end_byte > key->offset) {
516 /* 528 /*
@@ -522,15 +534,13 @@ static noinline int truncate_one_csum(struct btrfs_trans_handle *trans,
522 u32 new_size = (csum_end - end_byte) >> blocksize_bits; 534 u32 new_size = (csum_end - end_byte) >> blocksize_bits;
523 new_size *= csum_size; 535 new_size *= csum_size;
524 536
525 ret = btrfs_truncate_item(trans, root, path, new_size, 0); 537 btrfs_truncate_item(trans, root, path, new_size, 0);
526 538
527 key->offset = end_byte; 539 key->offset = end_byte;
528 ret = btrfs_set_item_key_safe(trans, root, path, key); 540 btrfs_set_item_key_safe(trans, root, path, key);
529 BUG_ON(ret);
530 } else { 541 } else {
531 BUG(); 542 BUG();
532 } 543 }
533 return 0;
534} 544}
535 545
536/* 546/*
@@ -635,13 +645,14 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
635 * item changed size or key 645 * item changed size or key
636 */ 646 */
637 ret = btrfs_split_item(trans, root, path, &key, offset); 647 ret = btrfs_split_item(trans, root, path, &key, offset);
638 BUG_ON(ret && ret != -EAGAIN); 648 if (ret && ret != -EAGAIN) {
649 btrfs_abort_transaction(trans, root, ret);
650 goto out;
651 }
639 652
640 key.offset = end_byte - 1; 653 key.offset = end_byte - 1;
641 } else { 654 } else {
642 ret = truncate_one_csum(trans, root, path, 655 truncate_one_csum(trans, root, path, &key, bytenr, len);
643 &key, bytenr, len);
644 BUG_ON(ret);
645 if (key.offset < bytenr) 656 if (key.offset < bytenr)
646 break; 657 break;
647 } 658 }
@@ -772,7 +783,7 @@ again:
772 if (diff != csum_size) 783 if (diff != csum_size)
773 goto insert; 784 goto insert;
774 785
775 ret = btrfs_extend_item(trans, root, path, diff); 786 btrfs_extend_item(trans, root, path, diff);
776 goto csum; 787 goto csum;
777 } 788 }
778 789