aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r--fs/btrfs/ioctl.c118
1 files changed, 108 insertions, 10 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 5fdb2abc4fa7..2616f7ed4799 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -40,6 +40,7 @@
40#include <linux/xattr.h> 40#include <linux/xattr.h>
41#include <linux/vmalloc.h> 41#include <linux/vmalloc.h>
42#include <linux/slab.h> 42#include <linux/slab.h>
43#include <linux/blkdev.h>
43#include "compat.h" 44#include "compat.h"
44#include "ctree.h" 45#include "ctree.h"
45#include "disk-io.h" 46#include "disk-io.h"
@@ -80,6 +81,13 @@ static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
80 iflags |= FS_NOATIME_FL; 81 iflags |= FS_NOATIME_FL;
81 if (flags & BTRFS_INODE_DIRSYNC) 82 if (flags & BTRFS_INODE_DIRSYNC)
82 iflags |= FS_DIRSYNC_FL; 83 iflags |= FS_DIRSYNC_FL;
84 if (flags & BTRFS_INODE_NODATACOW)
85 iflags |= FS_NOCOW_FL;
86
87 if ((flags & BTRFS_INODE_COMPRESS) && !(flags & BTRFS_INODE_NOCOMPRESS))
88 iflags |= FS_COMPR_FL;
89 else if (flags & BTRFS_INODE_NOCOMPRESS)
90 iflags |= FS_NOCOMP_FL;
83 91
84 return iflags; 92 return iflags;
85} 93}
@@ -138,6 +146,21 @@ static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
138 return 0; 146 return 0;
139} 147}
140 148
149static int check_flags(unsigned int flags)
150{
151 if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
152 FS_NOATIME_FL | FS_NODUMP_FL | \
153 FS_SYNC_FL | FS_DIRSYNC_FL | \
154 FS_NOCOMP_FL | FS_COMPR_FL |
155 FS_NOCOW_FL))
156 return -EOPNOTSUPP;
157
158 if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
159 return -EINVAL;
160
161 return 0;
162}
163
141static int btrfs_ioctl_setflags(struct file *file, void __user *arg) 164static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
142{ 165{
143 struct inode *inode = file->f_path.dentry->d_inode; 166 struct inode *inode = file->f_path.dentry->d_inode;
@@ -153,12 +176,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
153 if (copy_from_user(&flags, arg, sizeof(flags))) 176 if (copy_from_user(&flags, arg, sizeof(flags)))
154 return -EFAULT; 177 return -EFAULT;
155 178
156 if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ 179 ret = check_flags(flags);
157 FS_NOATIME_FL | FS_NODUMP_FL | \ 180 if (ret)
158 FS_SYNC_FL | FS_DIRSYNC_FL)) 181 return ret;
159 return -EOPNOTSUPP;
160 182
161 if (!is_owner_or_cap(inode)) 183 if (!inode_owner_or_capable(inode))
162 return -EACCES; 184 return -EACCES;
163 185
164 mutex_lock(&inode->i_mutex); 186 mutex_lock(&inode->i_mutex);
@@ -200,7 +222,25 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
200 ip->flags |= BTRFS_INODE_DIRSYNC; 222 ip->flags |= BTRFS_INODE_DIRSYNC;
201 else 223 else
202 ip->flags &= ~BTRFS_INODE_DIRSYNC; 224 ip->flags &= ~BTRFS_INODE_DIRSYNC;
225 if (flags & FS_NOCOW_FL)
226 ip->flags |= BTRFS_INODE_NODATACOW;
227 else
228 ip->flags &= ~BTRFS_INODE_NODATACOW;
203 229
230 /*
231 * The COMPRESS flag can only be changed by users, while the NOCOMPRESS
232 * flag may be changed automatically if compression code won't make
233 * things smaller.
234 */
235 if (flags & FS_NOCOMP_FL) {
236 ip->flags &= ~BTRFS_INODE_COMPRESS;
237 ip->flags |= BTRFS_INODE_NOCOMPRESS;
238 } else if (flags & FS_COMPR_FL) {
239 ip->flags |= BTRFS_INODE_COMPRESS;
240 ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
241 } else {
242 ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
243 }
204 244
205 trans = btrfs_join_transaction(root, 1); 245 trans = btrfs_join_transaction(root, 1);
206 BUG_ON(IS_ERR(trans)); 246 BUG_ON(IS_ERR(trans));
@@ -213,9 +253,11 @@ static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
213 btrfs_end_transaction(trans, root); 253 btrfs_end_transaction(trans, root);
214 254
215 mnt_drop_write(file->f_path.mnt); 255 mnt_drop_write(file->f_path.mnt);
256
257 ret = 0;
216 out_unlock: 258 out_unlock:
217 mutex_unlock(&inode->i_mutex); 259 mutex_unlock(&inode->i_mutex);
218 return 0; 260 return ret;
219} 261}
220 262
221static int btrfs_ioctl_getversion(struct file *file, int __user *arg) 263static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
@@ -225,6 +267,49 @@ static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
225 return put_user(inode->i_generation, arg); 267 return put_user(inode->i_generation, arg);
226} 268}
227 269
270static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
271{
272 struct btrfs_root *root = fdentry(file)->d_sb->s_fs_info;
273 struct btrfs_fs_info *fs_info = root->fs_info;
274 struct btrfs_device *device;
275 struct request_queue *q;
276 struct fstrim_range range;
277 u64 minlen = ULLONG_MAX;
278 u64 num_devices = 0;
279 int ret;
280
281 if (!capable(CAP_SYS_ADMIN))
282 return -EPERM;
283
284 mutex_lock(&fs_info->fs_devices->device_list_mutex);
285 list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) {
286 if (!device->bdev)
287 continue;
288 q = bdev_get_queue(device->bdev);
289 if (blk_queue_discard(q)) {
290 num_devices++;
291 minlen = min((u64)q->limits.discard_granularity,
292 minlen);
293 }
294 }
295 mutex_unlock(&fs_info->fs_devices->device_list_mutex);
296 if (!num_devices)
297 return -EOPNOTSUPP;
298
299 if (copy_from_user(&range, arg, sizeof(range)))
300 return -EFAULT;
301
302 range.minlen = max(range.minlen, minlen);
303 ret = btrfs_trim_fs(root, &range);
304 if (ret < 0)
305 return ret;
306
307 if (copy_to_user(arg, &range, sizeof(range)))
308 return -EFAULT;
309
310 return 0;
311}
312
228static noinline int create_subvol(struct btrfs_root *root, 313static noinline int create_subvol(struct btrfs_root *root,
229 struct dentry *dentry, 314 struct dentry *dentry,
230 char *name, int namelen, 315 char *name, int namelen,
@@ -294,6 +379,10 @@ static noinline int create_subvol(struct btrfs_root *root,
294 inode_item->nbytes = cpu_to_le64(root->leafsize); 379 inode_item->nbytes = cpu_to_le64(root->leafsize);
295 inode_item->mode = cpu_to_le32(S_IFDIR | 0755); 380 inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
296 381
382 root_item.flags = 0;
383 root_item.byte_limit = 0;
384 inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT);
385
297 btrfs_set_root_bytenr(&root_item, leaf->start); 386 btrfs_set_root_bytenr(&root_item, leaf->start);
298 btrfs_set_root_generation(&root_item, trans->transid); 387 btrfs_set_root_generation(&root_item, trans->transid);
299 btrfs_set_root_level(&root_item, 0); 388 btrfs_set_root_level(&root_item, 0);
@@ -409,7 +498,9 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
409 if (ret) 498 if (ret)
410 goto fail; 499 goto fail;
411 500
412 btrfs_orphan_cleanup(pending_snapshot->snap); 501 ret = btrfs_orphan_cleanup(pending_snapshot->snap);
502 if (ret)
503 goto fail;
413 504
414 parent = dget_parent(dentry); 505 parent = dget_parent(dentry);
415 inode = btrfs_lookup_dentry(parent->d_inode, dentry); 506 inode = btrfs_lookup_dentry(parent->d_inode, dentry);
@@ -1077,7 +1168,7 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
1077 if (flags & ~BTRFS_SUBVOL_RDONLY) 1168 if (flags & ~BTRFS_SUBVOL_RDONLY)
1078 return -EOPNOTSUPP; 1169 return -EOPNOTSUPP;
1079 1170
1080 if (!is_owner_or_cap(inode)) 1171 if (!inode_owner_or_capable(inode))
1081 return -EACCES; 1172 return -EACCES;
1082 1173
1083 down_write(&root->fs_info->subvol_sem); 1174 down_write(&root->fs_info->subvol_sem);
@@ -2202,7 +2293,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
2202 struct btrfs_ioctl_space_info space; 2293 struct btrfs_ioctl_space_info space;
2203 struct btrfs_ioctl_space_info *dest; 2294 struct btrfs_ioctl_space_info *dest;
2204 struct btrfs_ioctl_space_info *dest_orig; 2295 struct btrfs_ioctl_space_info *dest_orig;
2205 struct btrfs_ioctl_space_info *user_dest; 2296 struct btrfs_ioctl_space_info __user *user_dest;
2206 struct btrfs_space_info *info; 2297 struct btrfs_space_info *info;
2207 u64 types[] = {BTRFS_BLOCK_GROUP_DATA, 2298 u64 types[] = {BTRFS_BLOCK_GROUP_DATA,
2208 BTRFS_BLOCK_GROUP_SYSTEM, 2299 BTRFS_BLOCK_GROUP_SYSTEM,
@@ -2348,12 +2439,17 @@ static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp
2348 struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root; 2439 struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;
2349 struct btrfs_trans_handle *trans; 2440 struct btrfs_trans_handle *trans;
2350 u64 transid; 2441 u64 transid;
2442 int ret;
2351 2443
2352 trans = btrfs_start_transaction(root, 0); 2444 trans = btrfs_start_transaction(root, 0);
2353 if (IS_ERR(trans)) 2445 if (IS_ERR(trans))
2354 return PTR_ERR(trans); 2446 return PTR_ERR(trans);
2355 transid = trans->transid; 2447 transid = trans->transid;
2356 btrfs_commit_transaction_async(trans, root, 0); 2448 ret = btrfs_commit_transaction_async(trans, root, 0);
2449 if (ret) {
2450 btrfs_end_transaction(trans, root);
2451 return ret;
2452 }
2357 2453
2358 if (argp) 2454 if (argp)
2359 if (copy_to_user(argp, &transid, sizeof(transid))) 2455 if (copy_to_user(argp, &transid, sizeof(transid)))
@@ -2388,6 +2484,8 @@ long btrfs_ioctl(struct file *file, unsigned int
2388 return btrfs_ioctl_setflags(file, argp); 2484 return btrfs_ioctl_setflags(file, argp);
2389 case FS_IOC_GETVERSION: 2485 case FS_IOC_GETVERSION:
2390 return btrfs_ioctl_getversion(file, argp); 2486 return btrfs_ioctl_getversion(file, argp);
2487 case FITRIM:
2488 return btrfs_ioctl_fitrim(file, argp);
2391 case BTRFS_IOC_SNAP_CREATE: 2489 case BTRFS_IOC_SNAP_CREATE:
2392 return btrfs_ioctl_snap_create(file, argp, 0); 2490 return btrfs_ioctl_snap_create(file, argp, 0);
2393 case BTRFS_IOC_SNAP_CREATE_V2: 2491 case BTRFS_IOC_SNAP_CREATE_V2: