Skip to content

Commit

Permalink
btrfs: new ioctl TREE_SEARCH_V2
Browse files Browse the repository at this point in the history
This new ioctl call allows the user to supply a buffer of varying size in which
a tree search can store its results. This is much more flexible if you want to
receive items which are larger than the current fixed buffer of 3992 bytes or
if you want to fetch more items at once. Items larger than this buffer are for
example some of the type EXTENT_CSUM.

Signed-off-by: Gerhard Heift <[email protected]>
Signed-off-by: Chris Mason <[email protected]>
Acked-by: David Sterba <[email protected]>
  • Loading branch information
gheift authored and masoncl committed Jun 13, 2014
1 parent ba346b3 commit cc68a8a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
41 changes: 41 additions & 0 deletions fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2172,6 +2172,45 @@ static noinline int btrfs_ioctl_tree_search(struct file *file,
return ret;
}

static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
void __user *argp)
{
struct btrfs_ioctl_search_args_v2 __user *uarg;
struct btrfs_ioctl_search_args_v2 args;
struct inode *inode;
int ret;
size_t buf_size;
const size_t buf_limit = 16 * 1024 * 1024;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

/* copy search header and buffer size */
uarg = (struct btrfs_ioctl_search_args_v2 __user *)argp;
if (copy_from_user(&args, uarg, sizeof(args)))
return -EFAULT;

buf_size = args.buf_size;

if (buf_size < sizeof(struct btrfs_ioctl_search_header))
return -EOVERFLOW;

/* limit result size to 16MB */
if (buf_size > buf_limit)
buf_size = buf_limit;

inode = file_inode(file);
ret = search_ioctl(inode, &args.key, &buf_size,
(char *)(&uarg->buf[0]));
if (ret == 0 && copy_to_user(&uarg->key, &args.key, sizeof(args.key)))
ret = -EFAULT;
else if (ret == -EOVERFLOW &&
copy_to_user(&uarg->buf_size, &buf_size, sizeof(buf_size)))
ret = -EFAULT;

return ret;
}

/*
* Search INODE_REFs to identify path name of 'dirid' directory
* in a 'tree_id' tree. and sets path name to 'name'.
Expand Down Expand Up @@ -5252,6 +5291,8 @@ long btrfs_ioctl(struct file *file, unsigned int
return btrfs_ioctl_trans_end(file);
case BTRFS_IOC_TREE_SEARCH:
return btrfs_ioctl_tree_search(file, argp);
case BTRFS_IOC_TREE_SEARCH_V2:
return btrfs_ioctl_tree_search_v2(file, argp);
case BTRFS_IOC_INO_LOOKUP:
return btrfs_ioctl_ino_lookup(file, argp);
case BTRFS_IOC_INO_PATHS:
Expand Down
10 changes: 10 additions & 0 deletions include/uapi/linux/btrfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,14 @@ struct btrfs_ioctl_search_args {
char buf[BTRFS_SEARCH_ARGS_BUFSIZE];
};

struct btrfs_ioctl_search_args_v2 {
struct btrfs_ioctl_search_key key; /* in/out - search parameters */
__u64 buf_size; /* in - size of buffer
* out - on EOVERFLOW: needed size
* to store item */
__u64 buf[0]; /* out - found items */
};

struct btrfs_ioctl_clone_range_args {
__s64 src_fd;
__u64 src_offset, src_length;
Expand Down Expand Up @@ -558,6 +566,8 @@ static inline char *btrfs_err_str(enum btrfs_err_code err_code)
struct btrfs_ioctl_defrag_range_args)
#define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \
struct btrfs_ioctl_search_args)
#define BTRFS_IOC_TREE_SEARCH_V2 _IOWR(BTRFS_IOCTL_MAGIC, 17, \
struct btrfs_ioctl_search_args_v2)
#define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \
struct btrfs_ioctl_ino_lookup_args)
#define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64)
Expand Down

0 comments on commit cc68a8a

Please sign in to comment.