Commit 6ef5ed0d authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

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: default avatarJosef Bacik <josef@redhat.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 73f73415
...@@ -373,11 +373,13 @@ struct btrfs_super_block { ...@@ -373,11 +373,13 @@ struct btrfs_super_block {
* ones specified below then we will fail to mount * ones specified below then we will fail to mount
*/ */
#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0)
#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (2ULL << 0)
#define BTRFS_FEATURE_COMPAT_SUPP 0ULL #define BTRFS_FEATURE_COMPAT_SUPP 0ULL
#define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL #define BTRFS_FEATURE_COMPAT_RO_SUPP 0ULL
#define BTRFS_FEATURE_INCOMPAT_SUPP \ #define BTRFS_FEATURE_INCOMPAT_SUPP \
BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \
BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL)
/* /*
* A leaf is full of items. offset and size tell us where to find * A leaf is full of items. offset and size tell us where to find
......
...@@ -1579,6 +1579,79 @@ static long btrfs_ioctl_trans_start(struct file *file) ...@@ -1579,6 +1579,79 @@ static long btrfs_ioctl_trans_start(struct file *file)
return ret; return ret;
} }
static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
{
struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_root *new_root;
struct btrfs_dir_item *di;
struct btrfs_trans_handle *trans;
struct btrfs_path *path;
struct btrfs_key location;
struct btrfs_disk_key disk_key;
struct btrfs_super_block *disk_super;
u64 features;
u64 objectid = 0;
u64 dir_id;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user(&objectid, argp, sizeof(objectid)))
return -EFAULT;
if (!objectid)
objectid = root->root_key.objectid;
location.objectid = objectid;
location.type = BTRFS_ROOT_ITEM_KEY;
location.offset = (u64)-1;
new_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
if (IS_ERR(new_root))
return PTR_ERR(new_root);
if (btrfs_root_refs(&new_root->root_item) == 0)
return -ENOENT;
path = btrfs_alloc_path();
if (!path)
return -ENOMEM;
path->leave_spinning = 1;
trans = btrfs_start_transaction(root, 1);
if (!trans) {
btrfs_free_path(path);
return -ENOMEM;
}
dir_id = btrfs_super_root_dir(&root->fs_info->super_copy);
di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path,
dir_id, "default", 7, 1);
if (!di) {
btrfs_free_path(path);
btrfs_end_transaction(trans, root);
printk(KERN_ERR "Umm, you don't have the default dir item, "
"this isn't going to work\n");
return -ENOENT;
}
btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key);
btrfs_set_dir_item_key(path->nodes[0], di, &disk_key);
btrfs_mark_buffer_dirty(path->nodes[0]);
btrfs_free_path(path);
disk_super = &root->fs_info->super_copy;
features = btrfs_super_incompat_flags(disk_super);
if (!(features & BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL)) {
features |= BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL;
btrfs_set_super_incompat_flags(disk_super, features);
}
btrfs_end_transaction(trans, root);
return 0;
}
/* /*
* there are many ways the trans_start and trans_end ioctls can lead * there are many ways the trans_start and trans_end ioctls can lead
* to deadlocks. They should only be used by applications that * to deadlocks. They should only be used by applications that
...@@ -1625,6 +1698,8 @@ long btrfs_ioctl(struct file *file, unsigned int ...@@ -1625,6 +1698,8 @@ long btrfs_ioctl(struct file *file, unsigned int
return btrfs_ioctl_snap_create(file, argp, 1); return btrfs_ioctl_snap_create(file, argp, 1);
case BTRFS_IOC_SNAP_DESTROY: case BTRFS_IOC_SNAP_DESTROY:
return btrfs_ioctl_snap_destroy(file, argp); return btrfs_ioctl_snap_destroy(file, argp);
case BTRFS_IOC_DEFAULT_SUBVOL:
return btrfs_ioctl_default_subvol(file, argp);
case BTRFS_IOC_DEFRAG: case BTRFS_IOC_DEFRAG:
return btrfs_ioctl_defrag(file); return btrfs_ioctl_defrag(file);
case BTRFS_IOC_RESIZE: case BTRFS_IOC_RESIZE:
......
/* /*
* Copyright (C) 2007 Oracle. All rights reserved. * Copyright (C) 2007 Oracle. All rights reserved.
* *
...@@ -133,4 +134,5 @@ struct btrfs_ioctl_clone_range_args { ...@@ -133,4 +134,5 @@ struct btrfs_ioctl_clone_range_args {
struct btrfs_ioctl_search_args) struct btrfs_ioctl_search_args)
#define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \
struct btrfs_ioctl_ino_lookup_args) struct btrfs_ioctl_ino_lookup_args)
#define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, u64)
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment