diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 57 |
1 files changed, 32 insertions, 25 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index f84b5f6991cc..4c6e0c15754d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -76,9 +76,8 @@ static noinline int create_subvol(struct btrfs_root *root, char *name, | |||
76 | if (ret) | 76 | if (ret) |
77 | goto fail; | 77 | goto fail; |
78 | 78 | ||
79 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | 79 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, 0, |
80 | objectid, trans->transid, 0, 0, | 80 | objectid, trans->transid, 0, 0, 0); |
81 | 0, 0); | ||
82 | if (IS_ERR(leaf)) { | 81 | if (IS_ERR(leaf)) { |
83 | ret = PTR_ERR(leaf); | 82 | ret = PTR_ERR(leaf); |
84 | goto fail; | 83 | goto fail; |
@@ -525,13 +524,10 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd) | |||
525 | struct file *src_file; | 524 | struct file *src_file; |
526 | struct inode *src; | 525 | struct inode *src; |
527 | struct btrfs_trans_handle *trans; | 526 | struct btrfs_trans_handle *trans; |
528 | struct btrfs_ordered_extent *ordered; | ||
529 | struct btrfs_path *path; | 527 | struct btrfs_path *path; |
530 | struct extent_buffer *leaf; | 528 | struct extent_buffer *leaf; |
531 | char *buf; | 529 | char *buf; |
532 | struct btrfs_key key; | 530 | struct btrfs_key key; |
533 | struct btrfs_key new_key; | ||
534 | u32 size; | ||
535 | u32 nritems; | 531 | u32 nritems; |
536 | int slot; | 532 | int slot; |
537 | int ret; | 533 | int ret; |
@@ -576,6 +572,7 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd) | |||
576 | /* do any pending delalloc/csum calc on src, one way or | 572 | /* do any pending delalloc/csum calc on src, one way or |
577 | another, and lock file content */ | 573 | another, and lock file content */ |
578 | while (1) { | 574 | while (1) { |
575 | struct btrfs_ordered_extent *ordered; | ||
579 | lock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS); | 576 | lock_extent(&BTRFS_I(src)->io_tree, 0, (u64)-1, GFP_NOFS); |
580 | ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); | 577 | ordered = btrfs_lookup_first_ordered_extent(inode, (u64)-1); |
581 | if (BTRFS_I(src)->delalloc_bytes == 0 && !ordered) | 578 | if (BTRFS_I(src)->delalloc_bytes == 0 && !ordered) |
@@ -619,6 +616,32 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd) | |||
619 | key.objectid != src->i_ino) | 616 | key.objectid != src->i_ino) |
620 | break; | 617 | break; |
621 | 618 | ||
619 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY || | ||
620 | btrfs_key_type(&key) == BTRFS_CSUM_ITEM_KEY) { | ||
621 | u32 size; | ||
622 | struct btrfs_key new_key; | ||
623 | |||
624 | size = btrfs_item_size_nr(leaf, slot); | ||
625 | read_extent_buffer(leaf, buf, | ||
626 | btrfs_item_ptr_offset(leaf, slot), | ||
627 | size); | ||
628 | btrfs_release_path(root, path); | ||
629 | |||
630 | memcpy(&new_key, &key, sizeof(new_key)); | ||
631 | new_key.objectid = inode->i_ino; | ||
632 | ret = btrfs_insert_empty_item(trans, root, path, | ||
633 | &new_key, size); | ||
634 | if (ret) | ||
635 | goto out; | ||
636 | |||
637 | leaf = path->nodes[0]; | ||
638 | slot = path->slots[0]; | ||
639 | write_extent_buffer(leaf, buf, | ||
640 | btrfs_item_ptr_offset(leaf, slot), | ||
641 | size); | ||
642 | btrfs_mark_buffer_dirty(leaf); | ||
643 | } | ||
644 | |||
622 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { | 645 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) { |
623 | struct btrfs_file_extent_item *extent; | 646 | struct btrfs_file_extent_item *extent; |
624 | int found_type; | 647 | int found_type; |
@@ -634,31 +657,15 @@ long btrfs_ioctl_clone(struct file *file, unsigned long src_fd) | |||
634 | /* ds == 0 means there's a hole */ | 657 | /* ds == 0 means there's a hole */ |
635 | if (ds != 0) { | 658 | if (ds != 0) { |
636 | ret = btrfs_inc_extent_ref(trans, root, | 659 | ret = btrfs_inc_extent_ref(trans, root, |
637 | ds, dl, | 660 | ds, dl, leaf->start, |
638 | root->root_key.objectid, | 661 | root->root_key.objectid, |
639 | trans->transid, | 662 | trans->transid, |
640 | inode->i_ino, key.offset); | 663 | inode->i_ino, key.offset); |
641 | if (ret) | 664 | BUG_ON(ret); |
642 | goto out; | ||
643 | } | 665 | } |
644 | } | 666 | } |
645 | } | 667 | } |
646 | 668 | btrfs_release_path(root, path); | |
647 | if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY || | ||
648 | btrfs_key_type(&key) == BTRFS_CSUM_ITEM_KEY) { | ||
649 | size = btrfs_item_size_nr(leaf, slot); | ||
650 | read_extent_buffer(leaf, buf, | ||
651 | btrfs_item_ptr_offset(leaf, slot), | ||
652 | size); | ||
653 | btrfs_release_path(root, path); | ||
654 | memcpy(&new_key, &key, sizeof(new_key)); | ||
655 | new_key.objectid = inode->i_ino; | ||
656 | ret = btrfs_insert_item(trans, root, &new_key, | ||
657 | buf, size); | ||
658 | BUG_ON(ret); | ||
659 | } else { | ||
660 | btrfs_release_path(root, path); | ||
661 | } | ||
662 | key.offset++; | 669 | key.offset++; |
663 | } | 670 | } |
664 | ret = 0; | 671 | ret = 0; |