From: Jeff Mahoney <jeffm@suse.com>
To: linux-btrfs <linux-btrfs@vger.kernel.org>
Cc: David Sterba <dsterba@suse.cz>, Arvin Schnell <aschnell@suse.de>
Subject: [PATCH] btrfs: extend BTRFS_IOC_SNAP_CREATE_V2 to snapshot by subvolid
Date: Mon, 24 Mar 2014 19:58:32 -0400 [thread overview]
Message-ID: <5330C6A8.5050206@suse.com> (raw)
The BTRFS_IOC_SNAP_CREATE_V2 ioctl is limited by requiring that a file
descriptor be passed in order to create the snapshot. This means that
snapshots may only be created of trees that are available in the mounted
namespace. We have a need to create snapshots from subvolumes outside
of the namespace. This is already possible by mounting the numbered
subvolume by ID on a separate mount point, creating the snapshot, and
unmounting it. That's a tedious and unnecessary process since the ioctl
can be extended so easily.
This patch adds a new BTRFS_SUBVOL_CREATE_SUBVOLID flag that instructs
the ioctl to use the fd argument (which is now a union) as a subvolume
id instead. The subvolume ID is used to look up the root and instantiate
the inode so proper permission checking takes place.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
fs/btrfs/ioctl.c | 77 +++++++++++++++++++++++++++++++++++----------
include/uapi/linux/btrfs.h | 6 ++-
2 files changed, 65 insertions(+), 18 deletions(-)
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1535,8 +1535,8 @@ out:
}
static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
- char *name, unsigned long fd, int subvol,
- u64 *transid, bool readonly,
+ char *name, struct inode *src_inode,
+ int subvol, u64 *transid, bool readonly,
struct btrfs_qgroup_inherit *inherit)
{
int namelen;
@@ -1562,14 +1562,6 @@ static noinline int btrfs_ioctl_snap_cre
ret = btrfs_mksubvol(&file->f_path, name, namelen,
NULL, transid, readonly, inherit);
} else {
- struct fd src = fdget(fd);
- struct inode *src_inode;
- if (!src.file) {
- ret = -EINVAL;
- goto out_drop_write;
- }
-
- src_inode = file_inode(src.file);
if (src_inode->i_sb != file_inode(file)->i_sb) {
btrfs_info(BTRFS_I(src_inode)->root->fs_info,
"Snapshot src from another FS");
@@ -1585,7 +1577,6 @@ static noinline int btrfs_ioctl_snap_cre
BTRFS_I(src_inode)->root,
transid, readonly, inherit);
}
- fdput(src);
}
out_drop_write:
mnt_drop_write_file(file);
@@ -1597,6 +1588,7 @@ static noinline int btrfs_ioctl_snap_cre
void __user *arg, int subvol)
{
struct btrfs_ioctl_vol_args *vol_args;
+ struct fd src;
int ret;
vol_args = memdup_user(arg, sizeof(*vol_args));
@@ -1604,10 +1596,19 @@ static noinline int btrfs_ioctl_snap_cre
return PTR_ERR(vol_args);
vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
+ if (!subvol) {
+ src = fdget(vol_args->fd);
+ if (!src.file) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ }
+
ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
- vol_args->fd, subvol,
+ file_inode(src.file), subvol,
NULL, false, NULL);
-
+ fdput(src);
+out_free:
kfree(vol_args);
return ret;
}
@@ -1621,6 +1622,8 @@ static noinline int btrfs_ioctl_snap_cre
u64 *ptr = NULL;
bool readonly = false;
struct btrfs_qgroup_inherit *inherit = NULL;
+ struct fd src;
+ struct inode *src_inode = NULL;
vol_args = memdup_user(arg, sizeof(*vol_args));
if (IS_ERR(vol_args))
@@ -1629,7 +1632,7 @@ static noinline int btrfs_ioctl_snap_cre
if (vol_args->flags &
~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY |
- BTRFS_SUBVOL_QGROUP_INHERIT)) {
+ BTRFS_SUBVOL_QGROUP_INHERIT|BTRFS_SUBVOL_CREATE_SUBVOLID)) {
ret = -EOPNOTSUPP;
goto out;
}
@@ -1650,9 +1653,49 @@ static noinline int btrfs_ioctl_snap_cre
}
}
- ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
- vol_args->fd, subvol, ptr,
- readonly, inherit);
+ if (!subvol) {
+ if (vol_args->flags & BTRFS_SUBVOL_CREATE_SUBVOLID) {
+ struct super_block *sb = file_inode(file)->i_sb;
+ struct btrfs_root *root;
+ struct btrfs_key location = {
+ .objectid = vol_args->subvolid,
+ .offset = -1,
+ .type = BTRFS_ROOT_ITEM_KEY,
+ };
+
+ root = btrfs_get_fs_root(btrfs_sb(sb), &location, true);
+ if (IS_ERR(root)) {
+ ret = PTR_ERR(root);
+ goto out;
+ }
+
+ location.objectid = btrfs_root_dirid(&root->root_item);
+ location.type = BTRFS_INODE_ITEM_KEY;
+ location.offset = 0;
+ src_inode = btrfs_iget(sb, &location, root, NULL);
+ if (IS_ERR(src_inode)) {
+ ret = PTR_ERR(src_inode);
+ goto out;
+ }
+ } else {
+ src = fdget(vol_args->fd);
+ if (!src.file) {
+ ret = -EINVAL;
+ goto out;
+ }
+ src_inode = file_inode(src.file);
+ }
+ }
+
+ ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, src_inode,
+ subvol, ptr, readonly, inherit);
+
+ if (!subvol) {
+ if (vol_args->flags & BTRFS_SUBVOL_CREATE_SUBVOLID)
+ iput(src_inode);
+ else
+ fdput(src);
+ }
if (ret == 0 && ptr &&
copy_to_user(arg +
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -36,6 +36,7 @@ struct btrfs_ioctl_vol_args {
#define BTRFS_SUBVOL_CREATE_ASYNC (1ULL << 0)
#define BTRFS_SUBVOL_RDONLY (1ULL << 1)
#define BTRFS_SUBVOL_QGROUP_INHERIT (1ULL << 2)
+#define BTRFS_SUBVOL_CREATE_SUBVOLID (1ULL << 3)
#define BTRFS_FSID_SIZE 16
#define BTRFS_UUID_SIZE 16
@@ -65,7 +66,10 @@ struct btrfs_ioctl_qgroup_limit_args {
#define BTRFS_SUBVOL_NAME_MAX 4039
struct btrfs_ioctl_vol_args_v2 {
- __s64 fd;
+ union {
+ __s64 fd;
+ __u64 subvolid;
+ };
__u64 transid;
__u64 flags;
union {
--
Jeff Mahoney
SUSE Labs
next reply other threads:[~2014-03-24 23:58 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-24 23:58 Jeff Mahoney [this message]
2014-05-14 12:51 ` [PATCH] btrfs: extend BTRFS_IOC_SNAP_CREATE_V2 to snapshot by subvolid Chris Mason
2014-07-23 12:41 ` David Sterba
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5330C6A8.5050206@suse.com \
--to=jeffm@suse.com \
--cc=aschnell@suse.de \
--cc=dsterba@suse.cz \
--cc=linux-btrfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.