aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorArne Jansen <sensille@gmx.net>2011-09-14 09:58:21 -0400
committerJan Schmidt <list.btrfs@jan-o-sch.net>2012-07-12 04:54:40 -0400
commit6f72c7e20dbaea55f04546de69586c84a3654503 (patch)
tree4d8e13968765f4a4381a0fe91a4fb157128cbbc5 /fs/btrfs
parent5d13a37bd5327220e13329943d1228acfbe5934a (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')
-rw-r--r--fs/btrfs/ioctl.c59
-rw-r--r--fs/btrfs/ioctl.h11
-rw-r--r--fs/btrfs/transaction.c8
-rw-r--r--fs/btrfs/transaction.h1
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)
336static noinline int create_subvol(struct btrfs_root *root, 336static 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
485static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, 491static 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)
635static noinline int btrfs_mksubvol(struct path *parent, 645static 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
1381static noinline int btrfs_ioctl_snap_create_transid(struct file *file, 1392static 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 }
1432out: 1441out:
@@ -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;
1489out: 1511out:
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 */