aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorGerhard Heift <gerhard@heift.name>2014-01-30 10:24:03 -0500
committerChris Mason <clm@fb.com>2014-06-13 12:52:19 -0400
commitcc68a8a5a4330a4bb72922d0c7a7044ae13ee692 (patch)
tree8b5b09704b99bb0956836c8d45b6228cfcc2bfee /fs
parentba346b357d70becdd8e20ff9493cd56101ee0f46 (diff)
btrfs: new ioctl TREE_SEARCH_V2
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 <Gerhard@Heift.Name> Signed-off-by: Chris Mason <clm@fb.com> Acked-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ioctl.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 393a543a519e..6ea15469c63f 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2172,6 +2172,45 @@ static noinline int btrfs_ioctl_tree_search(struct file *file,
2172 return ret; 2172 return ret;
2173} 2173}
2174 2174
2175static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
2176 void __user *argp)
2177{
2178 struct btrfs_ioctl_search_args_v2 __user *uarg;
2179 struct btrfs_ioctl_search_args_v2 args;
2180 struct inode *inode;
2181 int ret;
2182 size_t buf_size;
2183 const size_t buf_limit = 16 * 1024 * 1024;
2184
2185 if (!capable(CAP_SYS_ADMIN))
2186 return -EPERM;
2187
2188 /* copy search header and buffer size */
2189 uarg = (struct btrfs_ioctl_search_args_v2 __user *)argp;
2190 if (copy_from_user(&args, uarg, sizeof(args)))
2191 return -EFAULT;
2192
2193 buf_size = args.buf_size;
2194
2195 if (buf_size < sizeof(struct btrfs_ioctl_search_header))
2196 return -EOVERFLOW;
2197
2198 /* limit result size to 16MB */
2199 if (buf_size > buf_limit)
2200 buf_size = buf_limit;
2201
2202 inode = file_inode(file);
2203 ret = search_ioctl(inode, &args.key, &buf_size,
2204 (char *)(&uarg->buf[0]));
2205 if (ret == 0 && copy_to_user(&uarg->key, &args.key, sizeof(args.key)))
2206 ret = -EFAULT;
2207 else if (ret == -EOVERFLOW &&
2208 copy_to_user(&uarg->buf_size, &buf_size, sizeof(buf_size)))
2209 ret = -EFAULT;
2210
2211 return ret;
2212}
2213
2175/* 2214/*
2176 * Search INODE_REFs to identify path name of 'dirid' directory 2215 * Search INODE_REFs to identify path name of 'dirid' directory
2177 * in a 'tree_id' tree. and sets path name to 'name'. 2216 * in a 'tree_id' tree. and sets path name to 'name'.
@@ -5252,6 +5291,8 @@ long btrfs_ioctl(struct file *file, unsigned int
5252 return btrfs_ioctl_trans_end(file); 5291 return btrfs_ioctl_trans_end(file);
5253 case BTRFS_IOC_TREE_SEARCH: 5292 case BTRFS_IOC_TREE_SEARCH:
5254 return btrfs_ioctl_tree_search(file, argp); 5293 return btrfs_ioctl_tree_search(file, argp);
5294 case BTRFS_IOC_TREE_SEARCH_V2:
5295 return btrfs_ioctl_tree_search_v2(file, argp);
5255 case BTRFS_IOC_INO_LOOKUP: 5296 case BTRFS_IOC_INO_LOOKUP:
5256 return btrfs_ioctl_ino_lookup(file, argp); 5297 return btrfs_ioctl_ino_lookup(file, argp);
5257 case BTRFS_IOC_INO_PATHS: 5298 case BTRFS_IOC_INO_PATHS: