diff options
author | Arne Jansen <sensille@gmx.net> | 2011-09-14 09:58:21 -0400 |
---|---|---|
committer | Jan Schmidt <list.btrfs@jan-o-sch.net> | 2012-07-12 04:54:40 -0400 |
commit | 6f72c7e20dbaea55f04546de69586c84a3654503 (patch) | |
tree | 4d8e13968765f4a4381a0fe91a4fb157128cbbc5 /fs | |
parent | 5d13a37bd5327220e13329943d1228acfbe5934a (diff) |
Btrfs: add qgroup inheritance
When creating a subvolume or snapshot, it is necessary
to initialize the qgroup account with a copy of some
other (tracking) qgroup. This patch adds parameters
to the ioctls to pass the information from which qgroup
to inherit.
Signed-off-by: Arne Jansen <sensille@gmx.net>
Diffstat (limited to 'fs')
-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 */ |