diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 75 | ||||
-rw-r--r-- | fs/btrfs/ioctl.h | 2 |
3 files changed, 80 insertions, 1 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 07d956977a07..1166b15e9bf6 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -373,11 +373,13 @@ struct btrfs_super_block { | |||
373 | * ones specified below then we will fail to mount | 373 | * ones specified below then we will fail to mount |
374 | */ | 374 | */ |
375 | #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) | 375 | #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) |
376 | #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (2ULL << 0) | ||
376 | 377 | ||
377 | #define BTRFS_FEATURE_COMPAT_SUPP 0ULL | 378 | #define BTRFS_FEATURE_COMPAT_SUPP 0ULL |
378 | #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL | 379 | #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL |
379 | #define BTRFS_FEATURE_INCOMPAT_SUPP \ | 380 | #define BTRFS_FEATURE_INCOMPAT_SUPP \ |
380 | BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | 381 | (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \ |
382 | BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL) | ||
381 | 383 | ||
382 | /* | 384 | /* |
383 | * A leaf is full of items. offset and size tell us where to find | 385 | * A leaf is full of items. offset and size tell us where to find |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c6044733198d..7875a75315d0 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -1579,6 +1579,79 @@ out: | |||
1579 | return ret; | 1579 | return ret; |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | ||
1583 | { | ||
1584 | struct inode *inode = fdentry(file)->d_inode; | ||
1585 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1586 | struct btrfs_root *new_root; | ||
1587 | struct btrfs_dir_item *di; | ||
1588 | struct btrfs_trans_handle *trans; | ||
1589 | struct btrfs_path *path; | ||
1590 | struct btrfs_key location; | ||
1591 | struct btrfs_disk_key disk_key; | ||
1592 | struct btrfs_super_block *disk_super; | ||
1593 | u64 features; | ||
1594 | u64 objectid = 0; | ||
1595 | u64 dir_id; | ||
1596 | |||
1597 | if (!capable(CAP_SYS_ADMIN)) | ||
1598 | return -EPERM; | ||
1599 | |||
1600 | if (copy_from_user(&objectid, argp, sizeof(objectid))) | ||
1601 | return -EFAULT; | ||
1602 | |||
1603 | if (!objectid) | ||
1604 | objectid = root->root_key.objectid; | ||
1605 | |||
1606 | location.objectid = objectid; | ||
1607 | location.type = BTRFS_ROOT_ITEM_KEY; | ||
1608 | location.offset = (u64)-1; | ||
1609 | |||
1610 | new_root = btrfs_read_fs_root_no_name(root->fs_info, &location); | ||
1611 | if (IS_ERR(new_root)) | ||
1612 | return PTR_ERR(new_root); | ||
1613 | |||
1614 | if (btrfs_root_refs(&new_root->root_item) == 0) | ||
1615 | return -ENOENT; | ||
1616 | |||
1617 | path = btrfs_alloc_path(); | ||
1618 | if (!path) | ||
1619 | return -ENOMEM; | ||
1620 | path->leave_spinning = 1; | ||
1621 | |||
1622 | trans = btrfs_start_transaction(root, 1); | ||
1623 | if (!trans) { | ||
1624 | btrfs_free_path(path); | ||
1625 | return -ENOMEM; | ||
1626 | } | ||
1627 | |||
1628 | dir_id = btrfs_super_root_dir(&root->fs_info->super_copy); | ||
1629 | di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path, | ||
1630 | dir_id, "default", 7, 1); | ||
1631 | if (!di) { | ||
1632 | btrfs_free_path(path); | ||
1633 | btrfs_end_transaction(trans, root); | ||
1634 | printk(KERN_ERR "Umm, you don't have the default dir item, " | ||
1635 | "this isn't going to work\n"); | ||
1636 | return -ENOENT; | ||
1637 | } | ||
1638 | |||
1639 | btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key); | ||
1640 | btrfs_set_dir_item_key(path->nodes[0], di, &disk_key); | ||
1641 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
1642 | btrfs_free_path(path); | ||
1643 | |||
1644 | disk_super = &root->fs_info->super_copy; | ||
1645 | features = btrfs_super_incompat_flags(disk_super); | ||
1646 | if (!(features & BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL)) { | ||
1647 | features |= BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL; | ||
1648 | btrfs_set_super_incompat_flags(disk_super, features); | ||
1649 | } | ||
1650 | btrfs_end_transaction(trans, root); | ||
1651 | |||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1582 | /* | 1655 | /* |
1583 | * there are many ways the trans_start and trans_end ioctls can lead | 1656 | * there are many ways the trans_start and trans_end ioctls can lead |
1584 | * to deadlocks. They should only be used by applications that | 1657 | * to deadlocks. They should only be used by applications that |
@@ -1625,6 +1698,8 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
1625 | return btrfs_ioctl_snap_create(file, argp, 1); | 1698 | return btrfs_ioctl_snap_create(file, argp, 1); |
1626 | case BTRFS_IOC_SNAP_DESTROY: | 1699 | case BTRFS_IOC_SNAP_DESTROY: |
1627 | return btrfs_ioctl_snap_destroy(file, argp); | 1700 | return btrfs_ioctl_snap_destroy(file, argp); |
1701 | case BTRFS_IOC_DEFAULT_SUBVOL: | ||
1702 | return btrfs_ioctl_default_subvol(file, argp); | ||
1628 | case BTRFS_IOC_DEFRAG: | 1703 | case BTRFS_IOC_DEFRAG: |
1629 | return btrfs_ioctl_defrag(file); | 1704 | return btrfs_ioctl_defrag(file); |
1630 | case BTRFS_IOC_RESIZE: | 1705 | case BTRFS_IOC_RESIZE: |
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h index 79c07b104f91..f1923e0260e3 100644 --- a/fs/btrfs/ioctl.h +++ b/fs/btrfs/ioctl.h | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | /* | 2 | /* |
2 | * Copyright (C) 2007 Oracle. All rights reserved. | 3 | * Copyright (C) 2007 Oracle. All rights reserved. |
3 | * | 4 | * |
@@ -133,4 +134,5 @@ struct btrfs_ioctl_clone_range_args { | |||
133 | struct btrfs_ioctl_search_args) | 134 | struct btrfs_ioctl_search_args) |
134 | #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ | 135 | #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ |
135 | struct btrfs_ioctl_ino_lookup_args) | 136 | struct btrfs_ioctl_ino_lookup_args) |
137 | #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64) | ||
136 | #endif | 138 | #endif |