diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 10:28:19 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-01-11 10:28:19 -0500 |
commit | 734d1ece37fbf3d2ddfc71bc6c69e0fe35f02542 (patch) | |
tree | c4805dd7e746b1feb9e09e9849f3245d0b2c0c6b /fs/btrfs/ioctl.c | |
parent | 216c82c6aba63eeb49d7654b448e0d47bea255bb (diff) | |
parent | 9931faca02c604c22335f5a935a501bb2ace6e20 (diff) |
Merge tag 'v3.8-rc3' into v4l_for_linus
Linux 3.8-rc3
* tag 'v3.8-rc3': (11110 commits)
Linux 3.8-rc3
mm: reinstante dropped pmd_trans_splitting() check
cred: Remove tgcred pointer from struct cred
drm/ttm: fix fence locking in ttm_buffer_object_transfer
ARM: clps711x: Fix bad merge of clockevents setup
ARM: highbank: save and restore L2 cache and GIC on suspend
ARM: highbank: add a power request clear
ARM: highbank: fix secondary boot and hotplug
ARM: highbank: fix typos with hignbank in power request functions
ARM: dts: fix highbank cpu mpidr values
ARM: dts: add device_type prop to cpu nodes on Calxeda platforms
drm/prime: drop reference on imported dma-buf come from gem
xen/netfront: improve truesize tracking
ARM: mx5: Fix MX53 flexcan2 clock
ARM: OMAP2+: am33xx-hwmod: Fix wrongly terminated am33xx_usbss_mpu_irqs array
sctp: fix Kconfig bug in default cookie hmac selection
EDAC: Cleanup device deregistering path
EDAC: Fix EDAC Kconfig menu
EDAC: Fix kernel panic on module unloading
ALSA: hda - add mute LED for HP Pavilion 17 (Realtek codec)
...
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 319 |
1 files changed, 237 insertions, 82 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 8fcf9a59c28d..4b4516770f05 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include "backref.h" | 55 | #include "backref.h" |
56 | #include "rcu-string.h" | 56 | #include "rcu-string.h" |
57 | #include "send.h" | 57 | #include "send.h" |
58 | #include "dev-replace.h" | ||
58 | 59 | ||
59 | /* Mask out flags that are inappropriate for the given type of inode. */ | 60 | /* Mask out flags that are inappropriate for the given type of inode. */ |
60 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 61 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) |
@@ -140,8 +141,11 @@ void btrfs_inherit_iflags(struct inode *inode, struct inode *dir) | |||
140 | BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS; | 141 | BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS; |
141 | } | 142 | } |
142 | 143 | ||
143 | if (flags & BTRFS_INODE_NODATACOW) | 144 | if (flags & BTRFS_INODE_NODATACOW) { |
144 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; | 145 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; |
146 | if (S_ISREG(inode->i_mode)) | ||
147 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; | ||
148 | } | ||
145 | 149 | ||
146 | btrfs_update_iflags(inode); | 150 | btrfs_update_iflags(inode); |
147 | } | 151 | } |
@@ -571,8 +575,12 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
571 | ret = btrfs_commit_transaction(trans, | 575 | ret = btrfs_commit_transaction(trans, |
572 | root->fs_info->extent_root); | 576 | root->fs_info->extent_root); |
573 | } | 577 | } |
574 | if (ret) | 578 | if (ret) { |
579 | /* cleanup_transaction has freed this for us */ | ||
580 | if (trans->aborted) | ||
581 | pending_snapshot = NULL; | ||
575 | goto fail; | 582 | goto fail; |
583 | } | ||
576 | 584 | ||
577 | ret = pending_snapshot->error; | 585 | ret = pending_snapshot->error; |
578 | if (ret) | 586 | if (ret) |
@@ -705,6 +713,16 @@ static noinline int btrfs_mksubvol(struct path *parent, | |||
705 | if (error) | 713 | if (error) |
706 | goto out_dput; | 714 | goto out_dput; |
707 | 715 | ||
716 | /* | ||
717 | * even if this name doesn't exist, we may get hash collisions. | ||
718 | * check for them now when we can safely fail | ||
719 | */ | ||
720 | error = btrfs_check_dir_item_collision(BTRFS_I(dir)->root, | ||
721 | dir->i_ino, name, | ||
722 | namelen); | ||
723 | if (error) | ||
724 | goto out_dput; | ||
725 | |||
708 | down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem); | 726 | down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem); |
709 | 727 | ||
710 | if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0) | 728 | if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0) |
@@ -1225,7 +1243,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1225 | } | 1243 | } |
1226 | 1244 | ||
1227 | defrag_count += ret; | 1245 | defrag_count += ret; |
1228 | balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret); | 1246 | balance_dirty_pages_ratelimited(inode->i_mapping); |
1229 | mutex_unlock(&inode->i_mutex); | 1247 | mutex_unlock(&inode->i_mutex); |
1230 | 1248 | ||
1231 | if (newer_than) { | 1249 | if (newer_than) { |
@@ -1293,12 +1311,13 @@ out_ra: | |||
1293 | return ret; | 1311 | return ret; |
1294 | } | 1312 | } |
1295 | 1313 | ||
1296 | static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | 1314 | static noinline int btrfs_ioctl_resize(struct file *file, |
1297 | void __user *arg) | 1315 | void __user *arg) |
1298 | { | 1316 | { |
1299 | u64 new_size; | 1317 | u64 new_size; |
1300 | u64 old_size; | 1318 | u64 old_size; |
1301 | u64 devid = 1; | 1319 | u64 devid = 1; |
1320 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
1302 | struct btrfs_ioctl_vol_args *vol_args; | 1321 | struct btrfs_ioctl_vol_args *vol_args; |
1303 | struct btrfs_trans_handle *trans; | 1322 | struct btrfs_trans_handle *trans; |
1304 | struct btrfs_device *device = NULL; | 1323 | struct btrfs_device *device = NULL; |
@@ -1313,13 +1332,17 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
1313 | if (!capable(CAP_SYS_ADMIN)) | 1332 | if (!capable(CAP_SYS_ADMIN)) |
1314 | return -EPERM; | 1333 | return -EPERM; |
1315 | 1334 | ||
1316 | mutex_lock(&root->fs_info->volume_mutex); | 1335 | ret = mnt_want_write_file(file); |
1317 | if (root->fs_info->balance_ctl) { | 1336 | if (ret) |
1318 | printk(KERN_INFO "btrfs: balance in progress\n"); | 1337 | return ret; |
1319 | ret = -EINVAL; | 1338 | |
1320 | goto out; | 1339 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
1340 | 1)) { | ||
1341 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
1342 | return -EINPROGRESS; | ||
1321 | } | 1343 | } |
1322 | 1344 | ||
1345 | mutex_lock(&root->fs_info->volume_mutex); | ||
1323 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 1346 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
1324 | if (IS_ERR(vol_args)) { | 1347 | if (IS_ERR(vol_args)) { |
1325 | ret = PTR_ERR(vol_args); | 1348 | ret = PTR_ERR(vol_args); |
@@ -1339,7 +1362,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
1339 | printk(KERN_INFO "btrfs: resizing devid %llu\n", | 1362 | printk(KERN_INFO "btrfs: resizing devid %llu\n", |
1340 | (unsigned long long)devid); | 1363 | (unsigned long long)devid); |
1341 | } | 1364 | } |
1342 | device = btrfs_find_device(root, devid, NULL, NULL); | 1365 | device = btrfs_find_device(root->fs_info, devid, NULL, NULL); |
1343 | if (!device) { | 1366 | if (!device) { |
1344 | printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", | 1367 | printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", |
1345 | (unsigned long long)devid); | 1368 | (unsigned long long)devid); |
@@ -1371,6 +1394,11 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
1371 | } | 1394 | } |
1372 | } | 1395 | } |
1373 | 1396 | ||
1397 | if (device->is_tgtdev_for_dev_replace) { | ||
1398 | ret = -EINVAL; | ||
1399 | goto out_free; | ||
1400 | } | ||
1401 | |||
1374 | old_size = device->total_bytes; | 1402 | old_size = device->total_bytes; |
1375 | 1403 | ||
1376 | if (mod < 0) { | 1404 | if (mod < 0) { |
@@ -1409,12 +1437,14 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root, | |||
1409 | btrfs_commit_transaction(trans, root); | 1437 | btrfs_commit_transaction(trans, root); |
1410 | } else if (new_size < old_size) { | 1438 | } else if (new_size < old_size) { |
1411 | ret = btrfs_shrink_device(device, new_size); | 1439 | ret = btrfs_shrink_device(device, new_size); |
1412 | } | 1440 | } /* equal, nothing need to do */ |
1413 | 1441 | ||
1414 | out_free: | 1442 | out_free: |
1415 | kfree(vol_args); | 1443 | kfree(vol_args); |
1416 | out: | 1444 | out: |
1417 | mutex_unlock(&root->fs_info->volume_mutex); | 1445 | mutex_unlock(&root->fs_info->volume_mutex); |
1446 | mnt_drop_write_file(file); | ||
1447 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
1418 | return ret; | 1448 | return ret; |
1419 | } | 1449 | } |
1420 | 1450 | ||
@@ -2156,9 +2186,17 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2156 | if (btrfs_root_readonly(root)) | 2186 | if (btrfs_root_readonly(root)) |
2157 | return -EROFS; | 2187 | return -EROFS; |
2158 | 2188 | ||
2189 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | ||
2190 | 1)) { | ||
2191 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
2192 | return -EINPROGRESS; | ||
2193 | } | ||
2159 | ret = mnt_want_write_file(file); | 2194 | ret = mnt_want_write_file(file); |
2160 | if (ret) | 2195 | if (ret) { |
2196 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, | ||
2197 | 0); | ||
2161 | return ret; | 2198 | return ret; |
2199 | } | ||
2162 | 2200 | ||
2163 | switch (inode->i_mode & S_IFMT) { | 2201 | switch (inode->i_mode & S_IFMT) { |
2164 | case S_IFDIR: | 2202 | case S_IFDIR: |
@@ -2210,6 +2248,7 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2210 | } | 2248 | } |
2211 | out: | 2249 | out: |
2212 | mnt_drop_write_file(file); | 2250 | mnt_drop_write_file(file); |
2251 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
2213 | return ret; | 2252 | return ret; |
2214 | } | 2253 | } |
2215 | 2254 | ||
@@ -2221,13 +2260,13 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | |||
2221 | if (!capable(CAP_SYS_ADMIN)) | 2260 | if (!capable(CAP_SYS_ADMIN)) |
2222 | return -EPERM; | 2261 | return -EPERM; |
2223 | 2262 | ||
2224 | mutex_lock(&root->fs_info->volume_mutex); | 2263 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
2225 | if (root->fs_info->balance_ctl) { | 2264 | 1)) { |
2226 | printk(KERN_INFO "btrfs: balance in progress\n"); | 2265 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
2227 | ret = -EINVAL; | 2266 | return -EINPROGRESS; |
2228 | goto out; | ||
2229 | } | 2267 | } |
2230 | 2268 | ||
2269 | mutex_lock(&root->fs_info->volume_mutex); | ||
2231 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 2270 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
2232 | if (IS_ERR(vol_args)) { | 2271 | if (IS_ERR(vol_args)) { |
2233 | ret = PTR_ERR(vol_args); | 2272 | ret = PTR_ERR(vol_args); |
@@ -2240,27 +2279,31 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | |||
2240 | kfree(vol_args); | 2279 | kfree(vol_args); |
2241 | out: | 2280 | out: |
2242 | mutex_unlock(&root->fs_info->volume_mutex); | 2281 | mutex_unlock(&root->fs_info->volume_mutex); |
2282 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
2243 | return ret; | 2283 | return ret; |
2244 | } | 2284 | } |
2245 | 2285 | ||
2246 | static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | 2286 | static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) |
2247 | { | 2287 | { |
2288 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
2248 | struct btrfs_ioctl_vol_args *vol_args; | 2289 | struct btrfs_ioctl_vol_args *vol_args; |
2249 | int ret; | 2290 | int ret; |
2250 | 2291 | ||
2251 | if (!capable(CAP_SYS_ADMIN)) | 2292 | if (!capable(CAP_SYS_ADMIN)) |
2252 | return -EPERM; | 2293 | return -EPERM; |
2253 | 2294 | ||
2254 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 2295 | ret = mnt_want_write_file(file); |
2255 | return -EROFS; | 2296 | if (ret) |
2297 | return ret; | ||
2256 | 2298 | ||
2257 | mutex_lock(&root->fs_info->volume_mutex); | 2299 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
2258 | if (root->fs_info->balance_ctl) { | 2300 | 1)) { |
2259 | printk(KERN_INFO "btrfs: balance in progress\n"); | 2301 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
2260 | ret = -EINVAL; | 2302 | mnt_drop_write_file(file); |
2261 | goto out; | 2303 | return -EINPROGRESS; |
2262 | } | 2304 | } |
2263 | 2305 | ||
2306 | mutex_lock(&root->fs_info->volume_mutex); | ||
2264 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 2307 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
2265 | if (IS_ERR(vol_args)) { | 2308 | if (IS_ERR(vol_args)) { |
2266 | ret = PTR_ERR(vol_args); | 2309 | ret = PTR_ERR(vol_args); |
@@ -2273,6 +2316,8 @@ static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg) | |||
2273 | kfree(vol_args); | 2316 | kfree(vol_args); |
2274 | out: | 2317 | out: |
2275 | mutex_unlock(&root->fs_info->volume_mutex); | 2318 | mutex_unlock(&root->fs_info->volume_mutex); |
2319 | mnt_drop_write_file(file); | ||
2320 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
2276 | return ret; | 2321 | return ret; |
2277 | } | 2322 | } |
2278 | 2323 | ||
@@ -2328,7 +2373,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg) | |||
2328 | s_uuid = di_args->uuid; | 2373 | s_uuid = di_args->uuid; |
2329 | 2374 | ||
2330 | mutex_lock(&fs_devices->device_list_mutex); | 2375 | mutex_lock(&fs_devices->device_list_mutex); |
2331 | dev = btrfs_find_device(root, di_args->devid, s_uuid, NULL); | 2376 | dev = btrfs_find_device(root->fs_info, di_args->devid, s_uuid, NULL); |
2332 | mutex_unlock(&fs_devices->device_list_mutex); | 2377 | mutex_unlock(&fs_devices->device_list_mutex); |
2333 | 2378 | ||
2334 | if (!dev) { | 2379 | if (!dev) { |
@@ -2821,12 +2866,19 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
2821 | struct btrfs_disk_key disk_key; | 2866 | struct btrfs_disk_key disk_key; |
2822 | u64 objectid = 0; | 2867 | u64 objectid = 0; |
2823 | u64 dir_id; | 2868 | u64 dir_id; |
2869 | int ret; | ||
2824 | 2870 | ||
2825 | if (!capable(CAP_SYS_ADMIN)) | 2871 | if (!capable(CAP_SYS_ADMIN)) |
2826 | return -EPERM; | 2872 | return -EPERM; |
2827 | 2873 | ||
2828 | if (copy_from_user(&objectid, argp, sizeof(objectid))) | 2874 | ret = mnt_want_write_file(file); |
2829 | return -EFAULT; | 2875 | if (ret) |
2876 | return ret; | ||
2877 | |||
2878 | if (copy_from_user(&objectid, argp, sizeof(objectid))) { | ||
2879 | ret = -EFAULT; | ||
2880 | goto out; | ||
2881 | } | ||
2830 | 2882 | ||
2831 | if (!objectid) | 2883 | if (!objectid) |
2832 | objectid = root->root_key.objectid; | 2884 | objectid = root->root_key.objectid; |
@@ -2836,21 +2888,28 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
2836 | location.offset = (u64)-1; | 2888 | location.offset = (u64)-1; |
2837 | 2889 | ||
2838 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); | 2890 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); |
2839 | if (IS_ERR(new_root)) | 2891 | if (IS_ERR(new_root)) { |
2840 | return PTR_ERR(new_root); | 2892 | ret = PTR_ERR(new_root); |
2893 | goto out; | ||
2894 | } | ||
2841 | 2895 | ||
2842 | if (btrfs_root_refs(&new_root->root_item) == 0) | 2896 | if (btrfs_root_refs(&new_root->root_item) == 0) { |
2843 | return -ENOENT; | 2897 | ret = -ENOENT; |
2898 | goto out; | ||
2899 | } | ||
2844 | 2900 | ||
2845 | path = btrfs_alloc_path(); | 2901 | path = btrfs_alloc_path(); |
2846 | if (!path) | 2902 | if (!path) { |
2847 | return -ENOMEM; | 2903 | ret = -ENOMEM; |
2904 | goto out; | ||
2905 | } | ||
2848 | path->leave_spinning = 1; | 2906 | path->leave_spinning = 1; |
2849 | 2907 | ||
2850 | trans = btrfs_start_transaction(root, 1); | 2908 | trans = btrfs_start_transaction(root, 1); |
2851 | if (IS_ERR(trans)) { | 2909 | if (IS_ERR(trans)) { |
2852 | btrfs_free_path(path); | 2910 | btrfs_free_path(path); |
2853 | return PTR_ERR(trans); | 2911 | ret = PTR_ERR(trans); |
2912 | goto out; | ||
2854 | } | 2913 | } |
2855 | 2914 | ||
2856 | dir_id = btrfs_super_root_dir(root->fs_info->super_copy); | 2915 | dir_id = btrfs_super_root_dir(root->fs_info->super_copy); |
@@ -2861,7 +2920,8 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
2861 | btrfs_end_transaction(trans, root); | 2920 | btrfs_end_transaction(trans, root); |
2862 | printk(KERN_ERR "Umm, you don't have the default dir item, " | 2921 | printk(KERN_ERR "Umm, you don't have the default dir item, " |
2863 | "this isn't going to work\n"); | 2922 | "this isn't going to work\n"); |
2864 | return -ENOENT; | 2923 | ret = -ENOENT; |
2924 | goto out; | ||
2865 | } | 2925 | } |
2866 | 2926 | ||
2867 | btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key); | 2927 | btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key); |
@@ -2871,8 +2931,9 @@ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | |||
2871 | 2931 | ||
2872 | btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL); | 2932 | btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL); |
2873 | btrfs_end_transaction(trans, root); | 2933 | btrfs_end_transaction(trans, root); |
2874 | 2934 | out: | |
2875 | return 0; | 2935 | mnt_drop_write_file(file); |
2936 | return ret; | ||
2876 | } | 2937 | } |
2877 | 2938 | ||
2878 | void btrfs_get_block_group_info(struct list_head *groups_list, | 2939 | void btrfs_get_block_group_info(struct list_head *groups_list, |
@@ -3036,32 +3097,38 @@ long btrfs_ioctl_trans_end(struct file *file) | |||
3036 | return 0; | 3097 | return 0; |
3037 | } | 3098 | } |
3038 | 3099 | ||
3039 | static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp) | 3100 | static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root, |
3101 | void __user *argp) | ||
3040 | { | 3102 | { |
3041 | struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root; | ||
3042 | struct btrfs_trans_handle *trans; | 3103 | struct btrfs_trans_handle *trans; |
3043 | u64 transid; | 3104 | u64 transid; |
3044 | int ret; | 3105 | int ret; |
3045 | 3106 | ||
3046 | trans = btrfs_start_transaction(root, 0); | 3107 | trans = btrfs_attach_transaction(root); |
3047 | if (IS_ERR(trans)) | 3108 | if (IS_ERR(trans)) { |
3048 | return PTR_ERR(trans); | 3109 | if (PTR_ERR(trans) != -ENOENT) |
3110 | return PTR_ERR(trans); | ||
3111 | |||
3112 | /* No running transaction, don't bother */ | ||
3113 | transid = root->fs_info->last_trans_committed; | ||
3114 | goto out; | ||
3115 | } | ||
3049 | transid = trans->transid; | 3116 | transid = trans->transid; |
3050 | ret = btrfs_commit_transaction_async(trans, root, 0); | 3117 | ret = btrfs_commit_transaction_async(trans, root, 0); |
3051 | if (ret) { | 3118 | if (ret) { |
3052 | btrfs_end_transaction(trans, root); | 3119 | btrfs_end_transaction(trans, root); |
3053 | return ret; | 3120 | return ret; |
3054 | } | 3121 | } |
3055 | 3122 | out: | |
3056 | if (argp) | 3123 | if (argp) |
3057 | if (copy_to_user(argp, &transid, sizeof(transid))) | 3124 | if (copy_to_user(argp, &transid, sizeof(transid))) |
3058 | return -EFAULT; | 3125 | return -EFAULT; |
3059 | return 0; | 3126 | return 0; |
3060 | } | 3127 | } |
3061 | 3128 | ||
3062 | static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp) | 3129 | static noinline long btrfs_ioctl_wait_sync(struct btrfs_root *root, |
3130 | void __user *argp) | ||
3063 | { | 3131 | { |
3064 | struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root; | ||
3065 | u64 transid; | 3132 | u64 transid; |
3066 | 3133 | ||
3067 | if (argp) { | 3134 | if (argp) { |
@@ -3073,10 +3140,11 @@ static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp) | |||
3073 | return btrfs_wait_for_commit(root, transid); | 3140 | return btrfs_wait_for_commit(root, transid); |
3074 | } | 3141 | } |
3075 | 3142 | ||
3076 | static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg) | 3143 | static long btrfs_ioctl_scrub(struct file *file, void __user *arg) |
3077 | { | 3144 | { |
3078 | int ret; | 3145 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; |
3079 | struct btrfs_ioctl_scrub_args *sa; | 3146 | struct btrfs_ioctl_scrub_args *sa; |
3147 | int ret; | ||
3080 | 3148 | ||
3081 | if (!capable(CAP_SYS_ADMIN)) | 3149 | if (!capable(CAP_SYS_ADMIN)) |
3082 | return -EPERM; | 3150 | return -EPERM; |
@@ -3085,12 +3153,22 @@ static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg) | |||
3085 | if (IS_ERR(sa)) | 3153 | if (IS_ERR(sa)) |
3086 | return PTR_ERR(sa); | 3154 | return PTR_ERR(sa); |
3087 | 3155 | ||
3088 | ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end, | 3156 | if (!(sa->flags & BTRFS_SCRUB_READONLY)) { |
3089 | &sa->progress, sa->flags & BTRFS_SCRUB_READONLY); | 3157 | ret = mnt_want_write_file(file); |
3158 | if (ret) | ||
3159 | goto out; | ||
3160 | } | ||
3161 | |||
3162 | ret = btrfs_scrub_dev(root->fs_info, sa->devid, sa->start, sa->end, | ||
3163 | &sa->progress, sa->flags & BTRFS_SCRUB_READONLY, | ||
3164 | 0); | ||
3090 | 3165 | ||
3091 | if (copy_to_user(arg, sa, sizeof(*sa))) | 3166 | if (copy_to_user(arg, sa, sizeof(*sa))) |
3092 | ret = -EFAULT; | 3167 | ret = -EFAULT; |
3093 | 3168 | ||
3169 | if (!(sa->flags & BTRFS_SCRUB_READONLY)) | ||
3170 | mnt_drop_write_file(file); | ||
3171 | out: | ||
3094 | kfree(sa); | 3172 | kfree(sa); |
3095 | return ret; | 3173 | return ret; |
3096 | } | 3174 | } |
@@ -3100,7 +3178,7 @@ static long btrfs_ioctl_scrub_cancel(struct btrfs_root *root, void __user *arg) | |||
3100 | if (!capable(CAP_SYS_ADMIN)) | 3178 | if (!capable(CAP_SYS_ADMIN)) |
3101 | return -EPERM; | 3179 | return -EPERM; |
3102 | 3180 | ||
3103 | return btrfs_scrub_cancel(root); | 3181 | return btrfs_scrub_cancel(root->fs_info); |
3104 | } | 3182 | } |
3105 | 3183 | ||
3106 | static long btrfs_ioctl_scrub_progress(struct btrfs_root *root, | 3184 | static long btrfs_ioctl_scrub_progress(struct btrfs_root *root, |
@@ -3149,6 +3227,51 @@ static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root, | |||
3149 | return ret; | 3227 | return ret; |
3150 | } | 3228 | } |
3151 | 3229 | ||
3230 | static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg) | ||
3231 | { | ||
3232 | struct btrfs_ioctl_dev_replace_args *p; | ||
3233 | int ret; | ||
3234 | |||
3235 | if (!capable(CAP_SYS_ADMIN)) | ||
3236 | return -EPERM; | ||
3237 | |||
3238 | p = memdup_user(arg, sizeof(*p)); | ||
3239 | if (IS_ERR(p)) | ||
3240 | return PTR_ERR(p); | ||
3241 | |||
3242 | switch (p->cmd) { | ||
3243 | case BTRFS_IOCTL_DEV_REPLACE_CMD_START: | ||
3244 | if (atomic_xchg( | ||
3245 | &root->fs_info->mutually_exclusive_operation_running, | ||
3246 | 1)) { | ||
3247 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
3248 | ret = -EINPROGRESS; | ||
3249 | } else { | ||
3250 | ret = btrfs_dev_replace_start(root, p); | ||
3251 | atomic_set( | ||
3252 | &root->fs_info->mutually_exclusive_operation_running, | ||
3253 | 0); | ||
3254 | } | ||
3255 | break; | ||
3256 | case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS: | ||
3257 | btrfs_dev_replace_status(root->fs_info, p); | ||
3258 | ret = 0; | ||
3259 | break; | ||
3260 | case BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL: | ||
3261 | ret = btrfs_dev_replace_cancel(root->fs_info, p); | ||
3262 | break; | ||
3263 | default: | ||
3264 | ret = -EINVAL; | ||
3265 | break; | ||
3266 | } | ||
3267 | |||
3268 | if (copy_to_user(arg, p, sizeof(*p))) | ||
3269 | ret = -EFAULT; | ||
3270 | |||
3271 | kfree(p); | ||
3272 | return ret; | ||
3273 | } | ||
3274 | |||
3152 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) | 3275 | static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) |
3153 | { | 3276 | { |
3154 | int ret = 0; | 3277 | int ret = 0; |
@@ -3315,6 +3438,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3315 | struct btrfs_ioctl_balance_args *bargs; | 3438 | struct btrfs_ioctl_balance_args *bargs; |
3316 | struct btrfs_balance_control *bctl; | 3439 | struct btrfs_balance_control *bctl; |
3317 | int ret; | 3440 | int ret; |
3441 | int need_to_clear_lock = 0; | ||
3318 | 3442 | ||
3319 | if (!capable(CAP_SYS_ADMIN)) | 3443 | if (!capable(CAP_SYS_ADMIN)) |
3320 | return -EPERM; | 3444 | return -EPERM; |
@@ -3350,10 +3474,13 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3350 | bargs = NULL; | 3474 | bargs = NULL; |
3351 | } | 3475 | } |
3352 | 3476 | ||
3353 | if (fs_info->balance_ctl) { | 3477 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
3478 | 1)) { | ||
3479 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
3354 | ret = -EINPROGRESS; | 3480 | ret = -EINPROGRESS; |
3355 | goto out_bargs; | 3481 | goto out_bargs; |
3356 | } | 3482 | } |
3483 | need_to_clear_lock = 1; | ||
3357 | 3484 | ||
3358 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | 3485 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); |
3359 | if (!bctl) { | 3486 | if (!bctl) { |
@@ -3387,6 +3514,9 @@ do_balance: | |||
3387 | out_bargs: | 3514 | out_bargs: |
3388 | kfree(bargs); | 3515 | kfree(bargs); |
3389 | out: | 3516 | out: |
3517 | if (need_to_clear_lock) | ||
3518 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, | ||
3519 | 0); | ||
3390 | mutex_unlock(&fs_info->balance_mutex); | 3520 | mutex_unlock(&fs_info->balance_mutex); |
3391 | mutex_unlock(&fs_info->volume_mutex); | 3521 | mutex_unlock(&fs_info->volume_mutex); |
3392 | mnt_drop_write_file(file); | 3522 | mnt_drop_write_file(file); |
@@ -3441,8 +3571,9 @@ out: | |||
3441 | return ret; | 3571 | return ret; |
3442 | } | 3572 | } |
3443 | 3573 | ||
3444 | static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg) | 3574 | static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg) |
3445 | { | 3575 | { |
3576 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3446 | struct btrfs_ioctl_quota_ctl_args *sa; | 3577 | struct btrfs_ioctl_quota_ctl_args *sa; |
3447 | struct btrfs_trans_handle *trans = NULL; | 3578 | struct btrfs_trans_handle *trans = NULL; |
3448 | int ret; | 3579 | int ret; |
@@ -3451,12 +3582,15 @@ static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg) | |||
3451 | if (!capable(CAP_SYS_ADMIN)) | 3582 | if (!capable(CAP_SYS_ADMIN)) |
3452 | return -EPERM; | 3583 | return -EPERM; |
3453 | 3584 | ||
3454 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 3585 | ret = mnt_want_write_file(file); |
3455 | return -EROFS; | 3586 | if (ret) |
3587 | return ret; | ||
3456 | 3588 | ||
3457 | sa = memdup_user(arg, sizeof(*sa)); | 3589 | sa = memdup_user(arg, sizeof(*sa)); |
3458 | if (IS_ERR(sa)) | 3590 | if (IS_ERR(sa)) { |
3459 | return PTR_ERR(sa); | 3591 | ret = PTR_ERR(sa); |
3592 | goto drop_write; | ||
3593 | } | ||
3460 | 3594 | ||
3461 | if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) { | 3595 | if (sa->cmd != BTRFS_QUOTA_CTL_RESCAN) { |
3462 | trans = btrfs_start_transaction(root, 2); | 3596 | trans = btrfs_start_transaction(root, 2); |
@@ -3489,14 +3623,16 @@ static long btrfs_ioctl_quota_ctl(struct btrfs_root *root, void __user *arg) | |||
3489 | if (err && !ret) | 3623 | if (err && !ret) |
3490 | ret = err; | 3624 | ret = err; |
3491 | } | 3625 | } |
3492 | |||
3493 | out: | 3626 | out: |
3494 | kfree(sa); | 3627 | kfree(sa); |
3628 | drop_write: | ||
3629 | mnt_drop_write_file(file); | ||
3495 | return ret; | 3630 | return ret; |
3496 | } | 3631 | } |
3497 | 3632 | ||
3498 | static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg) | 3633 | static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg) |
3499 | { | 3634 | { |
3635 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3500 | struct btrfs_ioctl_qgroup_assign_args *sa; | 3636 | struct btrfs_ioctl_qgroup_assign_args *sa; |
3501 | struct btrfs_trans_handle *trans; | 3637 | struct btrfs_trans_handle *trans; |
3502 | int ret; | 3638 | int ret; |
@@ -3505,12 +3641,15 @@ static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg) | |||
3505 | if (!capable(CAP_SYS_ADMIN)) | 3641 | if (!capable(CAP_SYS_ADMIN)) |
3506 | return -EPERM; | 3642 | return -EPERM; |
3507 | 3643 | ||
3508 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 3644 | ret = mnt_want_write_file(file); |
3509 | return -EROFS; | 3645 | if (ret) |
3646 | return ret; | ||
3510 | 3647 | ||
3511 | sa = memdup_user(arg, sizeof(*sa)); | 3648 | sa = memdup_user(arg, sizeof(*sa)); |
3512 | if (IS_ERR(sa)) | 3649 | if (IS_ERR(sa)) { |
3513 | return PTR_ERR(sa); | 3650 | ret = PTR_ERR(sa); |
3651 | goto drop_write; | ||
3652 | } | ||
3514 | 3653 | ||
3515 | trans = btrfs_join_transaction(root); | 3654 | trans = btrfs_join_transaction(root); |
3516 | if (IS_ERR(trans)) { | 3655 | if (IS_ERR(trans)) { |
@@ -3533,11 +3672,14 @@ static long btrfs_ioctl_qgroup_assign(struct btrfs_root *root, void __user *arg) | |||
3533 | 3672 | ||
3534 | out: | 3673 | out: |
3535 | kfree(sa); | 3674 | kfree(sa); |
3675 | drop_write: | ||
3676 | mnt_drop_write_file(file); | ||
3536 | return ret; | 3677 | return ret; |
3537 | } | 3678 | } |
3538 | 3679 | ||
3539 | static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg) | 3680 | static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) |
3540 | { | 3681 | { |
3682 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3541 | struct btrfs_ioctl_qgroup_create_args *sa; | 3683 | struct btrfs_ioctl_qgroup_create_args *sa; |
3542 | struct btrfs_trans_handle *trans; | 3684 | struct btrfs_trans_handle *trans; |
3543 | int ret; | 3685 | int ret; |
@@ -3546,12 +3688,15 @@ static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg) | |||
3546 | if (!capable(CAP_SYS_ADMIN)) | 3688 | if (!capable(CAP_SYS_ADMIN)) |
3547 | return -EPERM; | 3689 | return -EPERM; |
3548 | 3690 | ||
3549 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 3691 | ret = mnt_want_write_file(file); |
3550 | return -EROFS; | 3692 | if (ret) |
3693 | return ret; | ||
3551 | 3694 | ||
3552 | sa = memdup_user(arg, sizeof(*sa)); | 3695 | sa = memdup_user(arg, sizeof(*sa)); |
3553 | if (IS_ERR(sa)) | 3696 | if (IS_ERR(sa)) { |
3554 | return PTR_ERR(sa); | 3697 | ret = PTR_ERR(sa); |
3698 | goto drop_write; | ||
3699 | } | ||
3555 | 3700 | ||
3556 | trans = btrfs_join_transaction(root); | 3701 | trans = btrfs_join_transaction(root); |
3557 | if (IS_ERR(trans)) { | 3702 | if (IS_ERR(trans)) { |
@@ -3573,11 +3718,14 @@ static long btrfs_ioctl_qgroup_create(struct btrfs_root *root, void __user *arg) | |||
3573 | 3718 | ||
3574 | out: | 3719 | out: |
3575 | kfree(sa); | 3720 | kfree(sa); |
3721 | drop_write: | ||
3722 | mnt_drop_write_file(file); | ||
3576 | return ret; | 3723 | return ret; |
3577 | } | 3724 | } |
3578 | 3725 | ||
3579 | static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg) | 3726 | static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg) |
3580 | { | 3727 | { |
3728 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3581 | struct btrfs_ioctl_qgroup_limit_args *sa; | 3729 | struct btrfs_ioctl_qgroup_limit_args *sa; |
3582 | struct btrfs_trans_handle *trans; | 3730 | struct btrfs_trans_handle *trans; |
3583 | int ret; | 3731 | int ret; |
@@ -3587,12 +3735,15 @@ static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg) | |||
3587 | if (!capable(CAP_SYS_ADMIN)) | 3735 | if (!capable(CAP_SYS_ADMIN)) |
3588 | return -EPERM; | 3736 | return -EPERM; |
3589 | 3737 | ||
3590 | if (root->fs_info->sb->s_flags & MS_RDONLY) | 3738 | ret = mnt_want_write_file(file); |
3591 | return -EROFS; | 3739 | if (ret) |
3740 | return ret; | ||
3592 | 3741 | ||
3593 | sa = memdup_user(arg, sizeof(*sa)); | 3742 | sa = memdup_user(arg, sizeof(*sa)); |
3594 | if (IS_ERR(sa)) | 3743 | if (IS_ERR(sa)) { |
3595 | return PTR_ERR(sa); | 3744 | ret = PTR_ERR(sa); |
3745 | goto drop_write; | ||
3746 | } | ||
3596 | 3747 | ||
3597 | trans = btrfs_join_transaction(root); | 3748 | trans = btrfs_join_transaction(root); |
3598 | if (IS_ERR(trans)) { | 3749 | if (IS_ERR(trans)) { |
@@ -3615,6 +3766,8 @@ static long btrfs_ioctl_qgroup_limit(struct btrfs_root *root, void __user *arg) | |||
3615 | 3766 | ||
3616 | out: | 3767 | out: |
3617 | kfree(sa); | 3768 | kfree(sa); |
3769 | drop_write: | ||
3770 | mnt_drop_write_file(file); | ||
3618 | return ret; | 3771 | return ret; |
3619 | } | 3772 | } |
3620 | 3773 | ||
@@ -3735,11 +3888,11 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3735 | case BTRFS_IOC_DEFRAG_RANGE: | 3888 | case BTRFS_IOC_DEFRAG_RANGE: |
3736 | return btrfs_ioctl_defrag(file, argp); | 3889 | return btrfs_ioctl_defrag(file, argp); |
3737 | case BTRFS_IOC_RESIZE: | 3890 | case BTRFS_IOC_RESIZE: |
3738 | return btrfs_ioctl_resize(root, argp); | 3891 | return btrfs_ioctl_resize(file, argp); |
3739 | case BTRFS_IOC_ADD_DEV: | 3892 | case BTRFS_IOC_ADD_DEV: |
3740 | return btrfs_ioctl_add_dev(root, argp); | 3893 | return btrfs_ioctl_add_dev(root, argp); |
3741 | case BTRFS_IOC_RM_DEV: | 3894 | case BTRFS_IOC_RM_DEV: |
3742 | return btrfs_ioctl_rm_dev(root, argp); | 3895 | return btrfs_ioctl_rm_dev(file, argp); |
3743 | case BTRFS_IOC_FS_INFO: | 3896 | case BTRFS_IOC_FS_INFO: |
3744 | return btrfs_ioctl_fs_info(root, argp); | 3897 | return btrfs_ioctl_fs_info(root, argp); |
3745 | case BTRFS_IOC_DEV_INFO: | 3898 | case BTRFS_IOC_DEV_INFO: |
@@ -3768,11 +3921,11 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3768 | btrfs_sync_fs(file->f_dentry->d_sb, 1); | 3921 | btrfs_sync_fs(file->f_dentry->d_sb, 1); |
3769 | return 0; | 3922 | return 0; |
3770 | case BTRFS_IOC_START_SYNC: | 3923 | case BTRFS_IOC_START_SYNC: |
3771 | return btrfs_ioctl_start_sync(file, argp); | 3924 | return btrfs_ioctl_start_sync(root, argp); |
3772 | case BTRFS_IOC_WAIT_SYNC: | 3925 | case BTRFS_IOC_WAIT_SYNC: |
3773 | return btrfs_ioctl_wait_sync(file, argp); | 3926 | return btrfs_ioctl_wait_sync(root, argp); |
3774 | case BTRFS_IOC_SCRUB: | 3927 | case BTRFS_IOC_SCRUB: |
3775 | return btrfs_ioctl_scrub(root, argp); | 3928 | return btrfs_ioctl_scrub(file, argp); |
3776 | case BTRFS_IOC_SCRUB_CANCEL: | 3929 | case BTRFS_IOC_SCRUB_CANCEL: |
3777 | return btrfs_ioctl_scrub_cancel(root, argp); | 3930 | return btrfs_ioctl_scrub_cancel(root, argp); |
3778 | case BTRFS_IOC_SCRUB_PROGRESS: | 3931 | case BTRFS_IOC_SCRUB_PROGRESS: |
@@ -3790,13 +3943,15 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3790 | case BTRFS_IOC_GET_DEV_STATS: | 3943 | case BTRFS_IOC_GET_DEV_STATS: |
3791 | return btrfs_ioctl_get_dev_stats(root, argp); | 3944 | return btrfs_ioctl_get_dev_stats(root, argp); |
3792 | case BTRFS_IOC_QUOTA_CTL: | 3945 | case BTRFS_IOC_QUOTA_CTL: |
3793 | return btrfs_ioctl_quota_ctl(root, argp); | 3946 | return btrfs_ioctl_quota_ctl(file, argp); |
3794 | case BTRFS_IOC_QGROUP_ASSIGN: | 3947 | case BTRFS_IOC_QGROUP_ASSIGN: |
3795 | return btrfs_ioctl_qgroup_assign(root, argp); | 3948 | return btrfs_ioctl_qgroup_assign(file, argp); |
3796 | case BTRFS_IOC_QGROUP_CREATE: | 3949 | case BTRFS_IOC_QGROUP_CREATE: |
3797 | return btrfs_ioctl_qgroup_create(root, argp); | 3950 | return btrfs_ioctl_qgroup_create(file, argp); |
3798 | case BTRFS_IOC_QGROUP_LIMIT: | 3951 | case BTRFS_IOC_QGROUP_LIMIT: |
3799 | return btrfs_ioctl_qgroup_limit(root, argp); | 3952 | return btrfs_ioctl_qgroup_limit(file, argp); |
3953 | case BTRFS_IOC_DEV_REPLACE: | ||
3954 | return btrfs_ioctl_dev_replace(root, argp); | ||
3800 | } | 3955 | } |
3801 | 3956 | ||
3802 | return -ENOTTY; | 3957 | return -ENOTTY; |