Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Gerhard Heift and committed by
Chris Mason
cc68a8a5 ba346b35

+51
+41
fs/btrfs/ioctl.c
··· 2172 2172 return ret; 2173 2173 } 2174 2174 2175 + static 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 2215 * Search INODE_REFs to identify path name of 'dirid' directory 2177 2216 * in a 'tree_id' tree. and sets path name to 'name'. ··· 5291 5252 return btrfs_ioctl_trans_end(file); 5292 5253 case BTRFS_IOC_TREE_SEARCH: 5293 5254 return btrfs_ioctl_tree_search(file, argp); 5255 + case BTRFS_IOC_TREE_SEARCH_V2: 5256 + return btrfs_ioctl_tree_search_v2(file, argp); 5294 5257 case BTRFS_IOC_INO_LOOKUP: 5295 5258 return btrfs_ioctl_ino_lookup(file, argp); 5296 5259 case BTRFS_IOC_INO_PATHS:
+10
include/uapi/linux/btrfs.h
··· 306 306 char buf[BTRFS_SEARCH_ARGS_BUFSIZE]; 307 307 }; 308 308 309 + struct btrfs_ioctl_search_args_v2 { 310 + struct btrfs_ioctl_search_key key; /* in/out - search parameters */ 311 + __u64 buf_size; /* in - size of buffer 312 + * out - on EOVERFLOW: needed size 313 + * to store item */ 314 + __u64 buf[0]; /* out - found items */ 315 + }; 316 + 309 317 struct btrfs_ioctl_clone_range_args { 310 318 __s64 src_fd; 311 319 __u64 src_offset, src_length; ··· 566 558 struct btrfs_ioctl_defrag_range_args) 567 559 #define BTRFS_IOC_TREE_SEARCH _IOWR(BTRFS_IOCTL_MAGIC, 17, \ 568 560 struct btrfs_ioctl_search_args) 561 + #define BTRFS_IOC_TREE_SEARCH_V2 _IOWR(BTRFS_IOCTL_MAGIC, 17, \ 562 + struct btrfs_ioctl_search_args_v2) 569 563 #define BTRFS_IOC_INO_LOOKUP _IOWR(BTRFS_IOCTL_MAGIC, 18, \ 570 564 struct btrfs_ioctl_ino_lookup_args) 571 565 #define BTRFS_IOC_DEFAULT_SUBVOL _IOW(BTRFS_IOCTL_MAGIC, 19, __u64)