diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 403 |
1 files changed, 286 insertions, 117 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 4b4516770f05..2c02310ff2d9 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -42,12 +42,12 @@ | |||
42 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
43 | #include <linux/blkdev.h> | 43 | #include <linux/blkdev.h> |
44 | #include <linux/uuid.h> | 44 | #include <linux/uuid.h> |
45 | #include <linux/btrfs.h> | ||
45 | #include "compat.h" | 46 | #include "compat.h" |
46 | #include "ctree.h" | 47 | #include "ctree.h" |
47 | #include "disk-io.h" | 48 | #include "disk-io.h" |
48 | #include "transaction.h" | 49 | #include "transaction.h" |
49 | #include "btrfs_inode.h" | 50 | #include "btrfs_inode.h" |
50 | #include "ioctl.h" | ||
51 | #include "print-tree.h" | 51 | #include "print-tree.h" |
52 | #include "volumes.h" | 52 | #include "volumes.h" |
53 | #include "locking.h" | 53 | #include "locking.h" |
@@ -152,7 +152,7 @@ void btrfs_inherit_iflags(struct inode *inode, struct inode *dir) | |||
152 | 152 | ||
153 | static int btrfs_ioctl_getflags(struct file *file, void __user *arg) | 153 | static int btrfs_ioctl_getflags(struct file *file, void __user *arg) |
154 | { | 154 | { |
155 | struct btrfs_inode *ip = BTRFS_I(file->f_path.dentry->d_inode); | 155 | struct btrfs_inode *ip = BTRFS_I(file_inode(file)); |
156 | unsigned int flags = btrfs_flags_to_ioctl(ip->flags); | 156 | unsigned int flags = btrfs_flags_to_ioctl(ip->flags); |
157 | 157 | ||
158 | if (copy_to_user(arg, &flags, sizeof(flags))) | 158 | if (copy_to_user(arg, &flags, sizeof(flags))) |
@@ -177,7 +177,7 @@ static int check_flags(unsigned int flags) | |||
177 | 177 | ||
178 | static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | 178 | static int btrfs_ioctl_setflags(struct file *file, void __user *arg) |
179 | { | 179 | { |
180 | struct inode *inode = file->f_path.dentry->d_inode; | 180 | struct inode *inode = file_inode(file); |
181 | struct btrfs_inode *ip = BTRFS_I(inode); | 181 | struct btrfs_inode *ip = BTRFS_I(inode); |
182 | struct btrfs_root *root = ip->root; | 182 | struct btrfs_root *root = ip->root; |
183 | struct btrfs_trans_handle *trans; | 183 | struct btrfs_trans_handle *trans; |
@@ -310,7 +310,7 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | |||
310 | 310 | ||
311 | static int btrfs_ioctl_getversion(struct file *file, int __user *arg) | 311 | static int btrfs_ioctl_getversion(struct file *file, int __user *arg) |
312 | { | 312 | { |
313 | struct inode *inode = file->f_path.dentry->d_inode; | 313 | struct inode *inode = file_inode(file); |
314 | 314 | ||
315 | return put_user(inode->i_generation, arg); | 315 | return put_user(inode->i_generation, arg); |
316 | } | 316 | } |
@@ -363,46 +363,52 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
363 | return 0; | 363 | return 0; |
364 | } | 364 | } |
365 | 365 | ||
366 | static noinline int create_subvol(struct btrfs_root *root, | 366 | static noinline int create_subvol(struct inode *dir, |
367 | struct dentry *dentry, | 367 | struct dentry *dentry, |
368 | char *name, int namelen, | 368 | char *name, int namelen, |
369 | u64 *async_transid, | 369 | u64 *async_transid, |
370 | struct btrfs_qgroup_inherit **inherit) | 370 | struct btrfs_qgroup_inherit *inherit) |
371 | { | 371 | { |
372 | struct btrfs_trans_handle *trans; | 372 | struct btrfs_trans_handle *trans; |
373 | struct btrfs_key key; | 373 | struct btrfs_key key; |
374 | struct btrfs_root_item root_item; | 374 | struct btrfs_root_item root_item; |
375 | struct btrfs_inode_item *inode_item; | 375 | struct btrfs_inode_item *inode_item; |
376 | struct extent_buffer *leaf; | 376 | struct extent_buffer *leaf; |
377 | struct btrfs_root *root = BTRFS_I(dir)->root; | ||
377 | struct btrfs_root *new_root; | 378 | struct btrfs_root *new_root; |
378 | struct dentry *parent = dentry->d_parent; | 379 | struct btrfs_block_rsv block_rsv; |
379 | struct inode *dir; | ||
380 | struct timespec cur_time = CURRENT_TIME; | 380 | struct timespec cur_time = CURRENT_TIME; |
381 | int ret; | 381 | int ret; |
382 | int err; | 382 | int err; |
383 | u64 objectid; | 383 | u64 objectid; |
384 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; | 384 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; |
385 | u64 index = 0; | 385 | u64 index = 0; |
386 | u64 qgroup_reserved; | ||
386 | uuid_le new_uuid; | 387 | uuid_le new_uuid; |
387 | 388 | ||
388 | ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); | 389 | ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid); |
389 | if (ret) | 390 | if (ret) |
390 | return ret; | 391 | return ret; |
391 | 392 | ||
392 | dir = parent->d_inode; | 393 | btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP); |
393 | |||
394 | /* | 394 | /* |
395 | * 1 - inode item | 395 | * The same as the snapshot creation, please see the comment |
396 | * 2 - refs | 396 | * of create_snapshot(). |
397 | * 1 - root item | ||
398 | * 2 - dir items | ||
399 | */ | 397 | */ |
400 | trans = btrfs_start_transaction(root, 6); | 398 | ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, |
401 | if (IS_ERR(trans)) | 399 | 7, &qgroup_reserved); |
402 | return PTR_ERR(trans); | 400 | if (ret) |
401 | return ret; | ||
402 | |||
403 | trans = btrfs_start_transaction(root, 0); | ||
404 | if (IS_ERR(trans)) { | ||
405 | ret = PTR_ERR(trans); | ||
406 | goto out; | ||
407 | } | ||
408 | trans->block_rsv = &block_rsv; | ||
409 | trans->bytes_reserved = block_rsv.size; | ||
403 | 410 | ||
404 | ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, | 411 | ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, inherit); |
405 | inherit ? *inherit : NULL); | ||
406 | if (ret) | 412 | if (ret) |
407 | goto fail; | 413 | goto fail; |
408 | 414 | ||
@@ -515,22 +521,31 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
515 | 521 | ||
516 | BUG_ON(ret); | 522 | BUG_ON(ret); |
517 | 523 | ||
518 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); | ||
519 | fail: | 524 | fail: |
525 | trans->block_rsv = NULL; | ||
526 | trans->bytes_reserved = 0; | ||
520 | if (async_transid) { | 527 | if (async_transid) { |
521 | *async_transid = trans->transid; | 528 | *async_transid = trans->transid; |
522 | err = btrfs_commit_transaction_async(trans, root, 1); | 529 | err = btrfs_commit_transaction_async(trans, root, 1); |
530 | if (err) | ||
531 | err = btrfs_commit_transaction(trans, root); | ||
523 | } else { | 532 | } else { |
524 | err = btrfs_commit_transaction(trans, root); | 533 | err = btrfs_commit_transaction(trans, root); |
525 | } | 534 | } |
526 | if (err && !ret) | 535 | if (err && !ret) |
527 | ret = err; | 536 | ret = err; |
537 | |||
538 | if (!ret) | ||
539 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); | ||
540 | out: | ||
541 | btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved); | ||
528 | return ret; | 542 | return ret; |
529 | } | 543 | } |
530 | 544 | ||
531 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | 545 | static int create_snapshot(struct btrfs_root *root, struct inode *dir, |
532 | char *name, int namelen, u64 *async_transid, | 546 | struct dentry *dentry, char *name, int namelen, |
533 | bool readonly, struct btrfs_qgroup_inherit **inherit) | 547 | u64 *async_transid, bool readonly, |
548 | struct btrfs_qgroup_inherit *inherit) | ||
534 | { | 549 | { |
535 | struct inode *inode; | 550 | struct inode *inode; |
536 | struct btrfs_pending_snapshot *pending_snapshot; | 551 | struct btrfs_pending_snapshot *pending_snapshot; |
@@ -546,23 +561,31 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
546 | 561 | ||
547 | btrfs_init_block_rsv(&pending_snapshot->block_rsv, | 562 | btrfs_init_block_rsv(&pending_snapshot->block_rsv, |
548 | BTRFS_BLOCK_RSV_TEMP); | 563 | BTRFS_BLOCK_RSV_TEMP); |
564 | /* | ||
565 | * 1 - parent dir inode | ||
566 | * 2 - dir entries | ||
567 | * 1 - root item | ||
568 | * 2 - root ref/backref | ||
569 | * 1 - root of snapshot | ||
570 | */ | ||
571 | ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, | ||
572 | &pending_snapshot->block_rsv, 7, | ||
573 | &pending_snapshot->qgroup_reserved); | ||
574 | if (ret) | ||
575 | goto out; | ||
576 | |||
549 | pending_snapshot->dentry = dentry; | 577 | pending_snapshot->dentry = dentry; |
550 | pending_snapshot->root = root; | 578 | pending_snapshot->root = root; |
551 | pending_snapshot->readonly = readonly; | 579 | pending_snapshot->readonly = readonly; |
552 | if (inherit) { | 580 | pending_snapshot->dir = dir; |
553 | pending_snapshot->inherit = *inherit; | 581 | pending_snapshot->inherit = inherit; |
554 | *inherit = NULL; /* take responsibility to free it */ | ||
555 | } | ||
556 | 582 | ||
557 | trans = btrfs_start_transaction(root->fs_info->extent_root, 6); | 583 | trans = btrfs_start_transaction(root, 0); |
558 | if (IS_ERR(trans)) { | 584 | if (IS_ERR(trans)) { |
559 | ret = PTR_ERR(trans); | 585 | ret = PTR_ERR(trans); |
560 | goto fail; | 586 | goto fail; |
561 | } | 587 | } |
562 | 588 | ||
563 | ret = btrfs_snap_reserve_metadata(trans, pending_snapshot); | ||
564 | BUG_ON(ret); | ||
565 | |||
566 | spin_lock(&root->fs_info->trans_lock); | 589 | spin_lock(&root->fs_info->trans_lock); |
567 | list_add(&pending_snapshot->list, | 590 | list_add(&pending_snapshot->list, |
568 | &trans->transaction->pending_snapshots); | 591 | &trans->transaction->pending_snapshots); |
@@ -571,16 +594,14 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
571 | *async_transid = trans->transid; | 594 | *async_transid = trans->transid; |
572 | ret = btrfs_commit_transaction_async(trans, | 595 | ret = btrfs_commit_transaction_async(trans, |
573 | root->fs_info->extent_root, 1); | 596 | root->fs_info->extent_root, 1); |
597 | if (ret) | ||
598 | ret = btrfs_commit_transaction(trans, root); | ||
574 | } else { | 599 | } else { |
575 | ret = btrfs_commit_transaction(trans, | 600 | ret = btrfs_commit_transaction(trans, |
576 | root->fs_info->extent_root); | 601 | root->fs_info->extent_root); |
577 | } | 602 | } |
578 | if (ret) { | 603 | if (ret) |
579 | /* cleanup_transaction has freed this for us */ | ||
580 | if (trans->aborted) | ||
581 | pending_snapshot = NULL; | ||
582 | goto fail; | 604 | goto fail; |
583 | } | ||
584 | 605 | ||
585 | ret = pending_snapshot->error; | 606 | ret = pending_snapshot->error; |
586 | if (ret) | 607 | if (ret) |
@@ -599,6 +620,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
599 | d_instantiate(dentry, inode); | 620 | d_instantiate(dentry, inode); |
600 | ret = 0; | 621 | ret = 0; |
601 | fail: | 622 | fail: |
623 | btrfs_subvolume_release_metadata(BTRFS_I(dir)->root, | ||
624 | &pending_snapshot->block_rsv, | ||
625 | pending_snapshot->qgroup_reserved); | ||
626 | out: | ||
602 | kfree(pending_snapshot); | 627 | kfree(pending_snapshot); |
603 | return ret; | 628 | return ret; |
604 | } | 629 | } |
@@ -692,7 +717,7 @@ static noinline int btrfs_mksubvol(struct path *parent, | |||
692 | char *name, int namelen, | 717 | char *name, int namelen, |
693 | struct btrfs_root *snap_src, | 718 | struct btrfs_root *snap_src, |
694 | u64 *async_transid, bool readonly, | 719 | u64 *async_transid, bool readonly, |
695 | struct btrfs_qgroup_inherit **inherit) | 720 | struct btrfs_qgroup_inherit *inherit) |
696 | { | 721 | { |
697 | struct inode *dir = parent->dentry->d_inode; | 722 | struct inode *dir = parent->dentry->d_inode; |
698 | struct dentry *dentry; | 723 | struct dentry *dentry; |
@@ -729,11 +754,11 @@ static noinline int btrfs_mksubvol(struct path *parent, | |||
729 | goto out_up_read; | 754 | goto out_up_read; |
730 | 755 | ||
731 | if (snap_src) { | 756 | if (snap_src) { |
732 | error = create_snapshot(snap_src, dentry, name, namelen, | 757 | error = create_snapshot(snap_src, dir, dentry, name, namelen, |
733 | async_transid, readonly, inherit); | 758 | async_transid, readonly, inherit); |
734 | } else { | 759 | } else { |
735 | error = create_subvol(BTRFS_I(dir)->root, dentry, | 760 | error = create_subvol(dir, dentry, name, namelen, |
736 | name, namelen, async_transid, inherit); | 761 | async_transid, inherit); |
737 | } | 762 | } |
738 | if (!error) | 763 | if (!error) |
739 | fsnotify_mkdir(dir, dentry); | 764 | fsnotify_mkdir(dir, dentry); |
@@ -815,7 +840,7 @@ static int find_new_extents(struct btrfs_root *root, | |||
815 | 840 | ||
816 | while(1) { | 841 | while(1) { |
817 | ret = btrfs_search_forward(root, &min_key, &max_key, | 842 | ret = btrfs_search_forward(root, &min_key, &max_key, |
818 | path, 0, newer_than); | 843 | path, newer_than); |
819 | if (ret != 0) | 844 | if (ret != 0) |
820 | goto none; | 845 | goto none; |
821 | if (min_key.objectid != ino) | 846 | if (min_key.objectid != ino) |
@@ -1203,6 +1228,12 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, | |||
1203 | if (!(inode->i_sb->s_flags & MS_ACTIVE)) | 1228 | if (!(inode->i_sb->s_flags & MS_ACTIVE)) |
1204 | break; | 1229 | break; |
1205 | 1230 | ||
1231 | if (btrfs_defrag_cancelled(root->fs_info)) { | ||
1232 | printk(KERN_DEBUG "btrfs: defrag_file cancelled\n"); | ||
1233 | ret = -EAGAIN; | ||
1234 | break; | ||
1235 | } | ||
1236 | |||
1206 | if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, | 1237 | if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT, |
1207 | extent_thresh, &last_len, &skip, | 1238 | extent_thresh, &last_len, &skip, |
1208 | &defrag_end, range->flags & | 1239 | &defrag_end, range->flags & |
@@ -1317,7 +1348,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1317 | u64 new_size; | 1348 | u64 new_size; |
1318 | u64 old_size; | 1349 | u64 old_size; |
1319 | u64 devid = 1; | 1350 | u64 devid = 1; |
1320 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 1351 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
1321 | struct btrfs_ioctl_vol_args *vol_args; | 1352 | struct btrfs_ioctl_vol_args *vol_args; |
1322 | struct btrfs_trans_handle *trans; | 1353 | struct btrfs_trans_handle *trans; |
1323 | struct btrfs_device *device = NULL; | 1354 | struct btrfs_device *device = NULL; |
@@ -1326,9 +1357,6 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1326 | int ret = 0; | 1357 | int ret = 0; |
1327 | int mod = 0; | 1358 | int mod = 0; |
1328 | 1359 | ||
1329 | if (root->fs_info->sb->s_flags & MS_RDONLY) | ||
1330 | return -EROFS; | ||
1331 | |||
1332 | if (!capable(CAP_SYS_ADMIN)) | 1360 | if (!capable(CAP_SYS_ADMIN)) |
1333 | return -EPERM; | 1361 | return -EPERM; |
1334 | 1362 | ||
@@ -1339,7 +1367,8 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1339 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 1367 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
1340 | 1)) { | 1368 | 1)) { |
1341 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 1369 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
1342 | return -EINPROGRESS; | 1370 | mnt_drop_write_file(file); |
1371 | return -EINVAL; | ||
1343 | } | 1372 | } |
1344 | 1373 | ||
1345 | mutex_lock(&root->fs_info->volume_mutex); | 1374 | mutex_lock(&root->fs_info->volume_mutex); |
@@ -1359,21 +1388,27 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1359 | *devstr = '\0'; | 1388 | *devstr = '\0'; |
1360 | devstr = vol_args->name; | 1389 | devstr = vol_args->name; |
1361 | devid = simple_strtoull(devstr, &end, 10); | 1390 | devid = simple_strtoull(devstr, &end, 10); |
1391 | if (!devid) { | ||
1392 | ret = -EINVAL; | ||
1393 | goto out_free; | ||
1394 | } | ||
1362 | printk(KERN_INFO "btrfs: resizing devid %llu\n", | 1395 | printk(KERN_INFO "btrfs: resizing devid %llu\n", |
1363 | (unsigned long long)devid); | 1396 | (unsigned long long)devid); |
1364 | } | 1397 | } |
1398 | |||
1365 | device = btrfs_find_device(root->fs_info, devid, NULL, NULL); | 1399 | device = btrfs_find_device(root->fs_info, devid, NULL, NULL); |
1366 | if (!device) { | 1400 | if (!device) { |
1367 | printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", | 1401 | printk(KERN_INFO "btrfs: resizer unable to find device %llu\n", |
1368 | (unsigned long long)devid); | 1402 | (unsigned long long)devid); |
1369 | ret = -EINVAL; | 1403 | ret = -ENODEV; |
1370 | goto out_free; | 1404 | goto out_free; |
1371 | } | 1405 | } |
1372 | if (device->fs_devices && device->fs_devices->seeding) { | 1406 | |
1407 | if (!device->writeable) { | ||
1373 | printk(KERN_INFO "btrfs: resizer unable to apply on " | 1408 | printk(KERN_INFO "btrfs: resizer unable to apply on " |
1374 | "seeding device %llu\n", | 1409 | "readonly device %llu\n", |
1375 | (unsigned long long)devid); | 1410 | (unsigned long long)devid); |
1376 | ret = -EINVAL; | 1411 | ret = -EPERM; |
1377 | goto out_free; | 1412 | goto out_free; |
1378 | } | 1413 | } |
1379 | 1414 | ||
@@ -1395,7 +1430,7 @@ static noinline int btrfs_ioctl_resize(struct file *file, | |||
1395 | } | 1430 | } |
1396 | 1431 | ||
1397 | if (device->is_tgtdev_for_dev_replace) { | 1432 | if (device->is_tgtdev_for_dev_replace) { |
1398 | ret = -EINVAL; | 1433 | ret = -EPERM; |
1399 | goto out_free; | 1434 | goto out_free; |
1400 | } | 1435 | } |
1401 | 1436 | ||
@@ -1443,15 +1478,15 @@ out_free: | |||
1443 | kfree(vol_args); | 1478 | kfree(vol_args); |
1444 | out: | 1479 | out: |
1445 | mutex_unlock(&root->fs_info->volume_mutex); | 1480 | mutex_unlock(&root->fs_info->volume_mutex); |
1446 | mnt_drop_write_file(file); | ||
1447 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 1481 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
1482 | mnt_drop_write_file(file); | ||
1448 | return ret; | 1483 | return ret; |
1449 | } | 1484 | } |
1450 | 1485 | ||
1451 | static noinline int btrfs_ioctl_snap_create_transid(struct file *file, | 1486 | static noinline int btrfs_ioctl_snap_create_transid(struct file *file, |
1452 | char *name, unsigned long fd, int subvol, | 1487 | char *name, unsigned long fd, int subvol, |
1453 | u64 *transid, bool readonly, | 1488 | u64 *transid, bool readonly, |
1454 | struct btrfs_qgroup_inherit **inherit) | 1489 | struct btrfs_qgroup_inherit *inherit) |
1455 | { | 1490 | { |
1456 | int namelen; | 1491 | int namelen; |
1457 | int ret = 0; | 1492 | int ret = 0; |
@@ -1483,8 +1518,8 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file, | |||
1483 | goto out_drop_write; | 1518 | goto out_drop_write; |
1484 | } | 1519 | } |
1485 | 1520 | ||
1486 | src_inode = src.file->f_path.dentry->d_inode; | 1521 | src_inode = file_inode(src.file); |
1487 | if (src_inode->i_sb != file->f_path.dentry->d_inode->i_sb) { | 1522 | if (src_inode->i_sb != file_inode(file)->i_sb) { |
1488 | printk(KERN_INFO "btrfs: Snapshot src from " | 1523 | printk(KERN_INFO "btrfs: Snapshot src from " |
1489 | "another FS\n"); | 1524 | "another FS\n"); |
1490 | ret = -EINVAL; | 1525 | ret = -EINVAL; |
@@ -1560,7 +1595,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, | |||
1560 | 1595 | ||
1561 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, | 1596 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, |
1562 | vol_args->fd, subvol, ptr, | 1597 | vol_args->fd, subvol, ptr, |
1563 | readonly, &inherit); | 1598 | readonly, inherit); |
1564 | 1599 | ||
1565 | if (ret == 0 && ptr && | 1600 | if (ret == 0 && ptr && |
1566 | copy_to_user(arg + | 1601 | copy_to_user(arg + |
@@ -1576,7 +1611,7 @@ out: | |||
1576 | static noinline int btrfs_ioctl_subvol_getflags(struct file *file, | 1611 | static noinline int btrfs_ioctl_subvol_getflags(struct file *file, |
1577 | void __user *arg) | 1612 | void __user *arg) |
1578 | { | 1613 | { |
1579 | struct inode *inode = fdentry(file)->d_inode; | 1614 | struct inode *inode = file_inode(file); |
1580 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1615 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1581 | int ret = 0; | 1616 | int ret = 0; |
1582 | u64 flags = 0; | 1617 | u64 flags = 0; |
@@ -1598,7 +1633,7 @@ static noinline int btrfs_ioctl_subvol_getflags(struct file *file, | |||
1598 | static noinline int btrfs_ioctl_subvol_setflags(struct file *file, | 1633 | static noinline int btrfs_ioctl_subvol_setflags(struct file *file, |
1599 | void __user *arg) | 1634 | void __user *arg) |
1600 | { | 1635 | { |
1601 | struct inode *inode = fdentry(file)->d_inode; | 1636 | struct inode *inode = file_inode(file); |
1602 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1637 | struct btrfs_root *root = BTRFS_I(inode)->root; |
1603 | struct btrfs_trans_handle *trans; | 1638 | struct btrfs_trans_handle *trans; |
1604 | u64 root_flags; | 1639 | u64 root_flags; |
@@ -1857,7 +1892,7 @@ static noinline int search_ioctl(struct inode *inode, | |||
1857 | path->keep_locks = 1; | 1892 | path->keep_locks = 1; |
1858 | 1893 | ||
1859 | while(1) { | 1894 | while(1) { |
1860 | ret = btrfs_search_forward(root, &key, &max_key, path, 0, | 1895 | ret = btrfs_search_forward(root, &key, &max_key, path, |
1861 | sk->min_transid); | 1896 | sk->min_transid); |
1862 | if (ret != 0) { | 1897 | if (ret != 0) { |
1863 | if (ret > 0) | 1898 | if (ret > 0) |
@@ -1892,7 +1927,7 @@ static noinline int btrfs_ioctl_tree_search(struct file *file, | |||
1892 | if (IS_ERR(args)) | 1927 | if (IS_ERR(args)) |
1893 | return PTR_ERR(args); | 1928 | return PTR_ERR(args); |
1894 | 1929 | ||
1895 | inode = fdentry(file)->d_inode; | 1930 | inode = file_inode(file); |
1896 | ret = search_ioctl(inode, args); | 1931 | ret = search_ioctl(inode, args); |
1897 | if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) | 1932 | if (ret == 0 && copy_to_user(argp, args, sizeof(*args))) |
1898 | ret = -EFAULT; | 1933 | ret = -EFAULT; |
@@ -2002,7 +2037,7 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file, | |||
2002 | if (IS_ERR(args)) | 2037 | if (IS_ERR(args)) |
2003 | return PTR_ERR(args); | 2038 | return PTR_ERR(args); |
2004 | 2039 | ||
2005 | inode = fdentry(file)->d_inode; | 2040 | inode = file_inode(file); |
2006 | 2041 | ||
2007 | if (args->treeid == 0) | 2042 | if (args->treeid == 0) |
2008 | args->treeid = BTRFS_I(inode)->root->root_key.objectid; | 2043 | args->treeid = BTRFS_I(inode)->root->root_key.objectid; |
@@ -2029,6 +2064,8 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2029 | struct btrfs_root *dest = NULL; | 2064 | struct btrfs_root *dest = NULL; |
2030 | struct btrfs_ioctl_vol_args *vol_args; | 2065 | struct btrfs_ioctl_vol_args *vol_args; |
2031 | struct btrfs_trans_handle *trans; | 2066 | struct btrfs_trans_handle *trans; |
2067 | struct btrfs_block_rsv block_rsv; | ||
2068 | u64 qgroup_reserved; | ||
2032 | int namelen; | 2069 | int namelen; |
2033 | int ret; | 2070 | int ret; |
2034 | int err = 0; | 2071 | int err = 0; |
@@ -2095,13 +2132,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2095 | err = inode_permission(inode, MAY_WRITE | MAY_EXEC); | 2132 | err = inode_permission(inode, MAY_WRITE | MAY_EXEC); |
2096 | if (err) | 2133 | if (err) |
2097 | goto out_dput; | 2134 | goto out_dput; |
2098 | |||
2099 | /* check if subvolume may be deleted by a non-root user */ | ||
2100 | err = btrfs_may_delete(dir, dentry, 1); | ||
2101 | if (err) | ||
2102 | goto out_dput; | ||
2103 | } | 2135 | } |
2104 | 2136 | ||
2137 | /* check if subvolume may be deleted by a user */ | ||
2138 | err = btrfs_may_delete(dir, dentry, 1); | ||
2139 | if (err) | ||
2140 | goto out_dput; | ||
2141 | |||
2105 | if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) { | 2142 | if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) { |
2106 | err = -EINVAL; | 2143 | err = -EINVAL; |
2107 | goto out_dput; | 2144 | goto out_dput; |
@@ -2118,12 +2155,23 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2118 | if (err) | 2155 | if (err) |
2119 | goto out_up_write; | 2156 | goto out_up_write; |
2120 | 2157 | ||
2158 | btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP); | ||
2159 | /* | ||
2160 | * One for dir inode, two for dir entries, two for root | ||
2161 | * ref/backref. | ||
2162 | */ | ||
2163 | err = btrfs_subvolume_reserve_metadata(root, &block_rsv, | ||
2164 | 5, &qgroup_reserved); | ||
2165 | if (err) | ||
2166 | goto out_up_write; | ||
2167 | |||
2121 | trans = btrfs_start_transaction(root, 0); | 2168 | trans = btrfs_start_transaction(root, 0); |
2122 | if (IS_ERR(trans)) { | 2169 | if (IS_ERR(trans)) { |
2123 | err = PTR_ERR(trans); | 2170 | err = PTR_ERR(trans); |
2124 | goto out_up_write; | 2171 | goto out_release; |
2125 | } | 2172 | } |
2126 | trans->block_rsv = &root->fs_info->global_block_rsv; | 2173 | trans->block_rsv = &block_rsv; |
2174 | trans->bytes_reserved = block_rsv.size; | ||
2127 | 2175 | ||
2128 | ret = btrfs_unlink_subvol(trans, root, dir, | 2176 | ret = btrfs_unlink_subvol(trans, root, dir, |
2129 | dest->root_key.objectid, | 2177 | dest->root_key.objectid, |
@@ -2153,10 +2201,14 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file, | |||
2153 | } | 2201 | } |
2154 | } | 2202 | } |
2155 | out_end_trans: | 2203 | out_end_trans: |
2204 | trans->block_rsv = NULL; | ||
2205 | trans->bytes_reserved = 0; | ||
2156 | ret = btrfs_end_transaction(trans, root); | 2206 | ret = btrfs_end_transaction(trans, root); |
2157 | if (ret && !err) | 2207 | if (ret && !err) |
2158 | err = ret; | 2208 | err = ret; |
2159 | inode->i_flags |= S_DEAD; | 2209 | inode->i_flags |= S_DEAD; |
2210 | out_release: | ||
2211 | btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved); | ||
2160 | out_up_write: | 2212 | out_up_write: |
2161 | up_write(&root->fs_info->subvol_sem); | 2213 | up_write(&root->fs_info->subvol_sem); |
2162 | out_unlock: | 2214 | out_unlock: |
@@ -2165,6 +2217,12 @@ out_unlock: | |||
2165 | shrink_dcache_sb(root->fs_info->sb); | 2217 | shrink_dcache_sb(root->fs_info->sb); |
2166 | btrfs_invalidate_inodes(dest); | 2218 | btrfs_invalidate_inodes(dest); |
2167 | d_delete(dentry); | 2219 | d_delete(dentry); |
2220 | |||
2221 | /* the last ref */ | ||
2222 | if (dest->cache_inode) { | ||
2223 | iput(dest->cache_inode); | ||
2224 | dest->cache_inode = NULL; | ||
2225 | } | ||
2168 | } | 2226 | } |
2169 | out_dput: | 2227 | out_dput: |
2170 | dput(dentry); | 2228 | dput(dentry); |
@@ -2178,24 +2236,18 @@ out: | |||
2178 | 2236 | ||
2179 | static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | 2237 | static int btrfs_ioctl_defrag(struct file *file, void __user *argp) |
2180 | { | 2238 | { |
2181 | struct inode *inode = fdentry(file)->d_inode; | 2239 | struct inode *inode = file_inode(file); |
2182 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2240 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2183 | struct btrfs_ioctl_defrag_range_args *range; | 2241 | struct btrfs_ioctl_defrag_range_args *range; |
2184 | int ret; | 2242 | int ret; |
2185 | 2243 | ||
2186 | if (btrfs_root_readonly(root)) | ||
2187 | return -EROFS; | ||
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 | } | ||
2194 | ret = mnt_want_write_file(file); | 2244 | ret = mnt_want_write_file(file); |
2195 | if (ret) { | 2245 | if (ret) |
2196 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, | ||
2197 | 0); | ||
2198 | return ret; | 2246 | return ret; |
2247 | |||
2248 | if (btrfs_root_readonly(root)) { | ||
2249 | ret = -EROFS; | ||
2250 | goto out; | ||
2199 | } | 2251 | } |
2200 | 2252 | ||
2201 | switch (inode->i_mode & S_IFMT) { | 2253 | switch (inode->i_mode & S_IFMT) { |
@@ -2204,10 +2256,10 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2204 | ret = -EPERM; | 2256 | ret = -EPERM; |
2205 | goto out; | 2257 | goto out; |
2206 | } | 2258 | } |
2207 | ret = btrfs_defrag_root(root, 0); | 2259 | ret = btrfs_defrag_root(root); |
2208 | if (ret) | 2260 | if (ret) |
2209 | goto out; | 2261 | goto out; |
2210 | ret = btrfs_defrag_root(root->fs_info->extent_root, 0); | 2262 | ret = btrfs_defrag_root(root->fs_info->extent_root); |
2211 | break; | 2263 | break; |
2212 | case S_IFREG: | 2264 | case S_IFREG: |
2213 | if (!(file->f_mode & FMODE_WRITE)) { | 2265 | if (!(file->f_mode & FMODE_WRITE)) { |
@@ -2237,7 +2289,7 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2237 | /* the rest are all set to zero by kzalloc */ | 2289 | /* the rest are all set to zero by kzalloc */ |
2238 | range->len = (u64)-1; | 2290 | range->len = (u64)-1; |
2239 | } | 2291 | } |
2240 | ret = btrfs_defrag_file(fdentry(file)->d_inode, file, | 2292 | ret = btrfs_defrag_file(file_inode(file), file, |
2241 | range, 0, 0); | 2293 | range, 0, 0); |
2242 | if (ret > 0) | 2294 | if (ret > 0) |
2243 | ret = 0; | 2295 | ret = 0; |
@@ -2248,7 +2300,6 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2248 | } | 2300 | } |
2249 | out: | 2301 | out: |
2250 | mnt_drop_write_file(file); | 2302 | mnt_drop_write_file(file); |
2251 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
2252 | return ret; | 2303 | return ret; |
2253 | } | 2304 | } |
2254 | 2305 | ||
@@ -2263,7 +2314,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg) | |||
2263 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 2314 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, |
2264 | 1)) { | 2315 | 1)) { |
2265 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 2316 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
2266 | return -EINPROGRESS; | 2317 | return -EINVAL; |
2267 | } | 2318 | } |
2268 | 2319 | ||
2269 | mutex_lock(&root->fs_info->volume_mutex); | 2320 | mutex_lock(&root->fs_info->volume_mutex); |
@@ -2285,7 +2336,7 @@ out: | |||
2285 | 2336 | ||
2286 | static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | 2337 | static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) |
2287 | { | 2338 | { |
2288 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 2339 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
2289 | struct btrfs_ioctl_vol_args *vol_args; | 2340 | struct btrfs_ioctl_vol_args *vol_args; |
2290 | int ret; | 2341 | int ret; |
2291 | 2342 | ||
@@ -2300,7 +2351,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2300 | 1)) { | 2351 | 1)) { |
2301 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | 2352 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); |
2302 | mnt_drop_write_file(file); | 2353 | mnt_drop_write_file(file); |
2303 | return -EINPROGRESS; | 2354 | return -EINVAL; |
2304 | } | 2355 | } |
2305 | 2356 | ||
2306 | mutex_lock(&root->fs_info->volume_mutex); | 2357 | mutex_lock(&root->fs_info->volume_mutex); |
@@ -2316,8 +2367,8 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2316 | kfree(vol_args); | 2367 | kfree(vol_args); |
2317 | out: | 2368 | out: |
2318 | mutex_unlock(&root->fs_info->volume_mutex); | 2369 | mutex_unlock(&root->fs_info->volume_mutex); |
2319 | mnt_drop_write_file(file); | ||
2320 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | 2370 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); |
2371 | mnt_drop_write_file(file); | ||
2321 | return ret; | 2372 | return ret; |
2322 | } | 2373 | } |
2323 | 2374 | ||
@@ -2408,7 +2459,7 @@ out: | |||
2408 | static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | 2459 | static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, |
2409 | u64 off, u64 olen, u64 destoff) | 2460 | u64 off, u64 olen, u64 destoff) |
2410 | { | 2461 | { |
2411 | struct inode *inode = fdentry(file)->d_inode; | 2462 | struct inode *inode = file_inode(file); |
2412 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2463 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2413 | struct fd src_file; | 2464 | struct fd src_file; |
2414 | struct inode *src; | 2465 | struct inode *src; |
@@ -2454,7 +2505,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
2454 | if (src_file.file->f_path.mnt != file->f_path.mnt) | 2505 | if (src_file.file->f_path.mnt != file->f_path.mnt) |
2455 | goto out_fput; | 2506 | goto out_fput; |
2456 | 2507 | ||
2457 | src = src_file.file->f_dentry->d_inode; | 2508 | src = file_inode(src_file.file); |
2458 | 2509 | ||
2459 | ret = -EINVAL; | 2510 | ret = -EINVAL; |
2460 | if (src == inode) | 2511 | if (src == inode) |
@@ -2816,7 +2867,7 @@ static long btrfs_ioctl_clone_range(struct file *file, void __user *argp) | |||
2816 | */ | 2867 | */ |
2817 | static long btrfs_ioctl_trans_start(struct file *file) | 2868 | static long btrfs_ioctl_trans_start(struct file *file) |
2818 | { | 2869 | { |
2819 | struct inode *inode = fdentry(file)->d_inode; | 2870 | struct inode *inode = file_inode(file); |
2820 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2871 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2821 | struct btrfs_trans_handle *trans; | 2872 | struct btrfs_trans_handle *trans; |
2822 | int ret; | 2873 | int ret; |
@@ -2856,7 +2907,7 @@ out: | |||
2856 | 2907 | ||
2857 | static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | 2908 | static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) |
2858 | { | 2909 | { |
2859 | struct inode *inode = fdentry(file)->d_inode; | 2910 | struct inode *inode = file_inode(file); |
2860 | struct btrfs_root *root = BTRFS_I(inode)->root; | 2911 | struct btrfs_root *root = BTRFS_I(inode)->root; |
2861 | struct btrfs_root *new_root; | 2912 | struct btrfs_root *new_root; |
2862 | struct btrfs_dir_item *di; | 2913 | struct btrfs_dir_item *di; |
@@ -3080,7 +3131,7 @@ out: | |||
3080 | */ | 3131 | */ |
3081 | long btrfs_ioctl_trans_end(struct file *file) | 3132 | long btrfs_ioctl_trans_end(struct file *file) |
3082 | { | 3133 | { |
3083 | struct inode *inode = fdentry(file)->d_inode; | 3134 | struct inode *inode = file_inode(file); |
3084 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3135 | struct btrfs_root *root = BTRFS_I(inode)->root; |
3085 | struct btrfs_trans_handle *trans; | 3136 | struct btrfs_trans_handle *trans; |
3086 | 3137 | ||
@@ -3104,7 +3155,7 @@ static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root, | |||
3104 | u64 transid; | 3155 | u64 transid; |
3105 | int ret; | 3156 | int ret; |
3106 | 3157 | ||
3107 | trans = btrfs_attach_transaction(root); | 3158 | trans = btrfs_attach_transaction_barrier(root); |
3108 | if (IS_ERR(trans)) { | 3159 | if (IS_ERR(trans)) { |
3109 | if (PTR_ERR(trans) != -ENOENT) | 3160 | if (PTR_ERR(trans) != -ENOENT) |
3110 | return PTR_ERR(trans); | 3161 | return PTR_ERR(trans); |
@@ -3142,7 +3193,7 @@ static noinline long btrfs_ioctl_wait_sync(struct btrfs_root *root, | |||
3142 | 3193 | ||
3143 | static long btrfs_ioctl_scrub(struct file *file, void __user *arg) | 3194 | static long btrfs_ioctl_scrub(struct file *file, void __user *arg) |
3144 | { | 3195 | { |
3145 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3196 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3146 | struct btrfs_ioctl_scrub_args *sa; | 3197 | struct btrfs_ioctl_scrub_args *sa; |
3147 | int ret; | 3198 | int ret; |
3148 | 3199 | ||
@@ -3282,7 +3333,7 @@ static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg) | |||
3282 | struct inode_fs_paths *ipath = NULL; | 3333 | struct inode_fs_paths *ipath = NULL; |
3283 | struct btrfs_path *path; | 3334 | struct btrfs_path *path; |
3284 | 3335 | ||
3285 | if (!capable(CAP_SYS_ADMIN)) | 3336 | if (!capable(CAP_DAC_READ_SEARCH)) |
3286 | return -EPERM; | 3337 | return -EPERM; |
3287 | 3338 | ||
3288 | path = btrfs_alloc_path(); | 3339 | path = btrfs_alloc_path(); |
@@ -3433,12 +3484,12 @@ void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock, | |||
3433 | 3484 | ||
3434 | static long btrfs_ioctl_balance(struct file *file, void __user *arg) | 3485 | static long btrfs_ioctl_balance(struct file *file, void __user *arg) |
3435 | { | 3486 | { |
3436 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3487 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3437 | struct btrfs_fs_info *fs_info = root->fs_info; | 3488 | struct btrfs_fs_info *fs_info = root->fs_info; |
3438 | struct btrfs_ioctl_balance_args *bargs; | 3489 | struct btrfs_ioctl_balance_args *bargs; |
3439 | struct btrfs_balance_control *bctl; | 3490 | struct btrfs_balance_control *bctl; |
3491 | bool need_unlock; /* for mut. excl. ops lock */ | ||
3440 | int ret; | 3492 | int ret; |
3441 | int need_to_clear_lock = 0; | ||
3442 | 3493 | ||
3443 | if (!capable(CAP_SYS_ADMIN)) | 3494 | if (!capable(CAP_SYS_ADMIN)) |
3444 | return -EPERM; | 3495 | return -EPERM; |
@@ -3447,14 +3498,61 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3447 | if (ret) | 3498 | if (ret) |
3448 | return ret; | 3499 | return ret; |
3449 | 3500 | ||
3450 | mutex_lock(&fs_info->volume_mutex); | 3501 | again: |
3502 | if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) { | ||
3503 | mutex_lock(&fs_info->volume_mutex); | ||
3504 | mutex_lock(&fs_info->balance_mutex); | ||
3505 | need_unlock = true; | ||
3506 | goto locked; | ||
3507 | } | ||
3508 | |||
3509 | /* | ||
3510 | * mut. excl. ops lock is locked. Three possibilites: | ||
3511 | * (1) some other op is running | ||
3512 | * (2) balance is running | ||
3513 | * (3) balance is paused -- special case (think resume) | ||
3514 | */ | ||
3451 | mutex_lock(&fs_info->balance_mutex); | 3515 | mutex_lock(&fs_info->balance_mutex); |
3516 | if (fs_info->balance_ctl) { | ||
3517 | /* this is either (2) or (3) */ | ||
3518 | if (!atomic_read(&fs_info->balance_running)) { | ||
3519 | mutex_unlock(&fs_info->balance_mutex); | ||
3520 | if (!mutex_trylock(&fs_info->volume_mutex)) | ||
3521 | goto again; | ||
3522 | mutex_lock(&fs_info->balance_mutex); | ||
3523 | |||
3524 | if (fs_info->balance_ctl && | ||
3525 | !atomic_read(&fs_info->balance_running)) { | ||
3526 | /* this is (3) */ | ||
3527 | need_unlock = false; | ||
3528 | goto locked; | ||
3529 | } | ||
3530 | |||
3531 | mutex_unlock(&fs_info->balance_mutex); | ||
3532 | mutex_unlock(&fs_info->volume_mutex); | ||
3533 | goto again; | ||
3534 | } else { | ||
3535 | /* this is (2) */ | ||
3536 | mutex_unlock(&fs_info->balance_mutex); | ||
3537 | ret = -EINPROGRESS; | ||
3538 | goto out; | ||
3539 | } | ||
3540 | } else { | ||
3541 | /* this is (1) */ | ||
3542 | mutex_unlock(&fs_info->balance_mutex); | ||
3543 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
3544 | ret = -EINVAL; | ||
3545 | goto out; | ||
3546 | } | ||
3547 | |||
3548 | locked: | ||
3549 | BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running)); | ||
3452 | 3550 | ||
3453 | if (arg) { | 3551 | if (arg) { |
3454 | bargs = memdup_user(arg, sizeof(*bargs)); | 3552 | bargs = memdup_user(arg, sizeof(*bargs)); |
3455 | if (IS_ERR(bargs)) { | 3553 | if (IS_ERR(bargs)) { |
3456 | ret = PTR_ERR(bargs); | 3554 | ret = PTR_ERR(bargs); |
3457 | goto out; | 3555 | goto out_unlock; |
3458 | } | 3556 | } |
3459 | 3557 | ||
3460 | if (bargs->flags & BTRFS_BALANCE_RESUME) { | 3558 | if (bargs->flags & BTRFS_BALANCE_RESUME) { |
@@ -3474,13 +3572,10 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3474 | bargs = NULL; | 3572 | bargs = NULL; |
3475 | } | 3573 | } |
3476 | 3574 | ||
3477 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | 3575 | if (fs_info->balance_ctl) { |
3478 | 1)) { | ||
3479 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
3480 | ret = -EINPROGRESS; | 3576 | ret = -EINPROGRESS; |
3481 | goto out_bargs; | 3577 | goto out_bargs; |
3482 | } | 3578 | } |
3483 | need_to_clear_lock = 1; | ||
3484 | 3579 | ||
3485 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); | 3580 | bctl = kzalloc(sizeof(*bctl), GFP_NOFS); |
3486 | if (!bctl) { | 3581 | if (!bctl) { |
@@ -3501,11 +3596,17 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg) | |||
3501 | } | 3596 | } |
3502 | 3597 | ||
3503 | do_balance: | 3598 | do_balance: |
3504 | ret = btrfs_balance(bctl, bargs); | ||
3505 | /* | 3599 | /* |
3506 | * bctl is freed in __cancel_balance or in free_fs_info if | 3600 | * Ownership of bctl and mutually_exclusive_operation_running |
3507 | * restriper was paused all the way until unmount | 3601 | * goes to to btrfs_balance. bctl is freed in __cancel_balance, |
3602 | * or, if restriper was paused all the way until unmount, in | ||
3603 | * free_fs_info. mutually_exclusive_operation_running is | ||
3604 | * cleared in __cancel_balance. | ||
3508 | */ | 3605 | */ |
3606 | need_unlock = false; | ||
3607 | |||
3608 | ret = btrfs_balance(bctl, bargs); | ||
3609 | |||
3509 | if (arg) { | 3610 | if (arg) { |
3510 | if (copy_to_user(arg, bargs, sizeof(*bargs))) | 3611 | if (copy_to_user(arg, bargs, sizeof(*bargs))) |
3511 | ret = -EFAULT; | 3612 | ret = -EFAULT; |
@@ -3513,12 +3614,12 @@ do_balance: | |||
3513 | 3614 | ||
3514 | out_bargs: | 3615 | out_bargs: |
3515 | kfree(bargs); | 3616 | kfree(bargs); |
3516 | out: | 3617 | out_unlock: |
3517 | if (need_to_clear_lock) | ||
3518 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, | ||
3519 | 0); | ||
3520 | mutex_unlock(&fs_info->balance_mutex); | 3618 | mutex_unlock(&fs_info->balance_mutex); |
3521 | mutex_unlock(&fs_info->volume_mutex); | 3619 | mutex_unlock(&fs_info->volume_mutex); |
3620 | if (need_unlock) | ||
3621 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | ||
3622 | out: | ||
3522 | mnt_drop_write_file(file); | 3623 | mnt_drop_write_file(file); |
3523 | return ret; | 3624 | return ret; |
3524 | } | 3625 | } |
@@ -3573,7 +3674,7 @@ out: | |||
3573 | 3674 | ||
3574 | static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg) | 3675 | static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg) |
3575 | { | 3676 | { |
3576 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3677 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3577 | struct btrfs_ioctl_quota_ctl_args *sa; | 3678 | struct btrfs_ioctl_quota_ctl_args *sa; |
3578 | struct btrfs_trans_handle *trans = NULL; | 3679 | struct btrfs_trans_handle *trans = NULL; |
3579 | int ret; | 3680 | int ret; |
@@ -3632,7 +3733,7 @@ drop_write: | |||
3632 | 3733 | ||
3633 | static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg) | 3734 | static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg) |
3634 | { | 3735 | { |
3635 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3736 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3636 | struct btrfs_ioctl_qgroup_assign_args *sa; | 3737 | struct btrfs_ioctl_qgroup_assign_args *sa; |
3637 | struct btrfs_trans_handle *trans; | 3738 | struct btrfs_trans_handle *trans; |
3638 | int ret; | 3739 | int ret; |
@@ -3679,7 +3780,7 @@ drop_write: | |||
3679 | 3780 | ||
3680 | static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) | 3781 | static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) |
3681 | { | 3782 | { |
3682 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3783 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3683 | struct btrfs_ioctl_qgroup_create_args *sa; | 3784 | struct btrfs_ioctl_qgroup_create_args *sa; |
3684 | struct btrfs_trans_handle *trans; | 3785 | struct btrfs_trans_handle *trans; |
3685 | int ret; | 3786 | int ret; |
@@ -3698,6 +3799,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg) | |||
3698 | goto drop_write; | 3799 | goto drop_write; |
3699 | } | 3800 | } |
3700 | 3801 | ||
3802 | if (!sa->qgroupid) { | ||
3803 | ret = -EINVAL; | ||
3804 | goto out; | ||
3805 | } | ||
3806 | |||
3701 | trans = btrfs_join_transaction(root); | 3807 | trans = btrfs_join_transaction(root); |
3702 | if (IS_ERR(trans)) { | 3808 | if (IS_ERR(trans)) { |
3703 | ret = PTR_ERR(trans); | 3809 | ret = PTR_ERR(trans); |
@@ -3725,7 +3831,7 @@ drop_write: | |||
3725 | 3831 | ||
3726 | static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg) | 3832 | static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg) |
3727 | { | 3833 | { |
3728 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 3834 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3729 | struct btrfs_ioctl_qgroup_limit_args *sa; | 3835 | struct btrfs_ioctl_qgroup_limit_args *sa; |
3730 | struct btrfs_trans_handle *trans; | 3836 | struct btrfs_trans_handle *trans; |
3731 | int ret; | 3837 | int ret; |
@@ -3775,7 +3881,7 @@ static long btrfs_ioctl_set_received_subvol(struct file *file, | |||
3775 | void __user *arg) | 3881 | void __user *arg) |
3776 | { | 3882 | { |
3777 | struct btrfs_ioctl_received_subvol_args *sa = NULL; | 3883 | struct btrfs_ioctl_received_subvol_args *sa = NULL; |
3778 | struct inode *inode = fdentry(file)->d_inode; | 3884 | struct inode *inode = file_inode(file); |
3779 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3885 | struct btrfs_root *root = BTRFS_I(inode)->root; |
3780 | struct btrfs_root_item *root_item = &root->root_item; | 3886 | struct btrfs_root_item *root_item = &root->root_item; |
3781 | struct btrfs_trans_handle *trans; | 3887 | struct btrfs_trans_handle *trans; |
@@ -3852,10 +3958,69 @@ out: | |||
3852 | return ret; | 3958 | return ret; |
3853 | } | 3959 | } |
3854 | 3960 | ||
3961 | static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg) | ||
3962 | { | ||
3963 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3964 | const char *label = root->fs_info->super_copy->label; | ||
3965 | size_t len = strnlen(label, BTRFS_LABEL_SIZE); | ||
3966 | int ret; | ||
3967 | |||
3968 | if (len == BTRFS_LABEL_SIZE) { | ||
3969 | pr_warn("btrfs: label is too long, return the first %zu bytes\n", | ||
3970 | --len); | ||
3971 | } | ||
3972 | |||
3973 | mutex_lock(&root->fs_info->volume_mutex); | ||
3974 | ret = copy_to_user(arg, label, len); | ||
3975 | mutex_unlock(&root->fs_info->volume_mutex); | ||
3976 | |||
3977 | return ret ? -EFAULT : 0; | ||
3978 | } | ||
3979 | |||
3980 | static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg) | ||
3981 | { | ||
3982 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | ||
3983 | struct btrfs_super_block *super_block = root->fs_info->super_copy; | ||
3984 | struct btrfs_trans_handle *trans; | ||
3985 | char label[BTRFS_LABEL_SIZE]; | ||
3986 | int ret; | ||
3987 | |||
3988 | if (!capable(CAP_SYS_ADMIN)) | ||
3989 | return -EPERM; | ||
3990 | |||
3991 | if (copy_from_user(label, arg, sizeof(label))) | ||
3992 | return -EFAULT; | ||
3993 | |||
3994 | if (strnlen(label, BTRFS_LABEL_SIZE) == BTRFS_LABEL_SIZE) { | ||
3995 | pr_err("btrfs: unable to set label with more than %d bytes\n", | ||
3996 | BTRFS_LABEL_SIZE - 1); | ||
3997 | return -EINVAL; | ||
3998 | } | ||
3999 | |||
4000 | ret = mnt_want_write_file(file); | ||
4001 | if (ret) | ||
4002 | return ret; | ||
4003 | |||
4004 | mutex_lock(&root->fs_info->volume_mutex); | ||
4005 | trans = btrfs_start_transaction(root, 0); | ||
4006 | if (IS_ERR(trans)) { | ||
4007 | ret = PTR_ERR(trans); | ||
4008 | goto out_unlock; | ||
4009 | } | ||
4010 | |||
4011 | strcpy(super_block->label, label); | ||
4012 | ret = btrfs_end_transaction(trans, root); | ||
4013 | |||
4014 | out_unlock: | ||
4015 | mutex_unlock(&root->fs_info->volume_mutex); | ||
4016 | mnt_drop_write_file(file); | ||
4017 | return ret; | ||
4018 | } | ||
4019 | |||
3855 | long btrfs_ioctl(struct file *file, unsigned int | 4020 | long btrfs_ioctl(struct file *file, unsigned int |
3856 | cmd, unsigned long arg) | 4021 | cmd, unsigned long arg) |
3857 | { | 4022 | { |
3858 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 4023 | struct btrfs_root *root = BTRFS_I(file_inode(file))->root; |
3859 | void __user *argp = (void __user *)arg; | 4024 | void __user *argp = (void __user *)arg; |
3860 | 4025 | ||
3861 | switch (cmd) { | 4026 | switch (cmd) { |
@@ -3952,6 +4117,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
3952 | return btrfs_ioctl_qgroup_limit(file, argp); | 4117 | return btrfs_ioctl_qgroup_limit(file, argp); |
3953 | case BTRFS_IOC_DEV_REPLACE: | 4118 | case BTRFS_IOC_DEV_REPLACE: |
3954 | return btrfs_ioctl_dev_replace(root, argp); | 4119 | return btrfs_ioctl_dev_replace(root, argp); |
4120 | case BTRFS_IOC_GET_FSLABEL: | ||
4121 | return btrfs_ioctl_get_fslabel(file, argp); | ||
4122 | case BTRFS_IOC_SET_FSLABEL: | ||
4123 | return btrfs_ioctl_set_fslabel(file, argp); | ||
3955 | } | 4124 | } |
3956 | 4125 | ||
3957 | return -ENOTTY; | 4126 | return -ENOTTY; |