From: Liu Bo <liubo2009@cn.fujitsu.com>
To: <linux-btrfs@vger.kernel.org>
Subject: [PATCH 2/3] Btrfs: update subvol_getflags/setflags to know new args from user
Date: Fri, 29 Jun 2012 17:59:54 +0800 [thread overview]
Message-ID: <1340963995-32549-2-git-send-email-liubo2009@cn.fujitsu.com> (raw)
In-Reply-To: <1340963995-32549-1-git-send-email-liubo2009@cn.fujitsu.com>
I've modified 'btrfs subvolume list' to show a subvolume's attributes,
such as readonly and default, and adopted a new structure for args for
subvol_getflags/setflags.
So here is the kernel side update.
Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
---
fs/btrfs/ioctl.c | 100 ++++++++++++++++++++++++++++++++++++++++-------------
fs/btrfs/ioctl.h | 5 +++
2 files changed, 80 insertions(+), 25 deletions(-)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 60fff96..f9c2180 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1487,6 +1487,31 @@ out:
return ret;
}
+static struct btrfs_root *__btrfs_subvol_get_root(struct btrfs_root *root,
+ u64 root_id)
+{
+ struct btrfs_key root_key;
+ struct btrfs_root *root_ret = NULL;
+
+ if (root->objectid == root_id || !root_id) {
+ root_ret = root;
+ goto get_root;
+ }
+
+ root_key.objectid = root_id;
+ root_key.type = BTRFS_ROOT_ITEM_KEY;
+ root_key.offset = (u64)-1;
+ root_ret = btrfs_read_fs_root_no_name(root->fs_info, &root_key);
+ /* root_ret won't be NULL */
+ if (IS_ERR(root_ret))
+ return root_ret;
+get_root:
+ if (btrfs_root_refs(&root_ret->root_item) == 0)
+ return ERR_PTR(-ENOENT);
+
+ return root_ret;
+}
+
/* Return 1 for default, otherwise return 0. */
static int btrfs_root_default(struct btrfs_root *root)
{
@@ -1525,24 +1550,38 @@ static noinline int btrfs_ioctl_subvol_getflags(struct file *file,
{
struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_root *new_root = NULL;
int ret = 0;
- u64 flags = 0;
+ struct btrfs_ioctl_get_set_flags_args *get_args;
if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID)
return -EINVAL;
- down_read(&root->fs_info->subvol_sem);
- if (btrfs_root_readonly(root))
- flags |= BTRFS_SUBVOL_RDONLY;
+ get_args = memdup_user(arg, sizeof(*get_args));
+ if (IS_ERR(get_args))
+ return PTR_ERR(get_args);
- ret = btrfs_root_default(root);
- if (ret > 0)
- flags |= BTRFS_SUBVOL_DEFAULT;
- up_read(&root->fs_info->subvol_sem);
+ new_root = __btrfs_subvol_get_root(root, get_args->objectid);
+ if (IS_ERR(new_root)) {
+ ret = PTR_ERR(new_root);
+ goto out;
+ }
- if (copy_to_user(arg, &flags, sizeof(flags)))
+ down_read(&new_root->fs_info->subvol_sem);
+ if (btrfs_root_readonly(new_root))
+ get_args->flags |= BTRFS_SUBVOL_RDONLY;
+ ret = btrfs_root_default(new_root);
+ if (ret > 0) {
+ get_args->flags |= BTRFS_SUBVOL_DEFAULT;
+ ret = 0;
+ }
+ up_read(&new_root->fs_info->subvol_sem);
+
+ if (copy_to_user(arg, get_args, sizeof(*get_args)))
ret = -EFAULT;
+out:
+ kfree(get_args);
return ret;
}
@@ -1551,8 +1590,10 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
{
struct inode *inode = fdentry(file)->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_root *new_root = NULL;
struct btrfs_trans_handle *trans;
- u64 root_flags;
+ struct btrfs_ioctl_get_set_flags_args *set_args = NULL;
+ u64 root_flags, new_root_flags;
u64 flags;
int ret = 0;
@@ -1565,11 +1606,19 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
goto out_drop_write;
}
- if (copy_from_user(&flags, arg, sizeof(flags))) {
- ret = -EFAULT;
+ set_args = memdup_user(arg, sizeof(*set_args));
+ if (IS_ERR(set_args)) {
+ ret = PTR_ERR(set_args);
+ goto out_drop_write;
+ }
+
+ new_root = __btrfs_subvol_get_root(root, set_args->objectid);
+ if (IS_ERR(new_root)) {
+ ret = PTR_ERR(new_root);
goto out_drop_write;
}
+ flags = set_args->flags;
if (flags & BTRFS_SUBVOL_CREATE_ASYNC) {
ret = -EINVAL;
goto out_drop_write;
@@ -1585,38 +1634,39 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
goto out_drop_write;
}
- down_write(&root->fs_info->subvol_sem);
+ down_write(&new_root->fs_info->subvol_sem);
/* nothing to do */
- if (!!(flags & BTRFS_SUBVOL_RDONLY) == btrfs_root_readonly(root))
+ if (!!(flags & BTRFS_SUBVOL_RDONLY) == btrfs_root_readonly(new_root))
goto out_drop_sem;
- root_flags = btrfs_root_flags(&root->root_item);
+ new_root_flags = root_flags = btrfs_root_flags(&new_root->root_item);
if (flags & BTRFS_SUBVOL_RDONLY)
- btrfs_set_root_flags(&root->root_item,
- root_flags | BTRFS_ROOT_SUBVOL_RDONLY);
+ new_root_flags |= BTRFS_ROOT_SUBVOL_RDONLY;
else
- btrfs_set_root_flags(&root->root_item,
- root_flags & ~BTRFS_ROOT_SUBVOL_RDONLY);
+ new_root_flags &= ~BTRFS_ROOT_SUBVOL_RDONLY;
- trans = btrfs_start_transaction(root, 1);
+ btrfs_set_root_flags(&new_root->root_item, new_root_flags);
+
+ trans = btrfs_start_transaction(new_root, 1);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
goto out_reset;
}
- ret = btrfs_update_root(trans, root->fs_info->tree_root,
- &root->root_key, &root->root_item);
+ ret = btrfs_update_root(trans, new_root->fs_info->tree_root,
+ &new_root->root_key, &new_root->root_item);
- btrfs_commit_transaction(trans, root);
+ btrfs_commit_transaction(trans, new_root);
out_reset:
if (ret)
- btrfs_set_root_flags(&root->root_item, root_flags);
+ btrfs_set_root_flags(&new_root->root_item, root_flags);
out_drop_sem:
- up_write(&root->fs_info->subvol_sem);
+ up_write(&new_root->fs_info->subvol_sem);
out_drop_write:
mnt_drop_write_file(file);
out:
+ kfree(set_args);
return ret;
}
diff --git a/fs/btrfs/ioctl.h b/fs/btrfs/ioctl.h
index 3186d2d..1fa0ce2 100644
--- a/fs/btrfs/ioctl.h
+++ b/fs/btrfs/ioctl.h
@@ -45,6 +45,11 @@ struct btrfs_ioctl_vol_args_v2 {
char name[BTRFS_SUBVOL_NAME_MAX + 1];
};
+struct btrfs_ioctl_get_set_flags_args {
+ __u64 objectid;
+ __u64 flags;
+};
+
/*
* structure to report errors and progress to userspace, either as a
* result of a finished scrub, a canceled scrub or a progress inquiry
--
1.6.5.2
next prev parent reply other threads:[~2012-06-29 9:55 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-06-29 9:59 [PATCH 1/3] Btrfs: add default support for subvol getflags Liu Bo
2012-06-29 9:59 ` Liu Bo [this message]
2012-07-03 11:27 ` [PATCH 2/3] Btrfs: update subvol_getflags/setflags to know new args from user Alexander Block
2012-07-03 12:04 ` Liu Bo
2012-07-03 12:09 ` Alexander Block
2012-07-03 16:08 ` Josef Bacik
2012-07-04 0:57 ` Liu Bo
2012-06-29 9:59 ` [PATCH 3/3] Btrfs: use helper function to simplify code Liu Bo
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=1340963995-32549-2-git-send-email-liubo2009@cn.fujitsu.com \
--to=liubo2009@cn.fujitsu.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).