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/btrfs/ioctl.c | |
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/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 59 |
1 files changed, 42 insertions, 17 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: |