diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 168 |
1 files changed, 110 insertions, 58 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 14f8e1faa46e..0e92e5763005 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include "locking.h" | 52 | #include "locking.h" |
53 | #include "inode-map.h" | 53 | #include "inode-map.h" |
54 | #include "backref.h" | 54 | #include "backref.h" |
55 | #include "rcu-string.h" | ||
55 | 56 | ||
56 | /* Mask out flags that are inappropriate for the given type of inode. */ | 57 | /* Mask out flags that are inappropriate for the given type of inode. */ |
57 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 58 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) |
@@ -261,6 +262,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
261 | } | 262 | } |
262 | 263 | ||
263 | btrfs_update_iflags(inode); | 264 | btrfs_update_iflags(inode); |
265 | inode_inc_iversion(inode); | ||
264 | inode->i_ctime = CURRENT_TIME; | 266 | inode->i_ctime = CURRENT_TIME; |
265 | ret = btrfs_update_inode(trans, root, inode); | 267 | ret = btrfs_update_inode(trans, root, inode); |
266 | 268 | ||
@@ -367,7 +369,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
367 | return PTR_ERR(trans); | 369 | return PTR_ERR(trans); |
368 | 370 | ||
369 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | 371 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
370 | 0, objectid, NULL, 0, 0, 0, 0); | 372 | 0, objectid, NULL, 0, 0, 0); |
371 | if (IS_ERR(leaf)) { | 373 | if (IS_ERR(leaf)) { |
372 | ret = PTR_ERR(leaf); | 374 | ret = PTR_ERR(leaf); |
373 | goto fail; | 375 | goto fail; |
@@ -784,39 +786,57 @@ none: | |||
784 | return -ENOENT; | 786 | return -ENOENT; |
785 | } | 787 | } |
786 | 788 | ||
787 | /* | 789 | static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start) |
788 | * Validaty check of prev em and next em: | ||
789 | * 1) no prev/next em | ||
790 | * 2) prev/next em is an hole/inline extent | ||
791 | */ | ||
792 | static int check_adjacent_extents(struct inode *inode, struct extent_map *em) | ||
793 | { | 790 | { |
794 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 791 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
795 | struct extent_map *prev = NULL, *next = NULL; | 792 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
796 | int ret = 0; | 793 | struct extent_map *em; |
794 | u64 len = PAGE_CACHE_SIZE; | ||
797 | 795 | ||
796 | /* | ||
797 | * hopefully we have this extent in the tree already, try without | ||
798 | * the full extent lock | ||
799 | */ | ||
798 | read_lock(&em_tree->lock); | 800 | read_lock(&em_tree->lock); |
799 | prev = lookup_extent_mapping(em_tree, em->start - 1, (u64)-1); | 801 | em = lookup_extent_mapping(em_tree, start, len); |
800 | next = lookup_extent_mapping(em_tree, em->start + em->len, (u64)-1); | ||
801 | read_unlock(&em_tree->lock); | 802 | read_unlock(&em_tree->lock); |
802 | 803 | ||
803 | if ((!prev || prev->block_start >= EXTENT_MAP_LAST_BYTE) && | 804 | if (!em) { |
804 | (!next || next->block_start >= EXTENT_MAP_LAST_BYTE)) | 805 | /* get the big lock and read metadata off disk */ |
805 | ret = 1; | 806 | lock_extent(io_tree, start, start + len - 1); |
806 | free_extent_map(prev); | 807 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); |
807 | free_extent_map(next); | 808 | unlock_extent(io_tree, start, start + len - 1); |
809 | |||
810 | if (IS_ERR(em)) | ||
811 | return NULL; | ||
812 | } | ||
813 | |||
814 | return em; | ||
815 | } | ||
808 | 816 | ||
817 | static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em) | ||
818 | { | ||
819 | struct extent_map *next; | ||
820 | bool ret = true; | ||
821 | |||
822 | /* this is the last extent */ | ||
823 | if (em->start + em->len >= i_size_read(inode)) | ||
824 | return false; | ||
825 | |||
826 | next = defrag_lookup_extent(inode, em->start + em->len); | ||
827 | if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE) | ||
828 | ret = false; | ||
829 | |||
830 | free_extent_map(next); | ||
809 | return ret; | 831 | return ret; |
810 | } | 832 | } |
811 | 833 | ||
812 | static int should_defrag_range(struct inode *inode, u64 start, u64 len, | 834 | static int should_defrag_range(struct inode *inode, u64 start, int thresh, |
813 | int thresh, u64 *last_len, u64 *skip, | 835 | u64 *last_len, u64 *skip, u64 *defrag_end) |
814 | u64 *defrag_end) | ||
815 | { | 836 | { |
816 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 837 | struct extent_map *em; |
817 | struct extent_map *em = NULL; | ||
818 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | ||
819 | int ret = 1; | 838 | int ret = 1; |
839 | bool next_mergeable = true; | ||
820 | 840 | ||
821 | /* | 841 | /* |
822 | * make sure that once we start defragging an extent, we keep on | 842 | * make sure that once we start defragging an extent, we keep on |
@@ -827,23 +847,9 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
827 | 847 | ||
828 | *skip = 0; | 848 | *skip = 0; |
829 | 849 | ||
830 | /* | 850 | em = defrag_lookup_extent(inode, start); |
831 | * hopefully we have this extent in the tree already, try without | 851 | if (!em) |
832 | * the full extent lock | 852 | return 0; |
833 | */ | ||
834 | read_lock(&em_tree->lock); | ||
835 | em = lookup_extent_mapping(em_tree, start, len); | ||
836 | read_unlock(&em_tree->lock); | ||
837 | |||
838 | if (!em) { | ||
839 | /* get the big lock and read metadata off disk */ | ||
840 | lock_extent(io_tree, start, start + len - 1); | ||
841 | em = btrfs_get_extent(inode, NULL, 0, start, len, 0); | ||
842 | unlock_extent(io_tree, start, start + len - 1); | ||
843 | |||
844 | if (IS_ERR(em)) | ||
845 | return 0; | ||
846 | } | ||
847 | 853 | ||
848 | /* this will cover holes, and inline extents */ | 854 | /* this will cover holes, and inline extents */ |
849 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { | 855 | if (em->block_start >= EXTENT_MAP_LAST_BYTE) { |
@@ -851,18 +857,15 @@ static int should_defrag_range(struct inode *inode, u64 start, u64 len, | |||
851 | goto out; | 857 | goto out; |
852 | } | 858 | } |
853 | 859 | ||
854 | /* If we have nothing to merge with us, just skip. */ | 860 | next_mergeable = defrag_check_next_extent(inode, em); |
855 | if (check_adjacent_extents(inode, em)) { | ||
856 | ret = 0; | ||
857 | goto out; | ||
858 | } | ||
859 | 861 | ||
860 | /* | 862 | /* |
861 | * we hit a real extent, if it is big don't bother defragging it again | 863 | * we hit a real extent, if it is big or the next extent is not a |
864 | * real extent, don't bother defragging it | ||
862 | */ | 865 | */ |
863 | if ((*last_len == 0 || *last_len >= thresh) && em->len >= thresh) | 866 | if ((*last_len == 0 || *last_len >= thresh) && |
867 | (em->len >= thresh || !next_mergeable)) | ||
864 | ret = 0; | 868 | ret = 0; |
865 | |||
866 | out: | 869 | out: |
867 | /* | 870 | /* |
868 | * last_len ends up being a counter of how many bytes we've defragged. | 871 | * last_len ends up being a counter of how many bytes we've defragged. |
@@ -1141,8 +1144,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1141 | break; | 1144 | break; |
1142 | 1145 | ||
1143 | if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, | 1146 | if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, |
1144 | PAGE_CACHE_SIZE, extent_thresh, | 1147 | extent_thresh, &last_len, &skip, |
1145 | &last_len, &skip, &defrag_end)) { | 1148 | &defrag_end)) { |
1146 | unsigned long next; | 1149 | unsigned long next; |
1147 | /* | 1150 | /* |
1148 | * the should_defrag function tells us how much to skip | 1151 | * the should_defrag function tells us how much to skip |
@@ -1303,6 +1306,14 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
1303 | ret = -EINVAL; | 1306 | ret = -EINVAL; |
1304 | goto out_free; | 1307 | goto out_free; |
1305 | } | 1308 | } |
1309 | if (device->fs_devices && device->fs_devices->seeding) { | ||
1310 | printk(KERN_INFO "btrfs: resizer unable to apply on " | ||
1311 | "seeding device %llu\n", | ||
1312 | (unsigned long long)devid); | ||
1313 | ret = -EINVAL; | ||
1314 | goto out_free; | ||
1315 | } | ||
1316 | |||
1306 | if (!strcmp(sizestr, "max")) | 1317 | if (!strcmp(sizestr, "max")) |
1307 | new_size = device->bdev->bd_inode->i_size; | 1318 | new_size = device->bdev->bd_inode->i_size; |
1308 | else { | 1319 | else { |
@@ -1344,8 +1355,9 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
1344 | do_div(new_size, root->sectorsize); | 1355 | do_div(new_size, root->sectorsize); |
1345 | new_size *= root->sectorsize; | 1356 | new_size *= root->sectorsize; |
1346 | 1357 | ||
1347 | printk(KERN_INFO "btrfs: new size for %s is %llu\n", | 1358 | printk_in_rcu(KERN_INFO "btrfs: new size for %s is %llu\n", |
1348 | device->name, (unsigned long long)new_size); | 1359 | rcu_str_deref(device->name), |
1360 | (unsigned long long)new_size); | ||
1349 | 1361 | ||
1350 | if (new_size > old_size) { | 1362 | if (new_size > old_size) { |
1351 | trans = btrfs_start_transaction(root, 0); | 1363 | trans = btrfs_start_transaction(root, 0); |
@@ -2262,10 +2274,17 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) | |||
2262 | di_args->bytes_used = dev->bytes_used; | 2274 | di_args->bytes_used = dev->bytes_used; |
2263 | di_args->total_bytes = dev->total_bytes; | 2275 | di_args->total_bytes = dev->total_bytes; |
2264 | memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); | 2276 | memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); |
2265 | if (dev->name) | 2277 | if (dev->name) { |
2266 | strncpy(di_args->path, dev->name, sizeof(di_args->path)); | 2278 | struct rcu_string *name; |
2267 | else | 2279 | |
2280 | rcu_read_lock(); | ||
2281 | name = rcu_dereference(dev->name); | ||
2282 | strncpy(di_args->path, name->str, sizeof(di_args->path)); | ||
2283 | rcu_read_unlock(); | ||
2284 | di_args->path[sizeof(di_args->path) - 1] = 0; | ||
2285 | } else { | ||
2268 | di_args->path[0] = '\0'; | 2286 | di_args->path[0] = '\0'; |
2287 | } | ||
2269 | 2288 | ||
2270 | out: | 2289 | out: |
2271 | if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args))) | 2290 | if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args))) |
@@ -2622,6 +2641,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2622 | btrfs_mark_buffer_dirty(leaf); | 2641 | btrfs_mark_buffer_dirty(leaf); |
2623 | btrfs_release_path(path); | 2642 | btrfs_release_path(path); |
2624 | 2643 | ||
2644 | inode_inc_iversion(inode); | ||
2625 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 2645 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
2626 | 2646 | ||
2627 | /* | 2647 | /* |
@@ -2914,7 +2934,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) | |||
2914 | up_read(&info->groups_sem); | 2934 | up_read(&info->groups_sem); |
2915 | } | 2935 | } |
2916 | 2936 | ||
2917 | user_dest = (struct btrfs_ioctl_space_info *) | 2937 | user_dest = (struct btrfs_ioctl_space_info __user *) |
2918 | (arg + sizeof(struct btrfs_ioctl_space_args)); | 2938 | (arg + sizeof(struct btrfs_ioctl_space_args)); |
2919 | 2939 | ||
2920 | if (copy_to_user(user_dest, dest_orig, alloc_size)) | 2940 | if (copy_to_user(user_dest, dest_orig, alloc_size)) |
@@ -3042,6 +3062,28 @@ static long btrfs_ioctl_scrub_progress(struct btrfs_root *root, | |||
3042 | return ret; | 3062 | return ret; |
3043 | } | 3063 | } |
3044 | 3064 | ||
3065 | static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root, | ||
3066 | void __user *arg, int reset_after_read) | ||
3067 | { | ||
3068 | struct btrfs_ioctl_get_dev_stats *sa; | ||
3069 | int ret; | ||
3070 | |||
3071 | if (reset_after_read && !capable(CAP_SYS_ADMIN)) | ||
3072 | return -EPERM; | ||
3073 | |||
3074 | sa = memdup_user(arg, sizeof(*sa)); | ||
3075 | if (IS_ERR(sa)) | ||
3076 | return PTR_ERR(sa); | ||
3077 | |||
3078 | ret = btrfs_get_dev_stats(root, sa, reset_after_read); | ||
3079 | |||
3080 | if (copy_to_user(arg, sa, sizeof(*sa))) | ||
3081 | ret = -EFAULT; | ||
3082 | |||
3083 | kfree(sa); | ||
3084 | return ret; | ||
3085 | } | ||
3086 | |||
3045 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) | 3087 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) |
3046 | { | 3088 | { |
3047 | int ret = 0; | 3089 | int ret = 0; |
@@ -3212,8 +3254,9 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock, | |||
3212 | } | 3254 | } |
3213 | } | 3255 | } |
3214 | 3256 | ||
3215 | static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) | 3257 | static long btrfs_ioctl_balance(struct file *file, void __user *arg) |
3216 | { | 3258 | { |
3259 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3217 | struct btrfs_fs_info *fs_info = root->fs_info; | 3260 | struct btrfs_fs_info *fs_info = root->fs_info; |
3218 | struct btrfs_ioctl_balance_args *bargs; | 3261 | struct btrfs_ioctl_balance_args *bargs; |
3219 | struct btrfs_balance_control *bctl; | 3262 | struct btrfs_balance_control *bctl; |
@@ -3225,6 +3268,10 @@ static long btrfs_ioctl_balance(struct btrfs_root *root, void __user *arg) | |||
3225 | if (fs_info->sb->s_flags & MS_RDONLY) | 3268 | if (fs_info->sb->s_flags & MS_RDONLY) |
3226 | return -EROFS; | 3269 | return -EROFS; |
3227 | 3270 | ||
3271 | ret = mnt_want_write(file->f_path.mnt); | ||
3272 | if (ret) | ||
3273 | return ret; | ||
3274 | |||
3228 | mutex_lock(&fs_info->volume_mutex); | 3275 | mutex_lock(&fs_info->volume_mutex); |
3229 | mutex_lock(&fs_info->balance_mutex); | 3276 | mutex_lock(&fs_info->balance_mutex); |
3230 | 3277 | ||
@@ -3291,6 +3338,7 @@ out_bargs: | |||
3291 | out: | 3338 | out: |
3292 | mutex_unlock(&fs_info->balance_mutex); | 3339 | mutex_unlock(&fs_info->balance_mutex); |
3293 | mutex_unlock(&fs_info->volume_mutex); | 3340 | mutex_unlock(&fs_info->volume_mutex); |
3341 | mnt_drop_write(file->f_path.mnt); | ||
3294 | return ret; | 3342 | return ret; |
3295 | } | 3343 | } |
3296 | 3344 | ||
@@ -3386,7 +3434,7 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3386 | case BTRFS_IOC_DEV_INFO: | 3434 | case BTRFS_IOC_DEV_INFO: |
3387 | return btrfs_ioctl_dev_info(root, argp); | 3435 | return btrfs_ioctl_dev_info(root, argp); |
3388 | case BTRFS_IOC_BALANCE: | 3436 | case BTRFS_IOC_BALANCE: |
3389 | return btrfs_ioctl_balance(root, NULL); | 3437 | return btrfs_ioctl_balance(file, NULL); |
3390 | case BTRFS_IOC_CLONE: | 3438 | case BTRFS_IOC_CLONE: |
3391 | return btrfs_ioctl_clone(file, arg, 0, 0, 0); | 3439 | return btrfs_ioctl_clone(file, arg, 0, 0, 0); |
3392 | case BTRFS_IOC_CLONE_RANGE: | 3440 | case BTRFS_IOC_CLONE_RANGE: |
@@ -3419,11 +3467,15 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3419 | case BTRFS_IOC_SCRUB_PROGRESS: | 3467 | case BTRFS_IOC_SCRUB_PROGRESS: |
3420 | return btrfs_ioctl_scrub_progress(root, argp); | 3468 | return btrfs_ioctl_scrub_progress(root, argp); |
3421 | case BTRFS_IOC_BALANCE_V2: | 3469 | case BTRFS_IOC_BALANCE_V2: |
3422 | return btrfs_ioctl_balance(root, argp); | 3470 | return btrfs_ioctl_balance(file, argp); |
3423 | case BTRFS_IOC_BALANCE_CTL: | 3471 | case BTRFS_IOC_BALANCE_CTL: |
3424 | return btrfs_ioctl_balance_ctl(root, arg); | 3472 | return btrfs_ioctl_balance_ctl(root, arg); |
3425 | case BTRFS_IOC_BALANCE_PROGRESS: | 3473 | case BTRFS_IOC_BALANCE_PROGRESS: |
3426 | return btrfs_ioctl_balance_progress(root, argp); | 3474 | return btrfs_ioctl_balance_progress(root, argp); |
3475 | case BTRFS_IOC_GET_DEV_STATS: | ||
3476 | return btrfs_ioctl_get_dev_stats(root, argp, 0); | ||
3477 | case BTRFS_IOC_GET_AND_RESET_DEV_STATS: | ||
3478 | return btrfs_ioctl_get_dev_stats(root, argp, 1); | ||
3427 | } | 3479 | } |
3428 | 3480 | ||
3429 | return -ENOTTY; | 3481 | return -ENOTTY; |