aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2009-12-11 16:11:29 -0500
committerChris Mason <chris.mason@oracle.com>2010-03-15 11:00:08 -0400
commit6ef5ed0d386be5c43ec66d6f2999919c0893558b (patch)
tree7ec391a0525506eb03bcbb0b5e19709f530b0b74 /fs/btrfs
parent73f73415caddbc01d9f10c03e0a677d5b3d11569 (diff)
Btrfs: add ioctl and incompat flag to set the default mount subvol
This patch needs to go along with my previous patch. This lets us set the default dir item's location to whatever root we want to use as our default mounting subvol. With this we don't have to use mount -o subvol=<tree id> anymore to mount a different subvol, we can just set the new one and it will just magically work. I've done some moderate testing with this, mostly just switching the default mount around, mounting subvols and the default mount at the same time and such, everything seems to work. Thanks, Older kernels would generally be able to still mount the filesystem with the default subvolume set, but it would result in a different volume being mounted, which could be an even more unpleasant suprise for users. So if you set your default subvolume, you can't go back to older kernels. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/ioctl.c75
-rw-r--r--fs/btrfs/ioctl.h2
3 files changed, 80 insertions, 1 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 07d956977a0..1166b15e9bf 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 c6044733198..7875a75315d 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
1582static 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 79c07b104f9..f1923e0260e 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