diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 261 |
1 files changed, 206 insertions, 55 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b0134892dc70..e79ff6b90cb7 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -59,6 +59,32 @@ | |||
59 | #include "props.h" | 59 | #include "props.h" |
60 | #include "sysfs.h" | 60 | #include "sysfs.h" |
61 | 61 | ||
62 | #ifdef CONFIG_64BIT | ||
63 | /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI | ||
64 | * structures are incorrect, as the timespec structure from userspace | ||
65 | * is 4 bytes too small. We define these alternatives here to teach | ||
66 | * the kernel about the 32-bit struct packing. | ||
67 | */ | ||
68 | struct btrfs_ioctl_timespec_32 { | ||
69 | __u64 sec; | ||
70 | __u32 nsec; | ||
71 | } __attribute__ ((__packed__)); | ||
72 | |||
73 | struct btrfs_ioctl_received_subvol_args_32 { | ||
74 | char uuid[BTRFS_UUID_SIZE]; /* in */ | ||
75 | __u64 stransid; /* in */ | ||
76 | __u64 rtransid; /* out */ | ||
77 | struct btrfs_ioctl_timespec_32 stime; /* in */ | ||
78 | struct btrfs_ioctl_timespec_32 rtime; /* out */ | ||
79 | __u64 flags; /* in */ | ||
80 | __u64 reserved[16]; /* in */ | ||
81 | } __attribute__ ((__packed__)); | ||
82 | |||
83 | #define BTRFS_IOC_SET_RECEIVED_SUBVOL_32 _IOWR(BTRFS_IOCTL_MAGIC, 37, \ | ||
84 | struct btrfs_ioctl_received_subvol_args_32) | ||
85 | #endif | ||
86 | |||
87 | |||
62 | static int btrfs_clone(struct inode *src, struct inode *inode, | 88 | static int btrfs_clone(struct inode *src, struct inode *inode, |
63 | u64 off, u64 olen, u64 olen_aligned, u64 destoff); | 89 | u64 off, u64 olen, u64 olen_aligned, u64 destoff); |
64 | 90 | ||
@@ -585,6 +611,23 @@ fail: | |||
585 | return ret; | 611 | return ret; |
586 | } | 612 | } |
587 | 613 | ||
614 | static void btrfs_wait_nocow_write(struct btrfs_root *root) | ||
615 | { | ||
616 | s64 writers; | ||
617 | DEFINE_WAIT(wait); | ||
618 | |||
619 | do { | ||
620 | prepare_to_wait(&root->subv_writers->wait, &wait, | ||
621 | TASK_UNINTERRUPTIBLE); | ||
622 | |||
623 | writers = percpu_counter_sum(&root->subv_writers->counter); | ||
624 | if (writers) | ||
625 | schedule(); | ||
626 | |||
627 | finish_wait(&root->subv_writers->wait, &wait); | ||
628 | } while (writers); | ||
629 | } | ||
630 | |||
588 | static int create_snapshot(struct btrfs_root *root, struct inode *dir, | 631 | static int create_snapshot(struct btrfs_root *root, struct inode *dir, |
589 | struct dentry *dentry, char *name, int namelen, | 632 | struct dentry *dentry, char *name, int namelen, |
590 | u64 *async_transid, bool readonly, | 633 | u64 *async_transid, bool readonly, |
@@ -598,15 +641,21 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, | |||
598 | if (!root->ref_cows) | 641 | if (!root->ref_cows) |
599 | return -EINVAL; | 642 | return -EINVAL; |
600 | 643 | ||
644 | atomic_inc(&root->will_be_snapshoted); | ||
645 | smp_mb__after_atomic_inc(); | ||
646 | btrfs_wait_nocow_write(root); | ||
647 | |||
601 | ret = btrfs_start_delalloc_inodes(root, 0); | 648 | ret = btrfs_start_delalloc_inodes(root, 0); |
602 | if (ret) | 649 | if (ret) |
603 | return ret; | 650 | goto out; |
604 | 651 | ||
605 | btrfs_wait_ordered_extents(root, -1); | 652 | btrfs_wait_ordered_extents(root, -1); |
606 | 653 | ||
607 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); | 654 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); |
608 | if (!pending_snapshot) | 655 | if (!pending_snapshot) { |
609 | return -ENOMEM; | 656 | ret = -ENOMEM; |
657 | goto out; | ||
658 | } | ||
610 | 659 | ||
611 | btrfs_init_block_rsv(&pending_snapshot->block_rsv, | 660 | btrfs_init_block_rsv(&pending_snapshot->block_rsv, |
612 | BTRFS_BLOCK_RSV_TEMP); | 661 | BTRFS_BLOCK_RSV_TEMP); |
@@ -623,7 +672,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, | |||
623 | &pending_snapshot->qgroup_reserved, | 672 | &pending_snapshot->qgroup_reserved, |
624 | false); | 673 | false); |
625 | if (ret) | 674 | if (ret) |
626 | goto out; | 675 | goto free; |
627 | 676 | ||
628 | pending_snapshot->dentry = dentry; | 677 | pending_snapshot->dentry = dentry; |
629 | pending_snapshot->root = root; | 678 | pending_snapshot->root = root; |
@@ -674,8 +723,10 @@ fail: | |||
674 | btrfs_subvolume_release_metadata(BTRFS_I(dir)->root, | 723 | btrfs_subvolume_release_metadata(BTRFS_I(dir)->root, |
675 | &pending_snapshot->block_rsv, | 724 | &pending_snapshot->block_rsv, |
676 | pending_snapshot->qgroup_reserved); | 725 | pending_snapshot->qgroup_reserved); |
677 | out: | 726 | free: |
678 | kfree(pending_snapshot); | 727 | kfree(pending_snapshot); |
728 | out: | ||
729 | atomic_dec(&root->will_be_snapshoted); | ||
679 | return ret; | 730 | return ret; |
680 | } | 731 | } |
681 | 732 | ||
@@ -884,12 +935,14 @@ static int find_new_extents(struct btrfs_root *root, | |||
884 | min_key.type = BTRFS_EXTENT_DATA_KEY; | 935 | min_key.type = BTRFS_EXTENT_DATA_KEY; |
885 | min_key.offset = *off; | 936 | min_key.offset = *off; |
886 | 937 | ||
887 | path->keep_locks = 1; | ||
888 | |||
889 | while (1) { | 938 | while (1) { |
939 | path->keep_locks = 1; | ||
890 | ret = btrfs_search_forward(root, &min_key, path, newer_than); | 940 | ret = btrfs_search_forward(root, &min_key, path, newer_than); |
891 | if (ret != 0) | 941 | if (ret != 0) |
892 | goto none; | 942 | goto none; |
943 | path->keep_locks = 0; | ||
944 | btrfs_unlock_up_safe(path, 1); | ||
945 | process_slot: | ||
893 | if (min_key.objectid != ino) | 946 | if (min_key.objectid != ino) |
894 | goto none; | 947 | goto none; |
895 | if (min_key.type != BTRFS_EXTENT_DATA_KEY) | 948 | if (min_key.type != BTRFS_EXTENT_DATA_KEY) |
@@ -908,6 +961,12 @@ static int find_new_extents(struct btrfs_root *root, | |||
908 | return 0; | 961 | return 0; |
909 | } | 962 | } |
910 | 963 | ||
964 | path->slots[0]++; | ||
965 | if (path->slots[0] < btrfs_header_nritems(leaf)) { | ||
966 | btrfs_item_key_to_cpu(leaf, &min_key, path->slots[0]); | ||
967 | goto process_slot; | ||
968 | } | ||
969 | |||
911 | if (min_key.offset == (u64)-1) | 970 | if (min_key.offset == (u64)-1) |
912 | goto none; | 971 | goto none; |
913 | 972 | ||
@@ -935,10 +994,13 @@ static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start) | |||
935 | read_unlock(&em_tree->lock); | 994 | read_unlock(&em_tree->lock); |
936 | 995 | ||
937 | if (!em) { | 996 | if (!em) { |
997 | struct extent_state *cached = NULL; | ||
998 | u64 end = start + len - 1; | ||
999 | |||
938 | /* get the big lock and read metadata off disk */ | 1000 | /* get the big lock and read metadata off disk */ |
939 | lock_extent(io_tree, start, start + len - 1); | 1001 | lock_extent_bits(io_tree, start, end, 0, &cached); |
940 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); | 1002 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); |
941 | unlock_extent(io_tree, start, start + len - 1); | 1003 | unlock_extent_cached(io_tree, start, end, &cached, GFP_NOFS); |
942 | 1004 | ||
943 | if (IS_ERR(em)) | 1005 | if (IS_ERR(em)) |
944 | return NULL; | 1006 | return NULL; |
@@ -957,7 +1019,8 @@ static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em) | |||
957 | return false; | 1019 | return false; |
958 | 1020 | ||
959 | next = defrag_lookup_extent(inode, em->start + em->len); | 1021 | next = defrag_lookup_extent(inode, em->start + em->len); |
960 | if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE) | 1022 | if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE || |
1023 | (em->block_start + em->block_len == next->block_start)) | ||
961 | ret = false; | 1024 | ret = false; |
962 | 1025 | ||
963 | free_extent_map(next); | 1026 | free_extent_map(next); |
@@ -1076,10 +1139,12 @@ again: | |||
1076 | page_start = page_offset(page); | 1139 | page_start = page_offset(page); |
1077 | page_end = page_start + PAGE_CACHE_SIZE - 1; | 1140 | page_end = page_start + PAGE_CACHE_SIZE - 1; |
1078 | while (1) { | 1141 | while (1) { |
1079 | lock_extent(tree, page_start, page_end); | 1142 | lock_extent_bits(tree, page_start, page_end, |
1143 | 0, &cached_state); | ||
1080 | ordered = btrfs_lookup_ordered_extent(inode, | 1144 | ordered = btrfs_lookup_ordered_extent(inode, |
1081 | page_start); | 1145 | page_start); |
1082 | unlock_extent(tree, page_start, page_end); | 1146 | unlock_extent_cached(tree, page_start, page_end, |
1147 | &cached_state, GFP_NOFS); | ||
1083 | if (!ordered) | 1148 | if (!ordered) |
1084 | break; | 1149 | break; |
1085 | 1150 | ||
@@ -1356,8 +1421,12 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1356 | } | 1421 | } |
1357 | } | 1422 | } |
1358 | 1423 | ||
1359 | if ((range->flags & BTRFS_DEFRAG_RANGE_START_IO)) | 1424 | if ((range->flags & BTRFS_DEFRAG_RANGE_START_IO)) { |
1360 | filemap_flush(inode->i_mapping); | 1425 | filemap_flush(inode->i_mapping); |
1426 | if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT, | ||
1427 | &BTRFS_I(inode)->runtime_flags)) | ||
1428 | filemap_flush(inode->i_mapping); | ||
1429 | } | ||
1361 | 1430 | ||
1362 | if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) { | 1431 | if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) { |
1363 | /* the filemap_flush will queue IO into the worker threads, but | 1432 | /* the filemap_flush will queue IO into the worker threads, but |
@@ -1403,6 +1472,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1403 | struct btrfs_trans_handle *trans; | 1472 | struct btrfs_trans_handle *trans; |
1404 | struct btrfs_device *device = NULL; | 1473 | struct btrfs_device *device = NULL; |
1405 | char *sizestr; | 1474 | char *sizestr; |
1475 | char *retptr; | ||
1406 | char *devstr = NULL; | 1476 | char *devstr = NULL; |
1407 | int ret = 0; | 1477 | int ret = 0; |
1408 | int mod = 0; | 1478 | int mod = 0; |
@@ -1470,8 +1540,8 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1470 | mod = 1; | 1540 | mod = 1; |
1471 | sizestr++; | 1541 | sizestr++; |
1472 | } | 1542 | } |
1473 | new_size = memparse(sizestr, NULL); | 1543 | new_size = memparse(sizestr, &retptr); |
1474 | if (new_size == 0) { | 1544 | if (*retptr != '\0' || new_size == 0) { |
1475 | ret = -EINVAL; | 1545 | ret = -EINVAL; |
1476 | goto out_free; | 1546 | goto out_free; |
1477 | } | 1547 | } |
@@ -1573,7 +1643,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file, | |||
1573 | if (src_inode->i_sb != file_inode(file)->i_sb) { | 1643 | if (src_inode->i_sb != file_inode(file)->i_sb) { |
1574 | btrfs_info(BTRFS_I(src_inode)->root->fs_info, | 1644 | btrfs_info(BTRFS_I(src_inode)->root->fs_info, |
1575 | "Snapshot src from another FS"); | 1645 | "Snapshot src from another FS"); |
1576 | ret = -EINVAL; | 1646 | ret = -EXDEV; |
1577 | } else if (!inode_owner_or_capable(src_inode)) { | 1647 | } else if (!inode_owner_or_capable(src_inode)) { |
1578 | /* | 1648 | /* |
1579 | * Subvolume creation is not restricted, but snapshots | 1649 | * Subvolume creation is not restricted, but snapshots |
@@ -1797,7 +1867,9 @@ static noinline int may_destroy_subvol(struct btrfs_root *root) | |||
1797 | if (di && !IS_ERR(di)) { | 1867 | if (di && !IS_ERR(di)) { |
1798 | btrfs_dir_item_key_to_cpu(path->nodes[0], di, &key); | 1868 | btrfs_dir_item_key_to_cpu(path->nodes[0], di, &key); |
1799 | if (key.objectid == root->root_key.objectid) { | 1869 | if (key.objectid == root->root_key.objectid) { |
1800 | ret = -ENOTEMPTY; | 1870 | ret = -EPERM; |
1871 | btrfs_err(root->fs_info, "deleting default subvolume " | ||
1872 | "%llu is not allowed", key.objectid); | ||
1801 | goto out; | 1873 | goto out; |
1802 | } | 1874 | } |
1803 | btrfs_release_path(path); | 1875 | btrfs_release_path(path); |
@@ -2994,8 +3066,9 @@ process_slot: | |||
2994 | new_key.offset + datal, | 3066 | new_key.offset + datal, |
2995 | 1); | 3067 | 1); |
2996 | if (ret) { | 3068 | if (ret) { |
2997 | btrfs_abort_transaction(trans, root, | 3069 | if (ret != -EINVAL) |
2998 | ret); | 3070 | btrfs_abort_transaction(trans, |
3071 | root, ret); | ||
2999 | btrfs_end_transaction(trans, root); | 3072 | btrfs_end_transaction(trans, root); |
3000 | goto out; | 3073 | goto out; |
3001 | } | 3074 | } |
@@ -3068,8 +3141,9 @@ process_slot: | |||
3068 | new_key.offset + datal, | 3141 | new_key.offset + datal, |
3069 | 1); | 3142 | 1); |
3070 | if (ret) { | 3143 | if (ret) { |
3071 | btrfs_abort_transaction(trans, root, | 3144 | if (ret != -EINVAL) |
3072 | ret); | 3145 | btrfs_abort_transaction(trans, |
3146 | root, ret); | ||
3073 | btrfs_end_transaction(trans, root); | 3147 | btrfs_end_transaction(trans, root); |
3074 | goto out; | 3148 | goto out; |
3075 | } | 3149 | } |
@@ -3153,8 +3227,9 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
3153 | * decompress into destination's address_space (the file offset | 3227 | * decompress into destination's address_space (the file offset |
3154 | * may change, so source mapping won't do), then recompress (or | 3228 | * may change, so source mapping won't do), then recompress (or |
3155 | * otherwise reinsert) a subrange. | 3229 | * otherwise reinsert) a subrange. |
3156 | * - allow ranges within the same file to be cloned (provided | 3230 | * |
3157 | * they don't overlap)? | 3231 | * - split destination inode's inline extents. The inline extents can |
3232 | * be either compressed or non-compressed. | ||
3158 | */ | 3233 | */ |
3159 | 3234 | ||
3160 | /* the destination must be opened for writing */ | 3235 | /* the destination must be opened for writing */ |
@@ -3465,6 +3540,11 @@ static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
3465 | up_read(&info->groups_sem); | 3540 | up_read(&info->groups_sem); |
3466 | } | 3541 | } |
3467 | 3542 | ||
3543 | /* | ||
3544 | * Global block reserve, exported as a space_info | ||
3545 | */ | ||
3546 | slot_count++; | ||
3547 | |||
3468 | /* space_slots == 0 means they are asking for a count */ | 3548 | /* space_slots == 0 means they are asking for a count */ |
3469 | if (space_args.space_slots == 0) { | 3549 | if (space_args.space_slots == 0) { |
3470 | space_args.total_spaces = slot_count; | 3550 | space_args.total_spaces = slot_count; |
@@ -3523,6 +3603,21 @@ static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
3523 | up_read(&info->groups_sem); | 3603 | up_read(&info->groups_sem); |
3524 | } | 3604 | } |
3525 | 3605 | ||
3606 | /* | ||
3607 | * Add global block reserve | ||
3608 | */ | ||
3609 | if (slot_count) { | ||
3610 | struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv; | ||
3611 | |||
3612 | spin_lock(&block_rsv->lock); | ||
3613 | space.total_bytes = block_rsv->size; | ||
3614 | space.used_bytes = block_rsv->size - block_rsv->reserved; | ||
3615 | spin_unlock(&block_rsv->lock); | ||
3616 | space.flags = BTRFS_SPACE_INFO_GLOBAL_RSV; | ||
3617 | memcpy(dest, &space, sizeof(space)); | ||
3618 | space_args.total_spaces++; | ||
3619 | } | ||
3620 | |||
3526 | user_dest = (struct btrfs_ioctl_space_info __user *) | 3621 | user_dest = (struct btrfs_ioctl_space_info __user *) |
3527 | (arg + sizeof(struct btrfs_ioctl_space_args)); | 3622 | (arg + sizeof(struct btrfs_ioctl_space_args)); |
3528 | 3623 | ||
@@ -3537,20 +3632,6 @@ out: | |||
3537 | return ret; | 3632 | return ret; |
3538 | } | 3633 | } |
3539 | 3634 | ||
3540 | static long btrfs_ioctl_global_rsv(struct btrfs_root *root, void __user *arg) | ||
3541 | { | ||
3542 | struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv; | ||
3543 | u64 reserved; | ||
3544 | |||
3545 | spin_lock(&block_rsv->lock); | ||
3546 | reserved = block_rsv->reserved; | ||
3547 | spin_unlock(&block_rsv->lock); | ||
3548 | |||
3549 | if (arg && copy_to_user(arg, &reserved, sizeof(reserved))) | ||
3550 | return -EFAULT; | ||
3551 | return 0; | ||
3552 | } | ||
3553 | |||
3554 | /* | 3635 | /* |
3555 | * there are many ways the trans_start and trans_end ioctls can lead | 3636 | * there are many ways the trans_start and trans_end ioctls can lead |
3556 | * to deadlocks. They should only be used by applications that | 3637 | * to deadlocks. They should only be used by applications that |
@@ -4367,10 +4448,9 @@ static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg) | |||
4367 | return btrfs_qgroup_wait_for_completion(root->fs_info); | 4448 | return btrfs_qgroup_wait_for_completion(root->fs_info); |
4368 | } | 4449 | } |
4369 | 4450 | ||
4370 | static long btrfs_ioctl_set_received_subvol(struct file *file, | 4451 | static long _btrfs_ioctl_set_received_subvol(struct file *file, |
4371 | void __user *arg) | 4452 | struct btrfs_ioctl_received_subvol_args *sa) |
4372 | { | 4453 | { |
4373 | struct btrfs_ioctl_received_subvol_args *sa = NULL; | ||
4374 | struct inode *inode = file_inode(file); | 4454 | struct inode *inode = file_inode(file); |
4375 | struct btrfs_root *root = BTRFS_I(inode)->root; | 4455 | struct btrfs_root *root = BTRFS_I(inode)->root; |
4376 | struct btrfs_root_item *root_item = &root->root_item; | 4456 | struct btrfs_root_item *root_item = &root->root_item; |
@@ -4398,13 +4478,6 @@ static long btrfs_ioctl_set_received_subvol(struct file *file, | |||
4398 | goto out; | 4478 | goto out; |
4399 | } | 4479 | } |
4400 | 4480 | ||
4401 | sa = memdup_user(arg, sizeof(*sa)); | ||
4402 | if (IS_ERR(sa)) { | ||
4403 | ret = PTR_ERR(sa); | ||
4404 | sa = NULL; | ||
4405 | goto out; | ||
4406 | } | ||
4407 | |||
4408 | /* | 4481 | /* |
4409 | * 1 - root item | 4482 | * 1 - root item |
4410 | * 2 - uuid items (received uuid + subvol uuid) | 4483 | * 2 - uuid items (received uuid + subvol uuid) |
@@ -4458,14 +4531,90 @@ static long btrfs_ioctl_set_received_subvol(struct file *file, | |||
4458 | goto out; | 4531 | goto out; |
4459 | } | 4532 | } |
4460 | 4533 | ||
4534 | out: | ||
4535 | up_write(&root->fs_info->subvol_sem); | ||
4536 | mnt_drop_write_file(file); | ||
4537 | return ret; | ||
4538 | } | ||
4539 | |||
4540 | #ifdef CONFIG_64BIT | ||
4541 | static long btrfs_ioctl_set_received_subvol_32(struct file *file, | ||
4542 | void __user *arg) | ||
4543 | { | ||
4544 | struct btrfs_ioctl_received_subvol_args_32 *args32 = NULL; | ||
4545 | struct btrfs_ioctl_received_subvol_args *args64 = NULL; | ||
4546 | int ret = 0; | ||
4547 | |||
4548 | args32 = memdup_user(arg, sizeof(*args32)); | ||
4549 | if (IS_ERR(args32)) { | ||
4550 | ret = PTR_ERR(args32); | ||
4551 | args32 = NULL; | ||
4552 | goto out; | ||
4553 | } | ||
4554 | |||
4555 | args64 = kmalloc(sizeof(*args64), GFP_NOFS); | ||
4556 | if (!args64) { | ||
4557 | ret = -ENOMEM; | ||
4558 | goto out; | ||
4559 | } | ||
4560 | |||
4561 | memcpy(args64->uuid, args32->uuid, BTRFS_UUID_SIZE); | ||
4562 | args64->stransid = args32->stransid; | ||
4563 | args64->rtransid = args32->rtransid; | ||
4564 | args64->stime.sec = args32->stime.sec; | ||
4565 | args64->stime.nsec = args32->stime.nsec; | ||
4566 | args64->rtime.sec = args32->rtime.sec; | ||
4567 | args64->rtime.nsec = args32->rtime.nsec; | ||
4568 | args64->flags = args32->flags; | ||
4569 | |||
4570 | ret = _btrfs_ioctl_set_received_subvol(file, args64); | ||
4571 | if (ret) | ||
4572 | goto out; | ||
4573 | |||
4574 | memcpy(args32->uuid, args64->uuid, BTRFS_UUID_SIZE); | ||
4575 | args32->stransid = args64->stransid; | ||
4576 | args32->rtransid = args64->rtransid; | ||
4577 | args32->stime.sec = args64->stime.sec; | ||
4578 | args32->stime.nsec = args64->stime.nsec; | ||
4579 | args32->rtime.sec = args64->rtime.sec; | ||
4580 | args32->rtime.nsec = args64->rtime.nsec; | ||
4581 | args32->flags = args64->flags; | ||
4582 | |||
4583 | ret = copy_to_user(arg, args32, sizeof(*args32)); | ||
4584 | if (ret) | ||
4585 | ret = -EFAULT; | ||
4586 | |||
4587 | out: | ||
4588 | kfree(args32); | ||
4589 | kfree(args64); | ||
4590 | return ret; | ||
4591 | } | ||
4592 | #endif | ||
4593 | |||
4594 | static long btrfs_ioctl_set_received_subvol(struct file *file, | ||
4595 | void __user *arg) | ||
4596 | { | ||
4597 | struct btrfs_ioctl_received_subvol_args *sa = NULL; | ||
4598 | int ret = 0; | ||
4599 | |||
4600 | sa = memdup_user(arg, sizeof(*sa)); | ||
4601 | if (IS_ERR(sa)) { | ||
4602 | ret = PTR_ERR(sa); | ||
4603 | sa = NULL; | ||
4604 | goto out; | ||
4605 | } | ||
4606 | |||
4607 | ret = _btrfs_ioctl_set_received_subvol(file, sa); | ||
4608 | |||
4609 | if (ret) | ||
4610 | goto out; | ||
4611 | |||
4461 | ret = copy_to_user(arg, sa, sizeof(*sa)); | 4612 | ret = copy_to_user(arg, sa, sizeof(*sa)); |
4462 | if (ret) | 4613 | if (ret) |
4463 | ret = -EFAULT; | 4614 | ret = -EFAULT; |
4464 | 4615 | ||
4465 | out: | 4616 | out: |
4466 | kfree(sa); | 4617 | kfree(sa); |
4467 | up_write(&root->fs_info->subvol_sem); | ||
4468 | mnt_drop_write_file(file); | ||
4469 | return ret; | 4618 | return ret; |
4470 | } | 4619 | } |
4471 | 4620 | ||
@@ -4525,7 +4674,7 @@ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) | |||
4525 | spin_lock(&root->fs_info->super_lock); | 4674 | spin_lock(&root->fs_info->super_lock); |
4526 | strcpy(super_block->label, label); | 4675 | strcpy(super_block->label, label); |
4527 | spin_unlock(&root->fs_info->super_lock); | 4676 | spin_unlock(&root->fs_info->super_lock); |
4528 | ret = btrfs_end_transaction(trans, root); | 4677 | ret = btrfs_commit_transaction(trans, root); |
4529 | 4678 | ||
4530 | out_unlock: | 4679 | out_unlock: |
4531 | mnt_drop_write_file(file); | 4680 | mnt_drop_write_file(file); |
@@ -4668,7 +4817,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
4668 | if (ret) | 4817 | if (ret) |
4669 | return ret; | 4818 | return ret; |
4670 | 4819 | ||
4671 | trans = btrfs_start_transaction(root, 1); | 4820 | trans = btrfs_start_transaction(root, 0); |
4672 | if (IS_ERR(trans)) | 4821 | if (IS_ERR(trans)) |
4673 | return PTR_ERR(trans); | 4822 | return PTR_ERR(trans); |
4674 | 4823 | ||
@@ -4689,7 +4838,7 @@ static int btrfs_ioctl_set_features(struct file *file, void __user *arg) | |||
4689 | btrfs_set_super_incompat_flags(super_block, newflags); | 4838 | btrfs_set_super_incompat_flags(super_block, newflags); |
4690 | spin_unlock(&root->fs_info->super_lock); | 4839 | spin_unlock(&root->fs_info->super_lock); |
4691 | 4840 | ||
4692 | return btrfs_end_transaction(trans, root); | 4841 | return btrfs_commit_transaction(trans, root); |
4693 | } | 4842 | } |
4694 | 4843 | ||
4695 | long btrfs_ioctl(struct file *file, unsigned int | 4844 | long btrfs_ioctl(struct file *file, unsigned int |
@@ -4757,12 +4906,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
4757 | return btrfs_ioctl_logical_to_ino(root, argp); | 4906 | return btrfs_ioctl_logical_to_ino(root, argp); |
4758 | case BTRFS_IOC_SPACE_INFO: | 4907 | case BTRFS_IOC_SPACE_INFO: |
4759 | return btrfs_ioctl_space_info(root, argp); | 4908 | return btrfs_ioctl_space_info(root, argp); |
4760 | case BTRFS_IOC_GLOBAL_RSV: | ||
4761 | return btrfs_ioctl_global_rsv(root, argp); | ||
4762 | case BTRFS_IOC_SYNC: { | 4909 | case BTRFS_IOC_SYNC: { |
4763 | int ret; | 4910 | int ret; |
4764 | 4911 | ||
4765 | ret = btrfs_start_delalloc_roots(root->fs_info, 0); | 4912 | ret = btrfs_start_delalloc_roots(root->fs_info, 0, -1); |
4766 | if (ret) | 4913 | if (ret) |
4767 | return ret; | 4914 | return ret; |
4768 | ret = btrfs_sync_fs(file->f_dentry->d_sb, 1); | 4915 | ret = btrfs_sync_fs(file->f_dentry->d_sb, 1); |
@@ -4786,6 +4933,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
4786 | return btrfs_ioctl_balance_progress(root, argp); | 4933 | return btrfs_ioctl_balance_progress(root, argp); |
4787 | case BTRFS_IOC_SET_RECEIVED_SUBVOL: | 4934 | case BTRFS_IOC_SET_RECEIVED_SUBVOL: |
4788 | return btrfs_ioctl_set_received_subvol(file, argp); | 4935 | return btrfs_ioctl_set_received_subvol(file, argp); |
4936 | #ifdef CONFIG_64BIT | ||
4937 | case BTRFS_IOC_SET_RECEIVED_SUBVOL_32: | ||
4938 | return btrfs_ioctl_set_received_subvol_32(file, argp); | ||
4939 | #endif | ||
4789 | case BTRFS_IOC_SEND: | 4940 | case BTRFS_IOC_SEND: |
4790 | return btrfs_ioctl_send(file, argp); | 4941 | return btrfs_ioctl_send(file, argp); |
4791 | case BTRFS_IOC_GET_DEV_STATS: | 4942 | case BTRFS_IOC_GET_DEV_STATS: |