RE: [PATCH v6 1/3] btrfs: Add unprivileged ioctl which returns subvolume information
> -Original Message- > From: linux-btrfs-ow...@vger.kernel.org > [mailto:linux-btrfs-ow...@vger.kernel.org] On Behalf Of Tomohiro Misono > Sent: Friday, May 18, 2018 10:55 AM > To: linux-btrfs@vger.kernel.org > Subject: [PATCH v6 1/3] btrfs: Add unprivileged ioctl which returns subvolume > information > > Add new unprivileged ioctl BTRFS_IOC_GET_SUBVOL_INFO which returns the > information of subvolume containing this inode. > (i.e. returns the information in ROOT_ITEM and ROOT_BACKREF.) > > Signed-off-by: Tomohiro Misono> --- > v5 -> v6 > - Use brfs_read_fs_root_no_name() to get subvolume root and simplify > code > v4 -> v5 > - Update error handling of btrfs_next_leaf() to cover all cases > - Return error if ROOT_BACKREF is not found (except top-level) > > fs/btrfs/ioctl.c | 125 > + > include/uapi/linux/btrfs.h | 51 ++ > 2 files changed, 176 insertions(+) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index > 48e2ddff32bd..31af6e91c614 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -2242,6 +2242,129 @@ static noinline int btrfs_ioctl_ino_lookup(struct > file *file, > return ret; > } > > +/* Get the subvolume information in BTRFS_ROOT_ITEM and > +BTRFS_ROOT_BACKREF */ static noinline int btrfs_ioctl_get_subvol_info(struct > file *file, > +void __user *argp) > +{ > + struct btrfs_ioctl_get_subvol_info_args *subvol_info; > + struct btrfs_fs_info *fs_info; > + struct btrfs_root *root; > + struct btrfs_path *path; > + struct btrfs_key key; > + > + struct btrfs_root_item *root_item; > + struct btrfs_root_ref *rref; > + struct extent_buffer *l; > + int slot; > + > + unsigned long item_off; > + unsigned long item_len; > + > + struct inode *inode; > + int ret = 0; > + > + path = btrfs_alloc_path(); > + if (!path) > + return -ENOMEM; > + > + subvol_info = kzalloc(sizeof(*subvol_info), GFP_KERNEL); > + if (!subvol_info) { > + btrfs_free_path(path); > + return -ENOMEM; > + } > + > + inode = file_inode(file); > + fs_info = BTRFS_I(inode)->root->fs_info; > + > + /* Get root_item of inode's subvolume */ > + key.objectid = BTRFS_I(inode)->root->root_key.objectid; > + key.type = BTRFS_ROOT_ITEM_KEY; > + key.offset = (u64)-1; > + root = btrfs_read_fs_root_no_name(fs_info, ); > + if (IS_ERR(root)) { > + ret = PTR_ERR(root); > + goto out; > + } > + root_item = >root_item; > + > + subvol_info->id = key.objectid; > + > + subvol_info->generation = btrfs_root_generation(root_item); > + subvol_info->flags = btrfs_root_flags(root_item); > + > + memcpy(subvol_info->uuid, root_item->uuid, BTRFS_UUID_SIZE); > + memcpy(subvol_info->parent_uuid, root_item->parent_uuid, > + BTRFS_UUID_SIZE); > + memcpy(subvol_info->received_uuid, root_item->received_uuid, > + BTRFS_UUID_SIZE); > + > + subvol_info->ctransid = btrfs_root_ctransid(root_item); > + subvol_info->ctime.sec = btrfs_stack_timespec_sec(_item->otime); > + subvol_info->ctime.nsec = > +btrfs_stack_timespec_nsec(_item->ctime); > + > + subvol_info->otransid = btrfs_root_otransid(root_item); > + subvol_info->otime.sec = btrfs_stack_timespec_sec(_item->otime); > + subvol_info->otime.nsec = > +btrfs_stack_timespec_nsec(_item->otime); > + > + subvol_info->stransid = btrfs_root_stransid(root_item); > + subvol_info->stime.sec = btrfs_stack_timespec_sec(_item->stime); > + subvol_info->stime.nsec = > +btrfs_stack_timespec_nsec(_item->stime); > + > + subvol_info->rtransid = btrfs_root_rtransid(root_item); > + subvol_info->rtime.sec = btrfs_stack_timespec_sec(_item->rtime); > + subvol_info->rtime.nsec = > +btrfs_stack_timespec_nsec(_item->rtime); > + > + if (key.objectid != BTRFS_FS_TREE_OBJECTID) { > + /* Search root tree for ROOT_BACKREF of this subvolume */ > + root = fs_info->tree_root; > + > + key.type = BTRFS_ROOT_BACKREF_KEY; > + key.offset = 0; > + ret = btrfs_search_slot(NULL, root, , path, 0, 0); > + if (ret < 0) { > + goto out; > + } else if (path->slots[0] >= > + btrfs_header_nritems(path->nodes[0])) { > + ret = btrfs_next_leaf(root, path); > + if (ret < 0) { > + goto out; > + } else if (ret > 0) { > + ret = -EUCLEAN; > + goto out; > + } > + } > + > + l = path->nodes[0]; > + slot = path->slots[0]; > +
RE: [PATCH v6 1/3] btrfs: Add unprivileged ioctl which returns subvolume information
> -Original Message- > From: linux-btrfs-ow...@vger.kernel.org > [mailto:linux-btrfs-ow...@vger.kernel.org] On Behalf Of Tomohiro Misono > Sent: Friday, May 18, 2018 10:55 AM > To: linux-btrfs@vger.kernel.org > Subject: [PATCH v6 1/3] btrfs: Add unprivileged ioctl which returns subvolume > information > > Add new unprivileged ioctl BTRFS_IOC_GET_SUBVOL_INFO which returns the > information of subvolume containing this inode. > (i.e. returns the information in ROOT_ITEM and ROOT_BACKREF.) > > Signed-off-by: Tomohiro Misono> --- > v5 -> v6 > - Use brfs_read_fs_root_no_name() to get subvolume root and simplify > code > v4 -> v5 > - Update error handling of btrfs_next_leaf() to cover all cases > - Return error if ROOT_BACKREF is not found (except top-level) > > fs/btrfs/ioctl.c | 125 > + > include/uapi/linux/btrfs.h | 51 ++ > 2 files changed, 176 insertions(+) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index > 48e2ddff32bd..31af6e91c614 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -2242,6 +2242,129 @@ static noinline int btrfs_ioctl_ino_lookup(struct > file *file, > return ret; > } > > +/* Get the subvolume information in BTRFS_ROOT_ITEM and > +BTRFS_ROOT_BACKREF */ static noinline int btrfs_ioctl_get_subvol_info(struct > file *file, > +void __user *argp) > +{ > + struct btrfs_ioctl_get_subvol_info_args *subvol_info; > + struct btrfs_fs_info *fs_info; > + struct btrfs_root *root; > + struct btrfs_path *path; > + struct btrfs_key key; > + > + struct btrfs_root_item *root_item; > + struct btrfs_root_ref *rref; > + struct extent_buffer *l; > + int slot; > + > + unsigned long item_off; > + unsigned long item_len; > + > + struct inode *inode; > + int ret = 0; > + > + path = btrfs_alloc_path(); > + if (!path) > + return -ENOMEM; > + > + subvol_info = kzalloc(sizeof(*subvol_info), GFP_KERNEL); > + if (!subvol_info) { > + btrfs_free_path(path); > + return -ENOMEM; > + } > + > + inode = file_inode(file); > + fs_info = BTRFS_I(inode)->root->fs_info; > + > + /* Get root_item of inode's subvolume */ > + key.objectid = BTRFS_I(inode)->root->root_key.objectid; > + key.type = BTRFS_ROOT_ITEM_KEY; > + key.offset = (u64)-1; > + root = btrfs_read_fs_root_no_name(fs_info, ); > + if (IS_ERR(root)) { > + ret = PTR_ERR(root); > + goto out; > + } > + root_item = >root_item; > + > + subvol_info->id = key.objectid; > + > + subvol_info->generation = btrfs_root_generation(root_item); > + subvol_info->flags = btrfs_root_flags(root_item); > + > + memcpy(subvol_info->uuid, root_item->uuid, BTRFS_UUID_SIZE); > + memcpy(subvol_info->parent_uuid, root_item->parent_uuid, > + BTRFS_UUID_SIZE); > + memcpy(subvol_info->received_uuid, root_item->received_uuid, > + BTRFS_UUID_SIZE); > + > + subvol_info->ctransid = btrfs_root_ctransid(root_item); > + subvol_info->ctime.sec = btrfs_stack_timespec_sec(_item->otime); > + subvol_info->ctime.nsec = > +btrfs_stack_timespec_nsec(_item->ctime); > + > + subvol_info->otransid = btrfs_root_otransid(root_item); > + subvol_info->otime.sec = btrfs_stack_timespec_sec(_item->otime); > + subvol_info->otime.nsec = > +btrfs_stack_timespec_nsec(_item->otime); > + > + subvol_info->stransid = btrfs_root_stransid(root_item); > + subvol_info->stime.sec = btrfs_stack_timespec_sec(_item->stime); > + subvol_info->stime.nsec = > +btrfs_stack_timespec_nsec(_item->stime); > + > + subvol_info->rtransid = btrfs_root_rtransid(root_item); > + subvol_info->rtime.sec = btrfs_stack_timespec_sec(_item->rtime); > + subvol_info->rtime.nsec = > +btrfs_stack_timespec_nsec(_item->rtime); > + > + if (key.objectid != BTRFS_FS_TREE_OBJECTID) { > + /* Search root tree for ROOT_BACKREF of this subvolume */ > + root = fs_info->tree_root; > + > + key.type = BTRFS_ROOT_BACKREF_KEY; > + key.offset = 0; > + ret = btrfs_search_slot(NULL, root, , path, 0, 0); > + if (ret < 0) { > + goto out; > + } else if (path->slots[0] >= > + btrfs_header_nritems(path->nodes[0])) { > + ret = btrfs_next_leaf(root, path); > + if (ret < 0) { > + goto out; > + } else if (ret > 0) { > + ret = -EUCLEAN; > + goto out; > + } > + } > + > + l = path->nodes[0]; > + slot = path->slots[0]; > +
Re: [PATCH v6 1/3] btrfs: Add unprivileged ioctl which returns subvolume information
On 2018/05/18 11:54, Tomohiro Misono wrote: > Add new unprivileged ioctl BTRFS_IOC_GET_SUBVOL_INFO which returns > the information of subvolume containing this inode. > (i.e. returns the information in ROOT_ITEM and ROOT_BACKREF.) > > Signed-off-by: Tomohiro Misono> --- > v5 -> v6 > - Use brfs_read_fs_root_no_name() to get subvolume root and simplify > code > v4 -> v5 > - Update error handling of btrfs_next_leaf() to cover all cases > - Return error if ROOT_BACKREF is not found (except top-level) > > fs/btrfs/ioctl.c | 125 > + > include/uapi/linux/btrfs.h | 51 ++ > 2 files changed, 176 insertions(+) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index 48e2ddff32bd..31af6e91c614 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -2242,6 +2242,129 @@ static noinline int btrfs_ioctl_ino_lookup(struct > file *file, > return ret; > } > > +/* Get the subvolume information in BTRFS_ROOT_ITEM and BTRFS_ROOT_BACKREF */ > +static noinline int btrfs_ioctl_get_subvol_info(struct file *file, > +void __user *argp) > +{ > + struct btrfs_ioctl_get_subvol_info_args *subvol_info; > + struct btrfs_fs_info *fs_info; > + struct btrfs_root *root; > + struct btrfs_path *path; > + struct btrfs_key key; > + > + struct btrfs_root_item *root_item; > + struct btrfs_root_ref *rref; > + struct extent_buffer *l; > + int slot; > + > + unsigned long item_off; > + unsigned long item_len; > + > + struct inode *inode; > + int ret = 0; > + > + path = btrfs_alloc_path(); > + if (!path) > + return -ENOMEM; > + > + subvol_info = kzalloc(sizeof(*subvol_info), GFP_KERNEL); > + if (!subvol_info) { > + btrfs_free_path(path); > + return -ENOMEM; > + } > + > + inode = file_inode(file); > + fs_info = BTRFS_I(inode)->root->fs_info; > + > + /* Get root_item of inode's subvolume */ > + key.objectid = BTRFS_I(inode)->root->root_key.objectid; > + key.type = BTRFS_ROOT_ITEM_KEY; > + key.offset = (u64)-1; > + root = btrfs_read_fs_root_no_name(fs_info, ); > + if (IS_ERR(root)) { > + ret = PTR_ERR(root); > + goto out; > + } > + root_item = >root_item; > + > + subvol_info->id = key.objectid; > + > + subvol_info->generation = btrfs_root_generation(root_item); > + subvol_info->flags = btrfs_root_flags(root_item); > + > + memcpy(subvol_info->uuid, root_item->uuid, BTRFS_UUID_SIZE); > + memcpy(subvol_info->parent_uuid, root_item->parent_uuid, > + BTRFS_UUID_SIZE); > + memcpy(subvol_info->received_uuid, root_item->received_uuid, > + BTRFS_UUID_SIZE); > + > + subvol_info->ctransid = btrfs_root_ctransid(root_item); > + subvol_info->ctime.sec = btrfs_stack_timespec_sec(_item->otime); obviously ->ctime, sorry for messed up. > + subvol_info->ctime.nsec = btrfs_stack_timespec_nsec(_item->ctime); > + > + subvol_info->otransid = btrfs_root_otransid(root_item); > + subvol_info->otime.sec = btrfs_stack_timespec_sec(_item->otime); > + subvol_info->otime.nsec = btrfs_stack_timespec_nsec(_item->otime); > + > + subvol_info->stransid = btrfs_root_stransid(root_item); > + subvol_info->stime.sec = btrfs_stack_timespec_sec(_item->stime); > + subvol_info->stime.nsec = btrfs_stack_timespec_nsec(_item->stime); > + > + subvol_info->rtransid = btrfs_root_rtransid(root_item); > + subvol_info->rtime.sec = btrfs_stack_timespec_sec(_item->rtime); > + subvol_info->rtime.nsec = btrfs_stack_timespec_nsec(_item->rtime); > + > + if (key.objectid != BTRFS_FS_TREE_OBJECTID) { > + /* Search root tree for ROOT_BACKREF of this subvolume */ > + root = fs_info->tree_root; > + > + key.type = BTRFS_ROOT_BACKREF_KEY; > + key.offset = 0; > + ret = btrfs_search_slot(NULL, root, , path, 0, 0); > + if (ret < 0) { > + goto out; > + } else if (path->slots[0] >= > + btrfs_header_nritems(path->nodes[0])) { > + ret = btrfs_next_leaf(root, path); > + if (ret < 0) { > + goto out; > + } else if (ret > 0) { > + ret = -EUCLEAN; > + goto out; > + } > + } > + > + l = path->nodes[0]; > + slot = path->slots[0]; > + btrfs_item_key_to_cpu(l, , slot); > + if (key.objectid == subvol_info->id && > + key.type == BTRFS_ROOT_BACKREF_KEY) { > +