diff options
| -rw-r--r-- | fs/btrfs/ioctl.c | 59 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.h | 11 | ||||
| -rw-r--r-- | fs/btrfs/transaction.c | 8 | ||||
| -rw-r--r-- | fs/btrfs/transaction.h | 1 |
4 files changed, 61 insertions, 18 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 55a7283a9e18..1dffd0adf975 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -336,7 +336,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
| 336 | static noinline int create_subvol(struct btrfs_root *root, | 336 | static noinline int create_subvol(struct btrfs_root *root, |
| 337 | struct dentry *dentry, | 337 | struct dentry *dentry, |
| 338 | char *name, int namelen, | 338 | char *name, int namelen, |
| 339 | u64 *async_transid) | 339 | u64 *async_transid, |
| 340 | struct btrfs_qgroup_inherit **inherit) | ||
| 340 | { | 341 | { |
| 341 | struct btrfs_trans_handle *trans; | 342 | struct btrfs_trans_handle *trans; |
| 342 | struct btrfs_key key; | 343 | struct btrfs_key key; |
| @@ -368,6 +369,11 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 368 | if (IS_ERR(trans)) | 369 | if (IS_ERR(trans)) |
| 369 | return PTR_ERR(trans); | 370 | return PTR_ERR(trans); |
| 370 | 371 | ||
| 372 | ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, | ||
| 373 | inherit ? *inherit : NULL); | ||
| 374 | if (ret) | ||
| 375 | goto fail; | ||
| 376 | |||
| 371 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | 377 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
| 372 | 0, objectid, NULL, 0, 0, 0); | 378 | 0, objectid, NULL, 0, 0, 0); |
| 373 | if (IS_ERR(leaf)) { | 379 | if (IS_ERR(leaf)) { |
| @@ -484,7 +490,7 @@ fail: | |||
| 484 | 490 | ||
| 485 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | 491 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, |
| 486 | char *name, int namelen, u64 *async_transid, | 492 | char *name, int namelen, u64 *async_transid, |
| 487 | bool readonly) | 493 | bool readonly, struct btrfs_qgroup_inherit **inherit) |
| 488 | { | 494 | { |
| 489 | struct inode *inode; | 495 | struct inode *inode; |
| 490 | struct btrfs_pending_snapshot *pending_snapshot; | 496 | struct btrfs_pending_snapshot *pending_snapshot; |
| @@ -502,6 +508,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 502 | pending_snapshot->dentry = dentry; | 508 | pending_snapshot->dentry = dentry; |
| 503 | pending_snapshot->root = root; | 509 | pending_snapshot->root = root; |
| 504 | pending_snapshot->readonly = readonly; | 510 | pending_snapshot->readonly = readonly; |
| 511 | if (inherit) { | ||
| 512 | pending_snapshot->inherit = *inherit; | ||
| 513 | *inherit = NULL; /* take responsibility to free it */ | ||
| 514 | } | ||
| 505 | 515 | ||
| 506 | trans = btrfs_start_transaction(root->fs_info->extent_root, 5); | 516 | trans = btrfs_start_transaction(root->fs_info->extent_root, 5); |
| 507 | if (IS_ERR(trans)) { | 517 | if (IS_ERR(trans)) { |
| @@ -635,7 +645,8 @@ static inline int btrfs_may_create(struct inode *dir, struct dentry *child) | |||
| 635 | static noinline int btrfs_mksubvol(struct path *parent, | 645 | static noinline int btrfs_mksubvol(struct path *parent, |
| 636 | char *name, int namelen, | 646 | char *name, int namelen, |
| 637 | struct btrfs_root *snap_src, | 647 | struct btrfs_root *snap_src, |
| 638 | u64 *async_transid, bool readonly) | 648 | u64 *async_transid, bool readonly, |
| 649 | struct btrfs_qgroup_inherit **inherit) | ||
| 639 | { | 650 | { |
| 640 | struct inode *dir = parent->dentry->d_inode; | 651 | struct inode *dir = parent->dentry->d_inode; |
| 641 | struct dentry *dentry; | 652 | struct dentry *dentry; |
| @@ -666,11 +677,11 @@ static noinline int btrfs_mksubvol(struct path *parent, | |||
| 666 | goto out_up_read; | 677 | goto out_up_read; |
| 667 | 678 | ||
| 668 | if (snap_src) { | 679 | if (snap_src) { |
| 669 | error = create_snapshot(snap_src, dentry, | 680 | error = create_snapshot(snap_src, dentry, name, namelen, |
| 670 | name, namelen, async_transid, readonly); | 681 | async_transid, readonly, inherit); |
| 671 | } else { | 682 | } else { |
| 672 | error = create_subvol(BTRFS_I(dir)->root, dentry, | 683 | error = create_subvol(BTRFS_I(dir)->root, dentry, |
| 673 | name, namelen, async_transid); | 684 | name, namelen, async_transid, inherit); |
| 674 | } | 685 | } |
| 675 | if (!error) | 686 | if (!error) |
| 676 | fsnotify_mkdir(dir, dentry); | 687 | fsnotify_mkdir(dir, dentry); |
| @@ -1379,11 +1390,9 @@ out: | |||
| 1379 | } | 1390 | } |
| 1380 | 1391 | ||
| 1381 | static noinline int btrfs_ioctl_snap_create_transid(struct file *file, | 1392 | static noinline int btrfs_ioctl_snap_create_transid(struct file *file, |
| 1382 | char *name, | 1393 | char *name, unsigned long fd, int subvol, |
| 1383 | unsigned long fd, | 1394 | u64 *transid, bool readonly, |
| 1384 | int subvol, | 1395 | struct btrfs_qgroup_inherit **inherit) |
| 1385 | u64 *transid, | ||
| 1386 | bool readonly) | ||
| 1387 | { | 1396 | { |
| 1388 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; | 1397 | struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root; |
| 1389 | struct file *src_file; | 1398 | struct file *src_file; |
| @@ -1407,7 +1416,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file, | |||
| 1407 | 1416 | ||
| 1408 | if (subvol) { | 1417 | if (subvol) { |
| 1409 | ret = btrfs_mksubvol(&file->f_path, name, namelen, | 1418 | ret = btrfs_mksubvol(&file->f_path, name, namelen, |
| 1410 | NULL, transid, readonly); | 1419 | NULL, transid, readonly, inherit); |
| 1411 | } else { | 1420 | } else { |
| 1412 | struct inode *src_inode; | 1421 | struct inode *src_inode; |
| 1413 | src_file = fget(fd); | 1422 | src_file = fget(fd); |
| @@ -1426,7 +1435,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file, | |||
| 1426 | } | 1435 | } |
| 1427 | ret = btrfs_mksubvol(&file->f_path, name, namelen, | 1436 | ret = btrfs_mksubvol(&file->f_path, name, namelen, |
| 1428 | BTRFS_I(src_inode)->root, | 1437 | BTRFS_I(src_inode)->root, |
| 1429 | transid, readonly); | 1438 | transid, readonly, inherit); |
| 1430 | fput(src_file); | 1439 | fput(src_file); |
| 1431 | } | 1440 | } |
| 1432 | out: | 1441 | out: |
| @@ -1446,7 +1455,7 @@ static noinline int btrfs_ioctl_snap_create(struct file *file, | |||
| 1446 | 1455 | ||
| 1447 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, | 1456 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, |
| 1448 | vol_args->fd, subvol, | 1457 | vol_args->fd, subvol, |
| 1449 | NULL, false); | 1458 | NULL, false, NULL); |
| 1450 | 1459 | ||
| 1451 | kfree(vol_args); | 1460 | kfree(vol_args); |
| 1452 | return ret; | 1461 | return ret; |
| @@ -1460,6 +1469,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, | |||
| 1460 | u64 transid = 0; | 1469 | u64 transid = 0; |
| 1461 | u64 *ptr = NULL; | 1470 | u64 *ptr = NULL; |
| 1462 | bool readonly = false; | 1471 | bool readonly = false; |
| 1472 | struct btrfs_qgroup_inherit *inherit = NULL; | ||
| 1463 | 1473 | ||
| 1464 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 1474 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
| 1465 | if (IS_ERR(vol_args)) | 1475 | if (IS_ERR(vol_args)) |
| @@ -1467,7 +1477,8 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, | |||
| 1467 | vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; | 1477 | vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0'; |
| 1468 | 1478 | ||
| 1469 | if (vol_args->flags & | 1479 | if (vol_args->flags & |
| 1470 | ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY)) { | 1480 | ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY | |
| 1481 | BTRFS_SUBVOL_QGROUP_INHERIT)) { | ||
| 1471 | ret = -EOPNOTSUPP; | 1482 | ret = -EOPNOTSUPP; |
| 1472 | goto out; | 1483 | goto out; |
| 1473 | } | 1484 | } |
| @@ -1476,10 +1487,21 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, | |||
| 1476 | ptr = &transid; | 1487 | ptr = &transid; |
| 1477 | if (vol_args->flags & BTRFS_SUBVOL_RDONLY) | 1488 | if (vol_args->flags & BTRFS_SUBVOL_RDONLY) |
| 1478 | readonly = true; | 1489 | readonly = true; |
| 1490 | if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) { | ||
| 1491 | if (vol_args->size > PAGE_CACHE_SIZE) { | ||
| 1492 | ret = -EINVAL; | ||
| 1493 | goto out; | ||
| 1494 | } | ||
| 1495 | inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size); | ||
| 1496 | if (IS_ERR(inherit)) { | ||
| 1497 | ret = PTR_ERR(inherit); | ||
| 1498 | goto out; | ||
| 1499 | } | ||
| 1500 | } | ||
| 1479 | 1501 | ||
| 1480 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, | 1502 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, |
| 1481 | vol_args->fd, subvol, | 1503 | vol_args->fd, subvol, ptr, |
| 1482 | ptr, readonly); | 1504 | readonly, &inherit); |
| 1483 | 1505 | ||
| 1484 | if (ret == 0 && ptr && | 1506 | if (ret == 0 && ptr && |
| 1485 | copy_to_user(arg + | 1507 | copy_to_user(arg + |
| @@ -1488,6 +1510,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, | |||
| 1488 | ret = -EFAULT; | 1510 | ret = -EFAULT; |
| 1489 | out: | 1511 | out: |
| 1490 | kfree(vol_args); | 1512 | kfree(vol_args); |
| 1513 | kfree(inherit); | ||
| 1491 | return ret; | 1514 | return ret; |
| 1492 | } | 1515 | } |
| 1493 | 1516 | ||
| @@ -3588,6 +3611,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 3588 | return btrfs_ioctl_snap_create_v2(file, argp, 0); | 3611 | return btrfs_ioctl_snap_create_v2(file, argp, 0); |
| 3589 | case BTRFS_IOC_SUBVOL_CREATE: | 3612 | case BTRFS_IOC_SUBVOL_CREATE: |
| 3590 | return btrfs_ioctl_snap_create(file, argp, 1); | 3613 | return btrfs_ioctl_snap_create(file, argp, 1); |
| 3614 | case BTRFS_IOC_SUBVOL_CREATE_V2: | ||
| 3615 | return btrfs_ioctl_snap_create_v2(file, argp, 1); | ||
| 3591 | case BTRFS_IOC_SNAP_DESTROY: | 3616 | case BTRFS_IOC_SNAP_DESTROY: |
| 3592 | return btrfs_ioctl_snap_destroy(file, argp); | 3617 | return btrfs_ioctl_snap_destroy(file, argp); |
| 3593 | case BTRFS_IOC_SUBVOL_GETFLAGS: | 3618 | case BTRFS_IOC_SUBVOL_GETFLAGS: |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 9dd50c4656b3..cdda57f1c240 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
| @@ -32,6 +32,7 @@ struct btrfs_ioctl_vol_args { | |||
| 32 | 32 | ||
| 33 | #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) | 33 | #define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0) |
| 34 | #define BTRFS_SUBVOL_RDONLY (1ULL << 1) | 34 | #define BTRFS_SUBVOL_RDONLY (1ULL << 1) |
| 35 | #define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2) | ||
| 35 | #define BTRFS_FSID_SIZE 16 | 36 | #define BTRFS_FSID_SIZE 16 |
| 36 | #define BTRFS_UUID_SIZE 16 | 37 | #define BTRFS_UUID_SIZE 16 |
| 37 | 38 | ||
| @@ -64,7 +65,13 @@ struct btrfs_ioctl_vol_args_v2 { | |||
| 64 | __s64 fd; | 65 | __s64 fd; |
| 65 | __u64 transid; | 66 | __u64 transid; |
| 66 | __u64 flags; | 67 | __u64 flags; |
| 67 | __u64 unused[4]; | 68 | union { |
| 69 | struct { | ||
| 70 | __u64 size; | ||
| 71 | struct btrfs_qgroup_inherit __user *qgroup_inherit; | ||
| 72 | }; | ||
| 73 | __u64 unused[4]; | ||
| 74 | }; | ||
| 68 | char name[BTRFS_SUBVOL_NAME_MAX + 1]; | 75 | char name[BTRFS_SUBVOL_NAME_MAX + 1]; |
| 69 | }; | 76 | }; |
| 70 | 77 | ||
| @@ -382,6 +389,8 @@ struct btrfs_ioctl_qgroup_create_args { | |||
| 382 | #define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) | 389 | #define BTRFS_IOC_WAIT_SYNC _IOW(BTRFS_IOCTL_MAGIC, 22, __u64) |
| 383 | #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ | 390 | #define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \ |
| 384 | struct btrfs_ioctl_vol_args_v2) | 391 | struct btrfs_ioctl_vol_args_v2) |
| 392 | #define BTRFS_IOC_SUBVOL_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 24, \ | ||
| 393 | struct btrfs_ioctl_vol_args_v2) | ||
| 385 | #define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64) | 394 | #define BTRFS_IOC_SUBVOL_GETFLAGS _IOR(BTRFS_IOCTL_MAGIC, 25, __u64) |
| 386 | #define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64) | 395 | #define BTRFS_IOC_SUBVOL_SETFLAGS _IOW(BTRFS_IOCTL_MAGIC, 26, __u64) |
| 387 | #define BTRFS_IOC_SCRUB _IOWR(BTRFS_IOCTL_MAGIC, 27, \ | 396 | #define BTRFS_IOC_SCRUB _IOWR(BTRFS_IOCTL_MAGIC, 27, \ |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index f1e29fbd5317..127283913a42 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -990,6 +990,14 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 990 | } | 990 | } |
| 991 | } | 991 | } |
| 992 | 992 | ||
| 993 | ret = btrfs_qgroup_inherit(trans, fs_info, root->root_key.objectid, | ||
| 994 | objectid, pending->inherit); | ||
| 995 | kfree(pending->inherit); | ||
| 996 | if (ret) { | ||
| 997 | pending->error = ret; | ||
| 998 | goto fail; | ||
| 999 | } | ||
| 1000 | |||
| 993 | key.objectid = objectid; | 1001 | key.objectid = objectid; |
| 994 | key.offset = (u64)-1; | 1002 | key.offset = (u64)-1; |
| 995 | key.type = BTRFS_ROOT_ITEM_KEY; | 1003 | key.type = BTRFS_ROOT_ITEM_KEY; |
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h index 2759e0572c5c..cca315dcdfcd 100644 --- a/fs/btrfs/transaction.h +++ b/fs/btrfs/transaction.h | |||
| @@ -73,6 +73,7 @@ struct btrfs_pending_snapshot { | |||
| 73 | struct dentry *dentry; | 73 | struct dentry *dentry; |
| 74 | struct btrfs_root *root; | 74 | struct btrfs_root *root; |
| 75 | struct btrfs_root *snap; | 75 | struct btrfs_root *snap; |
| 76 | struct btrfs_qgroup_inherit *inherit; | ||
| 76 | /* block reservation for the operation */ | 77 | /* block reservation for the operation */ |
| 77 | struct btrfs_block_rsv block_rsv; | 78 | struct btrfs_block_rsv block_rsv; |
| 78 | /* extra metadata reseration for relocation */ | 79 | /* extra metadata reseration for relocation */ |
