Blame view

fs/btrfs/ioctl.c 118 KB
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   * Copyright (C) 2007 Oracle.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License v2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
  
  #include <linux/kernel.h>
  #include <linux/bio.h>
  #include <linux/buffer_head.h>
  #include <linux/file.h>
  #include <linux/fs.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
24
  #include <linux/fsnotify.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
25
26
27
28
29
  #include <linux/pagemap.h>
  #include <linux/highmem.h>
  #include <linux/time.h>
  #include <linux/init.h>
  #include <linux/string.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
30
  #include <linux/backing-dev.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
31
  #include <linux/mount.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
32
  #include <linux/mpage.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
33
  #include <linux/namei.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
34
35
36
37
38
  #include <linux/swap.h>
  #include <linux/writeback.h>
  #include <linux/statfs.h>
  #include <linux/compat.h>
  #include <linux/bit_spinlock.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
39
  #include <linux/security.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
40
  #include <linux/xattr.h>
7ea394f11   Yan Zheng   Btrfs: Fix nodata...
41
  #include <linux/vmalloc.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
42
  #include <linux/slab.h>
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
43
  #include <linux/blkdev.h>
8ea05e3a4   Alexander Block   Btrfs: introduce ...
44
  #include <linux/uuid.h>
55e301fd5   Filipe Brandenburger   Btrfs: move fs/bt...
45
  #include <linux/btrfs.h>
416161db9   Mark Fasheh   btrfs: offline de...
46
  #include <linux/uaccess.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
47
48
49
50
  #include "ctree.h"
  #include "disk-io.h"
  #include "transaction.h"
  #include "btrfs_inode.h"
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
51
52
  #include "print-tree.h"
  #include "volumes.h"
925baeddc   Chris Mason   Btrfs: Start btre...
53
  #include "locking.h"
581bb0509   Li Zefan   Btrfs: Cache free...
54
  #include "inode-map.h"
d7728c960   Jan Schmidt   btrfs: new ioctls...
55
  #include "backref.h"
606686eea   Josef Bacik   Btrfs: use rcu to...
56
  #include "rcu-string.h"
31db9f7c2   Alexander Block   Btrfs: introduce ...
57
  #include "send.h"
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
58
  #include "dev-replace.h"
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
59
  #include "props.h"
3b02a68a6   Jeff Mahoney   btrfs: use featur...
60
  #include "sysfs.h"
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
61

abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  #ifdef CONFIG_64BIT
  /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI
   * structures are incorrect, as the timespec structure from userspace
   * is 4 bytes too small. We define these alternatives here to teach
   * the kernel about the 32-bit struct packing.
   */
  struct btrfs_ioctl_timespec_32 {
  	__u64 sec;
  	__u32 nsec;
  } __attribute__ ((__packed__));
  
  struct btrfs_ioctl_received_subvol_args_32 {
  	char	uuid[BTRFS_UUID_SIZE];	/* in */
  	__u64	stransid;		/* in */
  	__u64	rtransid;		/* out */
  	struct btrfs_ioctl_timespec_32 stime; /* in */
  	struct btrfs_ioctl_timespec_32 rtime; /* out */
  	__u64	flags;			/* in */
  	__u64	reserved[16];		/* in */
  } __attribute__ ((__packed__));
  
  #define BTRFS_IOC_SET_RECEIVED_SUBVOL_32 _IOWR(BTRFS_IOCTL_MAGIC, 37, \
  				struct btrfs_ioctl_received_subvol_args_32)
  #endif
416161db9   Mark Fasheh   btrfs: offline de...
86
87
  static int btrfs_clone(struct inode *src, struct inode *inode,
  		       u64 off, u64 olen, u64 olen_aligned, u64 destoff);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  /* Mask out flags that are inappropriate for the given type of inode. */
  static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags)
  {
  	if (S_ISDIR(mode))
  		return flags;
  	else if (S_ISREG(mode))
  		return flags & ~FS_DIRSYNC_FL;
  	else
  		return flags & (FS_NODUMP_FL | FS_NOATIME_FL);
  }
  
  /*
   * Export inode flags to the format expected by the FS_IOC_GETFLAGS ioctl.
   */
  static unsigned int btrfs_flags_to_ioctl(unsigned int flags)
  {
  	unsigned int iflags = 0;
  
  	if (flags & BTRFS_INODE_SYNC)
  		iflags |= FS_SYNC_FL;
  	if (flags & BTRFS_INODE_IMMUTABLE)
  		iflags |= FS_IMMUTABLE_FL;
  	if (flags & BTRFS_INODE_APPEND)
  		iflags |= FS_APPEND_FL;
  	if (flags & BTRFS_INODE_NODUMP)
  		iflags |= FS_NODUMP_FL;
  	if (flags & BTRFS_INODE_NOATIME)
  		iflags |= FS_NOATIME_FL;
  	if (flags & BTRFS_INODE_DIRSYNC)
  		iflags |= FS_DIRSYNC_FL;
d0092bdda   Li Zefan   Btrfs: fix FS_IOC...
118
119
120
121
122
123
124
  	if (flags & BTRFS_INODE_NODATACOW)
  		iflags |= FS_NOCOW_FL;
  
  	if ((flags & BTRFS_INODE_COMPRESS) && !(flags & BTRFS_INODE_NOCOMPRESS))
  		iflags |= FS_COMPR_FL;
  	else if (flags & BTRFS_INODE_NOCOMPRESS)
  		iflags |= FS_NOCOMP_FL;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  
  	return iflags;
  }
  
  /*
   * Update inode->i_flags based on the btrfs internal flags.
   */
  void btrfs_update_iflags(struct inode *inode)
  {
  	struct btrfs_inode *ip = BTRFS_I(inode);
  
  	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
  
  	if (ip->flags & BTRFS_INODE_SYNC)
  		inode->i_flags |= S_SYNC;
  	if (ip->flags & BTRFS_INODE_IMMUTABLE)
  		inode->i_flags |= S_IMMUTABLE;
  	if (ip->flags & BTRFS_INODE_APPEND)
  		inode->i_flags |= S_APPEND;
  	if (ip->flags & BTRFS_INODE_NOATIME)
  		inode->i_flags |= S_NOATIME;
  	if (ip->flags & BTRFS_INODE_DIRSYNC)
  		inode->i_flags |= S_DIRSYNC;
  }
  
  /*
   * Inherit flags from the parent inode.
   *
e27425d61   Josef Bacik   Btrfs: only inher...
153
   * Currently only the compression flags and the cow flags are inherited.
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
154
155
156
   */
  void btrfs_inherit_iflags(struct inode *inode, struct inode *dir)
  {
0b4dcea57   Chris Mason   Btrfs: fix oops w...
157
158
159
160
161
162
  	unsigned int flags;
  
  	if (!dir)
  		return;
  
  	flags = BTRFS_I(dir)->flags;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
163

e27425d61   Josef Bacik   Btrfs: only inher...
164
165
166
167
168
169
170
  	if (flags & BTRFS_INODE_NOCOMPRESS) {
  		BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS;
  		BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
  	} else if (flags & BTRFS_INODE_COMPRESS) {
  		BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
  		BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
  	}
213490b30   Liu Bo   Btrfs: fix a bug ...
171
  	if (flags & BTRFS_INODE_NODATACOW) {
e27425d61   Josef Bacik   Btrfs: only inher...
172
  		BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
213490b30   Liu Bo   Btrfs: fix a bug ...
173
174
175
  		if (S_ISREG(inode->i_mode))
  			BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
176

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
177
178
179
180
181
  	btrfs_update_iflags(inode);
  }
  
  static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
182
  	struct btrfs_inode *ip = BTRFS_I(file_inode(file));
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
183
184
185
186
187
188
  	unsigned int flags = btrfs_flags_to_ioctl(ip->flags);
  
  	if (copy_to_user(arg, &flags, sizeof(flags)))
  		return -EFAULT;
  	return 0;
  }
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
189
190
191
192
193
  static int check_flags(unsigned int flags)
  {
  	if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \
  		      FS_NOATIME_FL | FS_NODUMP_FL | \
  		      FS_SYNC_FL | FS_DIRSYNC_FL | \
e1e8fb6a1   Li Zefan   fs: remove FS_COW_FL
194
195
  		      FS_NOCOMP_FL | FS_COMPR_FL |
  		      FS_NOCOW_FL))
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
196
197
198
199
  		return -EOPNOTSUPP;
  
  	if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
  		return -EINVAL;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
200
201
  	return 0;
  }
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
202
203
  static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
204
  	struct inode *inode = file_inode(file);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
205
206
207
208
209
  	struct btrfs_inode *ip = BTRFS_I(inode);
  	struct btrfs_root *root = ip->root;
  	struct btrfs_trans_handle *trans;
  	unsigned int flags, oldflags;
  	int ret;
f062abf08   Li Zefan   Btrfs: remove BUG...
210
211
  	u64 ip_oldflags;
  	unsigned int i_oldflags;
7e97b8daf   David Sterba   btrfs: allow sett...
212
  	umode_t mode;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
213

bd60ea0fe   David Sterba   btrfs: call permi...
214
215
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
b83cc9693   Li Zefan   Btrfs: Add readon...
216
217
  	if (btrfs_root_readonly(root))
  		return -EROFS;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
218
219
  	if (copy_from_user(&flags, arg, sizeof(flags)))
  		return -EFAULT;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
220
221
222
  	ret = check_flags(flags);
  	if (ret)
  		return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
223

e7848683a   Jan Kara   btrfs: Push mnt_w...
224
225
226
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
227
  	mutex_lock(&inode->i_mutex);
f062abf08   Li Zefan   Btrfs: remove BUG...
228
229
  	ip_oldflags = ip->flags;
  	i_oldflags = inode->i_flags;
7e97b8daf   David Sterba   btrfs: allow sett...
230
  	mode = inode->i_mode;
f062abf08   Li Zefan   Btrfs: remove BUG...
231

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
232
233
234
235
236
237
238
239
  	flags = btrfs_mask_flags(inode->i_mode, flags);
  	oldflags = btrfs_flags_to_ioctl(ip->flags);
  	if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) {
  		if (!capable(CAP_LINUX_IMMUTABLE)) {
  			ret = -EPERM;
  			goto out_unlock;
  		}
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  	if (flags & FS_SYNC_FL)
  		ip->flags |= BTRFS_INODE_SYNC;
  	else
  		ip->flags &= ~BTRFS_INODE_SYNC;
  	if (flags & FS_IMMUTABLE_FL)
  		ip->flags |= BTRFS_INODE_IMMUTABLE;
  	else
  		ip->flags &= ~BTRFS_INODE_IMMUTABLE;
  	if (flags & FS_APPEND_FL)
  		ip->flags |= BTRFS_INODE_APPEND;
  	else
  		ip->flags &= ~BTRFS_INODE_APPEND;
  	if (flags & FS_NODUMP_FL)
  		ip->flags |= BTRFS_INODE_NODUMP;
  	else
  		ip->flags &= ~BTRFS_INODE_NODUMP;
  	if (flags & FS_NOATIME_FL)
  		ip->flags |= BTRFS_INODE_NOATIME;
  	else
  		ip->flags &= ~BTRFS_INODE_NOATIME;
  	if (flags & FS_DIRSYNC_FL)
  		ip->flags |= BTRFS_INODE_DIRSYNC;
  	else
  		ip->flags &= ~BTRFS_INODE_DIRSYNC;
7e97b8daf   David Sterba   btrfs: allow sett...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
  	if (flags & FS_NOCOW_FL) {
  		if (S_ISREG(mode)) {
  			/*
  			 * It's safe to turn csums off here, no extents exist.
  			 * Otherwise we want the flag to reflect the real COW
  			 * status of the file and will not set it.
  			 */
  			if (inode->i_size == 0)
  				ip->flags |= BTRFS_INODE_NODATACOW
  					   | BTRFS_INODE_NODATASUM;
  		} else {
  			ip->flags |= BTRFS_INODE_NODATACOW;
  		}
  	} else {
  		/*
  		 * Revert back under same assuptions as above
  		 */
  		if (S_ISREG(mode)) {
  			if (inode->i_size == 0)
  				ip->flags &= ~(BTRFS_INODE_NODATACOW
  				             | BTRFS_INODE_NODATASUM);
  		} else {
  			ip->flags &= ~BTRFS_INODE_NODATACOW;
  		}
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
289

75e7cb7fe   Liu Bo   Btrfs: Per file/d...
290
291
292
293
294
295
296
297
  	/*
  	 * The COMPRESS flag can only be changed by users, while the NOCOMPRESS
  	 * flag may be changed automatically if compression code won't make
  	 * things smaller.
  	 */
  	if (flags & FS_NOCOMP_FL) {
  		ip->flags &= ~BTRFS_INODE_COMPRESS;
  		ip->flags |= BTRFS_INODE_NOCOMPRESS;
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
298
299
300
301
  
  		ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0);
  		if (ret && ret != -ENODATA)
  			goto out_drop;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
302
  	} else if (flags & FS_COMPR_FL) {
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
303
  		const char *comp;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
304
305
  		ip->flags |= BTRFS_INODE_COMPRESS;
  		ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
306
307
308
309
310
311
312
313
314
  
  		if (root->fs_info->compress_type == BTRFS_COMPRESS_LZO)
  			comp = "lzo";
  		else
  			comp = "zlib";
  		ret = btrfs_set_prop(inode, "btrfs.compression",
  				     comp, strlen(comp), 0);
  		if (ret)
  			goto out_drop;
ebcb904df   Li Zefan   Btrfs: fix FS_IOC...
315
316
  	} else {
  		ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
317
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
318

4da6f1a33   Li Zefan   Btrfs: reserve me...
319
  	trans = btrfs_start_transaction(root, 1);
f062abf08   Li Zefan   Btrfs: remove BUG...
320
321
322
323
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_drop;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
324

306424cc8   Li Zefan   Btrfs: fix ctime ...
325
  	btrfs_update_iflags(inode);
0c4d2d95d   Josef Bacik   Btrfs: use i_vers...
326
  	inode_inc_iversion(inode);
306424cc8   Li Zefan   Btrfs: fix ctime ...
327
  	inode->i_ctime = CURRENT_TIME;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
328
  	ret = btrfs_update_inode(trans, root, inode);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
329

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
330
  	btrfs_end_transaction(trans, root);
f062abf08   Li Zefan   Btrfs: remove BUG...
331
332
333
334
335
   out_drop:
  	if (ret) {
  		ip->flags = ip_oldflags;
  		inode->i_flags = i_oldflags;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
336

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
337
338
   out_unlock:
  	mutex_unlock(&inode->i_mutex);
e7848683a   Jan Kara   btrfs: Push mnt_w...
339
  	mnt_drop_write_file(file);
2d4e6f6ad   liubo   Btrfs: fix return...
340
  	return ret;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
341
342
343
344
  }
  
  static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
345
  	struct inode *inode = file_inode(file);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
346
347
348
  
  	return put_user(inode->i_generation, arg);
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
349

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
350
351
  static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
  {
54563d41a   Al Viro   btrfs: get rid of...
352
  	struct btrfs_fs_info *fs_info = btrfs_sb(file_inode(file)->i_sb);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
353
354
355
356
357
  	struct btrfs_device *device;
  	struct request_queue *q;
  	struct fstrim_range range;
  	u64 minlen = ULLONG_MAX;
  	u64 num_devices = 0;
815745cf3   Al Viro   btrfs: let ->s_fs...
358
  	u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
359
360
361
362
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
1f78160ce   Xiao Guangrong   Btrfs: using rcu ...
363
364
365
  	rcu_read_lock();
  	list_for_each_entry_rcu(device, &fs_info->fs_devices->devices,
  				dev_list) {
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
366
367
368
369
370
371
372
373
374
  		if (!device->bdev)
  			continue;
  		q = bdev_get_queue(device->bdev);
  		if (blk_queue_discard(q)) {
  			num_devices++;
  			minlen = min((u64)q->limits.discard_granularity,
  				     minlen);
  		}
  	}
1f78160ce   Xiao Guangrong   Btrfs: using rcu ...
375
  	rcu_read_unlock();
f4c697e64   Lukas Czerner   btrfs: return EIN...
376

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
377
378
  	if (!num_devices)
  		return -EOPNOTSUPP;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
379
380
  	if (copy_from_user(&range, arg, sizeof(range)))
  		return -EFAULT;
e515c18bf   Lukas Czerner   btrfs: Return EIN...
381
382
  	if (range.start > total_bytes ||
  	    range.len < fs_info->sb->s_blocksize)
f4c697e64   Lukas Czerner   btrfs: return EIN...
383
  		return -EINVAL;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
384

f4c697e64   Lukas Czerner   btrfs: return EIN...
385
  	range.len = min(range.len, total_bytes - range.start);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
386
  	range.minlen = max(range.minlen, minlen);
815745cf3   Al Viro   btrfs: let ->s_fs...
387
  	ret = btrfs_trim_fs(fs_info->tree_root, &range);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
388
389
390
391
392
393
394
395
  	if (ret < 0)
  		return ret;
  
  	if (copy_to_user(arg, &range, sizeof(range)))
  		return -EFAULT;
  
  	return 0;
  }
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
396
397
  int btrfs_is_empty_uuid(u8 *uuid)
  {
46e0f66a0   Chris Mason   btrfs: fix empty_...
398
399
400
401
402
403
404
  	int i;
  
  	for (i = 0; i < BTRFS_UUID_SIZE; i++) {
  		if (uuid[i])
  			return 0;
  	}
  	return 1;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
405
  }
d5c120701   Miao Xie   Btrfs: fix wrong ...
406
  static noinline int create_subvol(struct inode *dir,
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
407
  				  struct dentry *dentry,
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
408
  				  char *name, int namelen,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
409
  				  u64 *async_transid,
8696c5330   Miao Xie   Btrfs: fix memory...
410
  				  struct btrfs_qgroup_inherit *inherit)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
411
412
413
414
415
416
  {
  	struct btrfs_trans_handle *trans;
  	struct btrfs_key key;
  	struct btrfs_root_item root_item;
  	struct btrfs_inode_item *inode_item;
  	struct extent_buffer *leaf;
d5c120701   Miao Xie   Btrfs: fix wrong ...
417
  	struct btrfs_root *root = BTRFS_I(dir)->root;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
418
  	struct btrfs_root *new_root;
d5c120701   Miao Xie   Btrfs: fix wrong ...
419
  	struct btrfs_block_rsv block_rsv;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
420
  	struct timespec cur_time = CURRENT_TIME;
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
421
  	struct inode *inode;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
422
423
424
425
  	int ret;
  	int err;
  	u64 objectid;
  	u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
3de4586c5   Chris Mason   Btrfs: Allow subv...
426
  	u64 index = 0;
d5c120701   Miao Xie   Btrfs: fix wrong ...
427
  	u64 qgroup_reserved;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
428
  	uuid_le new_uuid;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
429

581bb0509   Li Zefan   Btrfs: Cache free...
430
  	ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
2fbe8c8ad   Al Viro   get rid of useles...
431
  	if (ret)
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
432
  		return ret;
6a9122130   Josef Bacik   Btrfs: use dget_p...
433

d5c120701   Miao Xie   Btrfs: fix wrong ...
434
  	btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
9ed74f2db   Josef Bacik   Btrfs: proper -EN...
435
  	/*
d5c120701   Miao Xie   Btrfs: fix wrong ...
436
437
  	 * The same as the snapshot creation, please see the comment
  	 * of create_snapshot().
9ed74f2db   Josef Bacik   Btrfs: proper -EN...
438
  	 */
d5c120701   Miao Xie   Btrfs: fix wrong ...
439
  	ret = btrfs_subvolume_reserve_metadata(root, &block_rsv,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
440
  					       8, &qgroup_reserved, false);
d5c120701   Miao Xie   Btrfs: fix wrong ...
441
442
443
444
445
446
  	if (ret)
  		return ret;
  
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
de6e82006   Liu Bo   Btrfs: release su...
447
448
449
  		btrfs_subvolume_release_metadata(root, &block_rsv,
  						 qgroup_reserved);
  		return ret;
d5c120701   Miao Xie   Btrfs: fix wrong ...
450
451
452
  	}
  	trans->block_rsv = &block_rsv;
  	trans->bytes_reserved = block_rsv.size;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
453

8696c5330   Miao Xie   Btrfs: fix memory...
454
  	ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, inherit);
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
455
456
  	if (ret)
  		goto fail;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
457
  	leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
5581a51a5   Jan Schmidt   Btrfs: don't set ...
458
  				      0, objectid, NULL, 0, 0, 0);
8e8a1e31f   Josef Bacik   Btrfs: Fix a few ...
459
460
461
462
  	if (IS_ERR(leaf)) {
  		ret = PTR_ERR(leaf);
  		goto fail;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
463

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
464
  	memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header));
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
465
466
  	btrfs_set_header_bytenr(leaf, leaf->start);
  	btrfs_set_header_generation(leaf, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
467
  	btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
468
  	btrfs_set_header_owner(leaf, objectid);
0a4e55860   Ross Kirk   btrfs: remove unu...
469
  	write_extent_buffer(leaf, root->fs_info->fsid, btrfs_header_fsid(),
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
470
  			    BTRFS_FSID_SIZE);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
471
  	write_extent_buffer(leaf, root->fs_info->chunk_tree_uuid,
b308bc2f0   Geert Uytterhoeven   Btrfs: Make btrfs...
472
  			    btrfs_header_chunk_tree_uuid(leaf),
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
473
  			    BTRFS_UUID_SIZE);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
474
  	btrfs_mark_buffer_dirty(leaf);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
475
  	memset(&root_item, 0, sizeof(root_item));
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
476
  	inode_item = &root_item.inode;
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
477
478
479
480
481
  	btrfs_set_stack_inode_generation(inode_item, 1);
  	btrfs_set_stack_inode_size(inode_item, 3);
  	btrfs_set_stack_inode_nlink(inode_item, 1);
  	btrfs_set_stack_inode_nbytes(inode_item, root->leafsize);
  	btrfs_set_stack_inode_mode(inode_item, S_IFDIR | 0755);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
482

3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
483
484
485
  	btrfs_set_root_flags(&root_item, 0);
  	btrfs_set_root_limit(&root_item, 0);
  	btrfs_set_stack_inode_flags(inode_item, BTRFS_INODE_ROOT_ITEM_INIT);
08fe4db17   Li Zefan   Btrfs: Fix uninit...
486

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
487
  	btrfs_set_root_bytenr(&root_item, leaf->start);
84234f3a1   Yan Zheng   Btrfs: Add root t...
488
  	btrfs_set_root_generation(&root_item, trans->transid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
489
490
  	btrfs_set_root_level(&root_item, 0);
  	btrfs_set_root_refs(&root_item, 1);
86b9f2eca   Yan, Zheng   Btrfs: Fix per ro...
491
  	btrfs_set_root_used(&root_item, leaf->len);
80ff38566   Yan Zheng   Btrfs: update nod...
492
  	btrfs_set_root_last_snapshot(&root_item, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
493

8ea05e3a4   Alexander Block   Btrfs: introduce ...
494
495
496
497
  	btrfs_set_root_generation_v2(&root_item,
  			btrfs_root_generation(&root_item));
  	uuid_le_gen(&new_uuid);
  	memcpy(root_item.uuid, new_uuid.b, BTRFS_UUID_SIZE);
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
498
499
  	btrfs_set_stack_timespec_sec(&root_item.otime, cur_time.tv_sec);
  	btrfs_set_stack_timespec_nsec(&root_item.otime, cur_time.tv_nsec);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
500
501
502
  	root_item.ctime = root_item.otime;
  	btrfs_set_root_ctransid(&root_item, trans->transid);
  	btrfs_set_root_otransid(&root_item, trans->transid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
503

925baeddc   Chris Mason   Btrfs: Start btre...
504
  	btrfs_tree_unlock(leaf);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
505
506
507
508
509
510
  	free_extent_buffer(leaf);
  	leaf = NULL;
  
  	btrfs_set_root_dirid(&root_item, new_dirid);
  
  	key.objectid = objectid;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
511
  	key.offset = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
512
513
514
515
516
  	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
  	ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
  				&root_item);
  	if (ret)
  		goto fail;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
517
518
  	key.offset = (u64)-1;
  	new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
79787eaab   Jeff Mahoney   btrfs: replace ma...
519
520
521
522
523
  	if (IS_ERR(new_root)) {
  		btrfs_abort_transaction(trans, root, PTR_ERR(new_root));
  		ret = PTR_ERR(new_root);
  		goto fail;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
524
525
  
  	btrfs_record_root_in_trans(trans, new_root);
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
526
  	ret = btrfs_create_subvol_root(trans, new_root, root, new_dirid);
ce598979b   Mark Fasheh   btrfs: Don't BUG_...
527
528
  	if (ret) {
  		/* We potentially lose an unused inode item here */
79787eaab   Jeff Mahoney   btrfs: replace ma...
529
  		btrfs_abort_transaction(trans, root, ret);
ce598979b   Mark Fasheh   btrfs: Don't BUG_...
530
531
  		goto fail;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
532
533
534
  	/*
  	 * insert the directory item
  	 */
3de4586c5   Chris Mason   Btrfs: Allow subv...
535
  	ret = btrfs_set_inode_index(dir, &index);
79787eaab   Jeff Mahoney   btrfs: replace ma...
536
537
538
539
  	if (ret) {
  		btrfs_abort_transaction(trans, root, ret);
  		goto fail;
  	}
3de4586c5   Chris Mason   Btrfs: Allow subv...
540
541
  
  	ret = btrfs_insert_dir_item(trans, root,
16cdcec73   Miao Xie   btrfs: implement ...
542
  				    name, namelen, dir, &key,
3de4586c5   Chris Mason   Btrfs: Allow subv...
543
  				    BTRFS_FT_DIR, index);
79787eaab   Jeff Mahoney   btrfs: replace ma...
544
545
  	if (ret) {
  		btrfs_abort_transaction(trans, root, ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
546
  		goto fail;
79787eaab   Jeff Mahoney   btrfs: replace ma...
547
  	}
0660b5af3   Chris Mason   Btrfs: Add backre...
548

52c261799   Yan Zheng   Btrfs: update dir...
549
550
551
  	btrfs_i_size_write(dir, dir->i_size + namelen * 2);
  	ret = btrfs_update_inode(trans, root, dir);
  	BUG_ON(ret);
0660b5af3   Chris Mason   Btrfs: Add backre...
552
  	ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
4df27c4d5   Yan, Zheng   Btrfs: change how...
553
  				 objectid, root->root_key.objectid,
33345d015   Li Zefan   Btrfs: Always use...
554
  				 btrfs_ino(dir), index, name, namelen);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
555
  	BUG_ON(ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
556

dd5f9615f   Stefan Behrens   Btrfs: maintain s...
557
558
559
560
561
  	ret = btrfs_uuid_tree_add(trans, root->fs_info->uuid_root,
  				  root_item.uuid, BTRFS_UUID_KEY_SUBVOL,
  				  objectid);
  	if (ret)
  		btrfs_abort_transaction(trans, root, ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
562
  fail:
d5c120701   Miao Xie   Btrfs: fix wrong ...
563
564
  	trans->block_rsv = NULL;
  	trans->bytes_reserved = 0;
de6e82006   Liu Bo   Btrfs: release su...
565
  	btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
566
567
568
  	if (async_transid) {
  		*async_transid = trans->transid;
  		err = btrfs_commit_transaction_async(trans, root, 1);
00d71c9c1   Miao Xie   Btrfs: fix unclos...
569
570
  		if (err)
  			err = btrfs_commit_transaction(trans, root);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
571
572
573
  	} else {
  		err = btrfs_commit_transaction(trans, root);
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
574
575
  	if (err && !ret)
  		ret = err;
1a65e24b0   Chris Mason   Btrfs: move d_ins...
576

5662344b3   Tsutomu Itoh   Btrfs: fix error ...
577
578
  	if (!ret) {
  		inode = btrfs_lookup_dentry(dir, dentry);
de6e82006   Liu Bo   Btrfs: release su...
579
580
  		if (IS_ERR(inode))
  			return PTR_ERR(inode);
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
581
582
  		d_instantiate(dentry, inode);
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
583
584
  	return ret;
  }
8257b2dc3   Miao Xie   Btrfs: introduce ...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
  static void btrfs_wait_nocow_write(struct btrfs_root *root)
  {
  	s64 writers;
  	DEFINE_WAIT(wait);
  
  	do {
  		prepare_to_wait(&root->subv_writers->wait, &wait,
  				TASK_UNINTERRUPTIBLE);
  
  		writers = percpu_counter_sum(&root->subv_writers->counter);
  		if (writers)
  			schedule();
  
  		finish_wait(&root->subv_writers->wait, &wait);
  	} while (writers);
  }
e9662f701   Miao Xie   Btrfs: remove unn...
601
602
603
604
  static int create_snapshot(struct btrfs_root *root, struct inode *dir,
  			   struct dentry *dentry, char *name, int namelen,
  			   u64 *async_transid, bool readonly,
  			   struct btrfs_qgroup_inherit *inherit)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
605
  {
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
606
  	struct inode *inode;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
607
608
  	struct btrfs_pending_snapshot *pending_snapshot;
  	struct btrfs_trans_handle *trans;
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
609
  	int ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
610
611
612
  
  	if (!root->ref_cows)
  		return -EINVAL;
8257b2dc3   Miao Xie   Btrfs: introduce ...
613
614
615
  	atomic_inc(&root->will_be_snapshoted);
  	smp_mb__after_atomic_inc();
  	btrfs_wait_nocow_write(root);
6a03843df   Miao Xie   Btrfs: just flush...
616
617
  	ret = btrfs_start_delalloc_inodes(root, 0);
  	if (ret)
8257b2dc3   Miao Xie   Btrfs: introduce ...
618
  		goto out;
6a03843df   Miao Xie   Btrfs: just flush...
619

b02441999   Miao Xie   Btrfs: don't wait...
620
  	btrfs_wait_ordered_extents(root, -1);
6a03843df   Miao Xie   Btrfs: just flush...
621

3de4586c5   Chris Mason   Btrfs: Allow subv...
622
  	pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
8257b2dc3   Miao Xie   Btrfs: introduce ...
623
624
625
626
  	if (!pending_snapshot) {
  		ret = -ENOMEM;
  		goto out;
  	}
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
627

66d8f3dd1   Miao Xie   Btrfs: add a new ...
628
629
  	btrfs_init_block_rsv(&pending_snapshot->block_rsv,
  			     BTRFS_BLOCK_RSV_TEMP);
d5c120701   Miao Xie   Btrfs: fix wrong ...
630
631
632
633
634
635
  	/*
  	 * 1 - parent dir inode
  	 * 2 - dir entries
  	 * 1 - root item
  	 * 2 - root ref/backref
  	 * 1 - root of snapshot
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
636
  	 * 1 - UUID item
d5c120701   Miao Xie   Btrfs: fix wrong ...
637
638
  	 */
  	ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
639
  					&pending_snapshot->block_rsv, 8,
ee3441b49   Jeff Mahoney   btrfs: fall back ...
640
641
  					&pending_snapshot->qgroup_reserved,
  					false);
d5c120701   Miao Xie   Btrfs: fix wrong ...
642
  	if (ret)
8257b2dc3   Miao Xie   Btrfs: introduce ...
643
  		goto free;
d5c120701   Miao Xie   Btrfs: fix wrong ...
644

3de4586c5   Chris Mason   Btrfs: Allow subv...
645
  	pending_snapshot->dentry = dentry;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
646
  	pending_snapshot->root = root;
b83cc9693   Li Zefan   Btrfs: Add readon...
647
  	pending_snapshot->readonly = readonly;
e9662f701   Miao Xie   Btrfs: remove unn...
648
  	pending_snapshot->dir = dir;
8696c5330   Miao Xie   Btrfs: fix memory...
649
  	pending_snapshot->inherit = inherit;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
650

d5c120701   Miao Xie   Btrfs: fix wrong ...
651
  	trans = btrfs_start_transaction(root, 0);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
652
653
654
655
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto fail;
  	}
8351583e3   Josef Bacik   Btrfs: protect th...
656
  	spin_lock(&root->fs_info->trans_lock);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
657
658
  	list_add(&pending_snapshot->list,
  		 &trans->transaction->pending_snapshots);
8351583e3   Josef Bacik   Btrfs: protect th...
659
  	spin_unlock(&root->fs_info->trans_lock);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
660
661
662
663
  	if (async_transid) {
  		*async_transid = trans->transid;
  		ret = btrfs_commit_transaction_async(trans,
  				     root->fs_info->extent_root, 1);
00d71c9c1   Miao Xie   Btrfs: fix unclos...
664
665
  		if (ret)
  			ret = btrfs_commit_transaction(trans, root);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
666
667
668
669
  	} else {
  		ret = btrfs_commit_transaction(trans,
  					       root->fs_info->extent_root);
  	}
aec8030a8   Miao Xie   Btrfs: fix wrong ...
670
  	if (ret)
c37b2b626   Josef Bacik   Btrfs: do not bug...
671
  		goto fail;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
672
673
674
675
  
  	ret = pending_snapshot->error;
  	if (ret)
  		goto fail;
66b4ffd11   Josef Bacik   Btrfs: handle err...
676
677
678
  	ret = btrfs_orphan_cleanup(pending_snapshot->snap);
  	if (ret)
  		goto fail;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
679

2fbe8c8ad   Al Viro   get rid of useles...
680
  	inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
681
682
683
684
  	if (IS_ERR(inode)) {
  		ret = PTR_ERR(inode);
  		goto fail;
  	}
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
685

2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
686
687
688
  	d_instantiate(dentry, inode);
  	ret = 0;
  fail:
d5c120701   Miao Xie   Btrfs: fix wrong ...
689
690
691
  	btrfs_subvolume_release_metadata(BTRFS_I(dir)->root,
  					 &pending_snapshot->block_rsv,
  					 pending_snapshot->qgroup_reserved);
8257b2dc3   Miao Xie   Btrfs: introduce ...
692
  free:
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
693
  	kfree(pending_snapshot);
8257b2dc3   Miao Xie   Btrfs: introduce ...
694
695
  out:
  	atomic_dec(&root->will_be_snapshoted);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
696
697
  	return ret;
  }
4260f7c75   Sage Weil   Btrfs: allow subv...
698
699
700
701
702
703
  /*  copy of check_sticky in fs/namei.c()
  * It's inline, so penalty for filesystems that don't use sticky bit is
  * minimal.
  */
  static inline int btrfs_check_sticky(struct inode *dir, struct inode *inode)
  {
2f2f43d3c   Eric W. Biederman   userns: Convert b...
704
  	kuid_t fsuid = current_fsuid();
4260f7c75   Sage Weil   Btrfs: allow subv...
705
706
707
  
  	if (!(dir->i_mode & S_ISVTX))
  		return 0;
2f2f43d3c   Eric W. Biederman   userns: Convert b...
708
  	if (uid_eq(inode->i_uid, fsuid))
4260f7c75   Sage Weil   Btrfs: allow subv...
709
  		return 0;
2f2f43d3c   Eric W. Biederman   userns: Convert b...
710
  	if (uid_eq(dir->i_uid, fsuid))
4260f7c75   Sage Weil   Btrfs: allow subv...
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
  		return 0;
  	return !capable(CAP_FOWNER);
  }
  
  /*  copy of may_delete in fs/namei.c()
   *	Check whether we can remove a link victim from directory dir, check
   *  whether the type of victim is right.
   *  1. We can't do it if dir is read-only (done in permission())
   *  2. We should have write and exec permissions on dir
   *  3. We can't remove anything from append-only dir
   *  4. We can't do anything with immutable dir (done in permission())
   *  5. If the sticky bit on dir is set we should either
   *	a. be owner of dir, or
   *	b. be owner of victim, or
   *	c. have CAP_FOWNER capability
   *  6. If the victim is append-only or immutable we can't do antyhing with
   *     links pointing to it.
   *  7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
   *  8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
   *  9. We can't remove a root or mountpoint.
   * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
   *     nfs_async_unlink().
   */
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
734
  static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
4260f7c75   Sage Weil   Btrfs: allow subv...
735
736
737
738
739
740
741
  {
  	int error;
  
  	if (!victim->d_inode)
  		return -ENOENT;
  
  	BUG_ON(victim->d_parent->d_inode != dir);
4fa6b5ecb   Jeff Layton   audit: overhaul _...
742
  	audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
4260f7c75   Sage Weil   Btrfs: allow subv...
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  
  	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
  	if (error)
  		return error;
  	if (IS_APPEND(dir))
  		return -EPERM;
  	if (btrfs_check_sticky(dir, victim->d_inode)||
  		IS_APPEND(victim->d_inode)||
  	    IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
  		return -EPERM;
  	if (isdir) {
  		if (!S_ISDIR(victim->d_inode->i_mode))
  			return -ENOTDIR;
  		if (IS_ROOT(victim))
  			return -EBUSY;
  	} else if (S_ISDIR(victim->d_inode->i_mode))
  		return -EISDIR;
  	if (IS_DEADDIR(dir))
  		return -ENOENT;
  	if (victim->d_flags & DCACHE_NFSFS_RENAMED)
  		return -EBUSY;
  	return 0;
  }
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
  /* copy of may_create in fs/namei.c() */
  static inline int btrfs_may_create(struct inode *dir, struct dentry *child)
  {
  	if (child->d_inode)
  		return -EEXIST;
  	if (IS_DEADDIR(dir))
  		return -ENOENT;
  	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
  }
  
  /*
   * Create a new subvolume below @parent.  This is largely modeled after
   * sys_mkdirat and vfs_mkdir, but we only do a single component lookup
   * inside this filesystem so it's quite a bit simpler.
   */
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
781
782
  static noinline int btrfs_mksubvol(struct path *parent,
  				   char *name, int namelen,
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
783
  				   struct btrfs_root *snap_src,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
784
  				   u64 *async_transid, bool readonly,
8696c5330   Miao Xie   Btrfs: fix memory...
785
  				   struct btrfs_qgroup_inherit *inherit)
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
786
  {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
787
  	struct inode *dir  = parent->dentry->d_inode;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
788
789
  	struct dentry *dentry;
  	int error;
5c50c9b89   David Sterba   btrfs: make subvo...
790
791
792
  	error = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
  	if (error == -EINTR)
  		return error;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
793
794
795
796
797
798
799
800
801
  
  	dentry = lookup_one_len(name, parent->dentry, namelen);
  	error = PTR_ERR(dentry);
  	if (IS_ERR(dentry))
  		goto out_unlock;
  
  	error = -EEXIST;
  	if (dentry->d_inode)
  		goto out_dput;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
802
  	error = btrfs_may_create(dir, dentry);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
803
  	if (error)
a874a63e1   Liu Bo   Btrfs: check writ...
804
  		goto out_dput;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
805

9c52057c6   Chris Mason   Btrfs: fix hash o...
806
807
808
809
810
811
812
813
814
  	/*
  	 * even if this name doesn't exist, we may get hash collisions.
  	 * check for them now when we can safely fail
  	 */
  	error = btrfs_check_dir_item_collision(BTRFS_I(dir)->root,
  					       dir->i_ino, name,
  					       namelen);
  	if (error)
  		goto out_dput;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
815
816
817
818
  	down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
  
  	if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0)
  		goto out_up_read;
3de4586c5   Chris Mason   Btrfs: Allow subv...
819
  	if (snap_src) {
e9662f701   Miao Xie   Btrfs: remove unn...
820
  		error = create_snapshot(snap_src, dir, dentry, name, namelen,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
821
  					async_transid, readonly, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
822
  	} else {
d5c120701   Miao Xie   Btrfs: fix wrong ...
823
824
  		error = create_subvol(dir, dentry, name, namelen,
  				      async_transid, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
825
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
826
827
828
829
  	if (!error)
  		fsnotify_mkdir(dir, dentry);
  out_up_read:
  	up_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
830
831
832
  out_dput:
  	dput(dentry);
  out_unlock:
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
833
  	mutex_unlock(&dir->i_mutex);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
834
835
  	return error;
  }
4cb5300bc   Chris Mason   Btrfs: add mount ...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
  /*
   * When we're defragging a range, we don't want to kick it off again
   * if it is really just waiting for delalloc to send it down.
   * If we find a nice big extent or delalloc range for the bytes in the
   * file you want to defrag, we return 0 to let you know to skip this
   * part of the file
   */
  static int check_defrag_in_cache(struct inode *inode, u64 offset, int thresh)
  {
  	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
  	struct extent_map *em = NULL;
  	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
  	u64 end;
  
  	read_lock(&em_tree->lock);
  	em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE);
  	read_unlock(&em_tree->lock);
  
  	if (em) {
  		end = extent_map_end(em);
  		free_extent_map(em);
  		if (end - offset > thresh)
  			return 0;
  	}
  	/* if we already have a nice delalloc here, just stop */
  	thresh /= 2;
  	end = count_range_bits(io_tree, &offset, offset + thresh,
  			       thresh, EXTENT_DELALLOC, 1);
  	if (end >= thresh)
  		return 0;
  	return 1;
  }
  
  /*
   * helper function to walk through a file and find extents
   * newer than a specific transid, and smaller than thresh.
   *
   * This is used by the defragging code to find new and small
   * extents
   */
  static int find_new_extents(struct btrfs_root *root,
  			    struct inode *inode, u64 newer_than,
  			    u64 *off, int thresh)
  {
  	struct btrfs_path *path;
  	struct btrfs_key min_key;
4cb5300bc   Chris Mason   Btrfs: add mount ...
882
883
884
885
  	struct extent_buffer *leaf;
  	struct btrfs_file_extent_item *extent;
  	int type;
  	int ret;
a4689d2bd   David Sterba   btrfs: use btrfs_...
886
  	u64 ino = btrfs_ino(inode);
4cb5300bc   Chris Mason   Btrfs: add mount ...
887
888
889
890
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
a4689d2bd   David Sterba   btrfs: use btrfs_...
891
  	min_key.objectid = ino;
4cb5300bc   Chris Mason   Btrfs: add mount ...
892
893
  	min_key.type = BTRFS_EXTENT_DATA_KEY;
  	min_key.offset = *off;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
894
  	while (1) {
f094c9bd3   Filipe Manana   Btrfs: less fs tr...
895
  		path->keep_locks = 1;
6174d3cb4   Filipe David Borba Manana   Btrfs: remove unu...
896
  		ret = btrfs_search_forward(root, &min_key, path, newer_than);
4cb5300bc   Chris Mason   Btrfs: add mount ...
897
898
  		if (ret != 0)
  			goto none;
f094c9bd3   Filipe Manana   Btrfs: less fs tr...
899
900
901
  		path->keep_locks = 0;
  		btrfs_unlock_up_safe(path, 1);
  process_slot:
a4689d2bd   David Sterba   btrfs: use btrfs_...
902
  		if (min_key.objectid != ino)
4cb5300bc   Chris Mason   Btrfs: add mount ...
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
  			goto none;
  		if (min_key.type != BTRFS_EXTENT_DATA_KEY)
  			goto none;
  
  		leaf = path->nodes[0];
  		extent = btrfs_item_ptr(leaf, path->slots[0],
  					struct btrfs_file_extent_item);
  
  		type = btrfs_file_extent_type(leaf, extent);
  		if (type == BTRFS_FILE_EXTENT_REG &&
  		    btrfs_file_extent_num_bytes(leaf, extent) < thresh &&
  		    check_defrag_in_cache(inode, min_key.offset, thresh)) {
  			*off = min_key.offset;
  			btrfs_free_path(path);
  			return 0;
  		}
f094c9bd3   Filipe Manana   Btrfs: less fs tr...
919
920
921
922
923
  		path->slots[0]++;
  		if (path->slots[0] < btrfs_header_nritems(leaf)) {
  			btrfs_item_key_to_cpu(leaf, &min_key, path->slots[0]);
  			goto process_slot;
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
924
925
926
927
928
929
930
931
932
933
  		if (min_key.offset == (u64)-1)
  			goto none;
  
  		min_key.offset++;
  		btrfs_release_path(path);
  	}
  none:
  	btrfs_free_path(path);
  	return -ENOENT;
  }
6c282eb40   Li Zefan   Btrfs: fix defrag...
934
  static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start)
17ce6ef8d   Liu Bo   Btrfs: add a chec...
935
936
  {
  	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
6c282eb40   Li Zefan   Btrfs: fix defrag...
937
938
939
  	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
  	struct extent_map *em;
  	u64 len = PAGE_CACHE_SIZE;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
940

6c282eb40   Li Zefan   Btrfs: fix defrag...
941
942
943
944
  	/*
  	 * hopefully we have this extent in the tree already, try without
  	 * the full extent lock
  	 */
17ce6ef8d   Liu Bo   Btrfs: add a chec...
945
  	read_lock(&em_tree->lock);
6c282eb40   Li Zefan   Btrfs: fix defrag...
946
  	em = lookup_extent_mapping(em_tree, start, len);
17ce6ef8d   Liu Bo   Btrfs: add a chec...
947
  	read_unlock(&em_tree->lock);
6c282eb40   Li Zefan   Btrfs: fix defrag...
948
  	if (!em) {
308d9800b   Filipe Manana   Btrfs: cache exte...
949
950
  		struct extent_state *cached = NULL;
  		u64 end = start + len - 1;
6c282eb40   Li Zefan   Btrfs: fix defrag...
951
  		/* get the big lock and read metadata off disk */
308d9800b   Filipe Manana   Btrfs: cache exte...
952
  		lock_extent_bits(io_tree, start, end, 0, &cached);
6c282eb40   Li Zefan   Btrfs: fix defrag...
953
  		em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
308d9800b   Filipe Manana   Btrfs: cache exte...
954
  		unlock_extent_cached(io_tree, start, end, &cached, GFP_NOFS);
6c282eb40   Li Zefan   Btrfs: fix defrag...
955
956
957
958
959
960
961
  
  		if (IS_ERR(em))
  			return NULL;
  	}
  
  	return em;
  }
17ce6ef8d   Liu Bo   Btrfs: add a chec...
962

6c282eb40   Li Zefan   Btrfs: fix defrag...
963
964
965
966
967
968
969
970
971
972
  static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em)
  {
  	struct extent_map *next;
  	bool ret = true;
  
  	/* this is the last extent */
  	if (em->start + em->len >= i_size_read(inode))
  		return false;
  
  	next = defrag_lookup_extent(inode, em->start + em->len);
e2127cf00   Filipe Manana   Btrfs: make defra...
973
974
  	if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE ||
  	    (em->block_start + em->block_len == next->block_start))
6c282eb40   Li Zefan   Btrfs: fix defrag...
975
976
977
  		ret = false;
  
  	free_extent_map(next);
17ce6ef8d   Liu Bo   Btrfs: add a chec...
978
979
  	return ret;
  }
6c282eb40   Li Zefan   Btrfs: fix defrag...
980
  static int should_defrag_range(struct inode *inode, u64 start, int thresh,
a43a21113   Andrew Mahone   btrfs: ignore unf...
981
982
  			       u64 *last_len, u64 *skip, u64 *defrag_end,
  			       int compress)
940100a4a   Chris Mason   Btrfs: be more se...
983
  {
6c282eb40   Li Zefan   Btrfs: fix defrag...
984
  	struct extent_map *em;
940100a4a   Chris Mason   Btrfs: be more se...
985
  	int ret = 1;
6c282eb40   Li Zefan   Btrfs: fix defrag...
986
  	bool next_mergeable = true;
940100a4a   Chris Mason   Btrfs: be more se...
987
988
  
  	/*
008873eaf   Li Zefan   Btrfs: honor exte...
989
  	 * make sure that once we start defragging an extent, we keep on
940100a4a   Chris Mason   Btrfs: be more se...
990
991
992
993
994
995
  	 * defragging it
  	 */
  	if (start < *defrag_end)
  		return 1;
  
  	*skip = 0;
6c282eb40   Li Zefan   Btrfs: fix defrag...
996
997
998
  	em = defrag_lookup_extent(inode, start);
  	if (!em)
  		return 0;
940100a4a   Chris Mason   Btrfs: be more se...
999
1000
  
  	/* this will cover holes, and inline extents */
17ce6ef8d   Liu Bo   Btrfs: add a chec...
1001
  	if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
940100a4a   Chris Mason   Btrfs: be more se...
1002
  		ret = 0;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
1003
1004
  		goto out;
  	}
6c282eb40   Li Zefan   Btrfs: fix defrag...
1005
  	next_mergeable = defrag_check_next_extent(inode, em);
940100a4a   Chris Mason   Btrfs: be more se...
1006
1007
  
  	/*
6c282eb40   Li Zefan   Btrfs: fix defrag...
1008
1009
  	 * we hit a real extent, if it is big or the next extent is not a
  	 * real extent, don't bother defragging it
940100a4a   Chris Mason   Btrfs: be more se...
1010
  	 */
a43a21113   Andrew Mahone   btrfs: ignore unf...
1011
  	if (!compress && (*last_len == 0 || *last_len >= thresh) &&
6c282eb40   Li Zefan   Btrfs: fix defrag...
1012
  	    (em->len >= thresh || !next_mergeable))
940100a4a   Chris Mason   Btrfs: be more se...
1013
  		ret = 0;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
1014
  out:
940100a4a   Chris Mason   Btrfs: be more se...
1015
1016
1017
1018
1019
1020
1021
1022
1023
  	/*
  	 * last_len ends up being a counter of how many bytes we've defragged.
  	 * every time we choose not to defrag an extent, we reset *last_len
  	 * so that the next tiny extent will force a defrag.
  	 *
  	 * The end result of this is that tiny extents before a single big
  	 * extent will force at least part of that big extent to be defragged.
  	 */
  	if (ret) {
940100a4a   Chris Mason   Btrfs: be more se...
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
  		*defrag_end = extent_map_end(em);
  	} else {
  		*last_len = 0;
  		*skip = extent_map_end(em);
  		*defrag_end = 0;
  	}
  
  	free_extent_map(em);
  	return ret;
  }
4cb5300bc   Chris Mason   Btrfs: add mount ...
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
  /*
   * it doesn't do much good to defrag one or two pages
   * at a time.  This pulls in a nice chunk of pages
   * to COW and defrag.
   *
   * It also makes sure the delalloc code has enough
   * dirty data to avoid making new small extents as part
   * of the defrag
   *
   * It's a good idea to start RA on this range
   * before calling this.
   */
  static int cluster_pages_for_defrag(struct inode *inode,
  				    struct page **pages,
  				    unsigned long start_index,
c41570c9d   Justin Maggard   btrfs: fix defrag...
1049
  				    unsigned long num_pages)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1050
  {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1051
1052
1053
1054
  	unsigned long file_end;
  	u64 isize = i_size_read(inode);
  	u64 page_start;
  	u64 page_end;
1f12bd063   Liu Bo   Btrfs: fix the mi...
1055
  	u64 page_cnt;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1056
1057
1058
  	int ret;
  	int i;
  	int i_done;
3eaa28852   Chris Mason   Btrfs: Fix the de...
1059
  	struct btrfs_ordered_extent *ordered;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1060
  	struct extent_state *cached_state = NULL;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1061
  	struct extent_io_tree *tree;
3b16a4e3c   Josef Bacik   Btrfs: use the in...
1062
  	gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1063

4cb5300bc   Chris Mason   Btrfs: add mount ...
1064
  	file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
1f12bd063   Liu Bo   Btrfs: fix the mi...
1065
1066
1067
1068
  	if (!isize || start_index > file_end)
  		return 0;
  
  	page_cnt = min_t(u64, (u64)num_pages, (u64)file_end - start_index + 1);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1069
1070
  
  	ret = btrfs_delalloc_reserve_space(inode,
1f12bd063   Liu Bo   Btrfs: fix the mi...
1071
  					   page_cnt << PAGE_CACHE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1072
1073
  	if (ret)
  		return ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1074
  	i_done = 0;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1075
  	tree = &BTRFS_I(inode)->io_tree;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1076
1077
  
  	/* step one, lock all the pages */
1f12bd063   Liu Bo   Btrfs: fix the mi...
1078
  	for (i = 0; i < page_cnt; i++) {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1079
  		struct page *page;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1080
  again:
a94733d0b   Josef Bacik   Btrfs: use find_o...
1081
  		page = find_or_create_page(inode->i_mapping,
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1082
  					   start_index + i, mask);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1083
1084
  		if (!page)
  			break;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1085
1086
1087
  		page_start = page_offset(page);
  		page_end = page_start + PAGE_CACHE_SIZE - 1;
  		while (1) {
308d9800b   Filipe Manana   Btrfs: cache exte...
1088
1089
  			lock_extent_bits(tree, page_start, page_end,
  					 0, &cached_state);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1090
1091
  			ordered = btrfs_lookup_ordered_extent(inode,
  							      page_start);
308d9800b   Filipe Manana   Btrfs: cache exte...
1092
1093
  			unlock_extent_cached(tree, page_start, page_end,
  					     &cached_state, GFP_NOFS);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1094
1095
1096
1097
1098
1099
1100
  			if (!ordered)
  				break;
  
  			unlock_page(page);
  			btrfs_start_ordered_extent(inode, ordered, 1);
  			btrfs_put_ordered_extent(ordered);
  			lock_page(page);
1f12bd063   Liu Bo   Btrfs: fix the mi...
1101
1102
1103
1104
1105
1106
1107
1108
1109
  			/*
  			 * we unlocked the page above, so we need check if
  			 * it was released or not.
  			 */
  			if (page->mapping != inode->i_mapping) {
  				unlock_page(page);
  				page_cache_release(page);
  				goto again;
  			}
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1110
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
  		if (!PageUptodate(page)) {
  			btrfs_readpage(NULL, page);
  			lock_page(page);
  			if (!PageUptodate(page)) {
  				unlock_page(page);
  				page_cache_release(page);
  				ret = -EIO;
  				break;
  			}
  		}
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1121

600a45e1d   Miao Xie   Btrfs: fix deadlo...
1122
1123
1124
1125
1126
  		if (page->mapping != inode->i_mapping) {
  			unlock_page(page);
  			page_cache_release(page);
  			goto again;
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  		pages[i] = page;
  		i_done++;
  	}
  	if (!i_done || ret)
  		goto out;
  
  	if (!(inode->i_sb->s_flags & MS_ACTIVE))
  		goto out;
  
  	/*
  	 * so now we have a nice long stream of locked
  	 * and up to date pages, lets wait on them
  	 */
  	for (i = 0; i < i_done; i++)
  		wait_on_page_writeback(pages[i]);
  
  	page_start = page_offset(pages[0]);
  	page_end = page_offset(pages[i_done - 1]) + PAGE_CACHE_SIZE;
  
  	lock_extent_bits(&BTRFS_I(inode)->io_tree,
d0082371c   Jeff Mahoney   btrfs: drop gfp_t...
1147
  			 page_start, page_end - 1, 0, &cached_state);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1148
1149
  	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
  			  page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
9e8a4a8b0   Liu Bo   Btrfs: use flag E...
1150
1151
  			  EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0,
  			  &cached_state, GFP_NOFS);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1152

1f12bd063   Liu Bo   Btrfs: fix the mi...
1153
  	if (i_done != page_cnt) {
9e0baf60d   Josef Bacik   Btrfs: fix enospc...
1154
1155
1156
  		spin_lock(&BTRFS_I(inode)->lock);
  		BTRFS_I(inode)->outstanding_extents++;
  		spin_unlock(&BTRFS_I(inode)->lock);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1157
  		btrfs_delalloc_release_space(inode,
1f12bd063   Liu Bo   Btrfs: fix the mi...
1158
  				     (page_cnt - i_done) << PAGE_CACHE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1159
  	}
9e8a4a8b0   Liu Bo   Btrfs: use flag E...
1160
1161
  	set_extent_defrag(&BTRFS_I(inode)->io_tree, page_start, page_end - 1,
  			  &cached_state, GFP_NOFS);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
  
  	unlock_extent_cached(&BTRFS_I(inode)->io_tree,
  			     page_start, page_end - 1, &cached_state,
  			     GFP_NOFS);
  
  	for (i = 0; i < i_done; i++) {
  		clear_page_dirty_for_io(pages[i]);
  		ClearPageChecked(pages[i]);
  		set_page_extent_mapped(pages[i]);
  		set_page_dirty(pages[i]);
  		unlock_page(pages[i]);
  		page_cache_release(pages[i]);
  	}
  	return i_done;
  out:
  	for (i = 0; i < i_done; i++) {
  		unlock_page(pages[i]);
  		page_cache_release(pages[i]);
  	}
1f12bd063   Liu Bo   Btrfs: fix the mi...
1181
  	btrfs_delalloc_release_space(inode, page_cnt << PAGE_CACHE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1182
1183
1184
1185
1186
1187
1188
1189
1190
  	return ret;
  
  }
  
  int btrfs_defrag_file(struct inode *inode, struct file *file,
  		      struct btrfs_ioctl_defrag_range_args *range,
  		      u64 newer_than, unsigned long max_to_defrag)
  {
  	struct btrfs_root *root = BTRFS_I(inode)->root;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1191
  	struct file_ra_state *ra = NULL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1192
  	unsigned long last_index;
151a31b25   Li Zefan   Btrfs: use i_size...
1193
  	u64 isize = i_size_read(inode);
940100a4a   Chris Mason   Btrfs: be more se...
1194
1195
1196
  	u64 last_len = 0;
  	u64 skip = 0;
  	u64 defrag_end = 0;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1197
  	u64 newer_off = range->start;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1198
  	unsigned long i;
008873eaf   Li Zefan   Btrfs: honor exte...
1199
  	unsigned long ra_index = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1200
  	int ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1201
  	int defrag_count = 0;
1a419d85a   Li Zefan   btrfs: Allow to s...
1202
  	int compress_type = BTRFS_COMPRESS_ZLIB;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1203
  	int extent_thresh = range->extent_thresh;
c41570c9d   Justin Maggard   btrfs: fix defrag...
1204
1205
  	unsigned long max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT;
  	unsigned long cluster = max_cluster;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1206
1207
  	u64 new_align = ~((u64)128 * 1024 - 1);
  	struct page **pages = NULL;
0abd5b172   Liu Bo   Btrfs: return err...
1208
1209
1210
1211
1212
  	if (isize == 0)
  		return 0;
  
  	if (range->start >= isize)
  		return -EINVAL;
1a419d85a   Li Zefan   btrfs: Allow to s...
1213
1214
1215
1216
1217
1218
1219
  
  	if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
  		if (range->compress_type > BTRFS_COMPRESS_TYPES)
  			return -EINVAL;
  		if (range->compress_type)
  			compress_type = range->compress_type;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1220

0abd5b172   Liu Bo   Btrfs: return err...
1221
1222
  	if (extent_thresh == 0)
  		extent_thresh = 256 * 1024;
940100a4a   Chris Mason   Btrfs: be more se...
1223

4cb5300bc   Chris Mason   Btrfs: add mount ...
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
  	/*
  	 * if we were not given a file, allocate a readahead
  	 * context
  	 */
  	if (!file) {
  		ra = kzalloc(sizeof(*ra), GFP_NOFS);
  		if (!ra)
  			return -ENOMEM;
  		file_ra_state_init(ra, inode->i_mapping);
  	} else {
  		ra = &file->f_ra;
  	}
d9b0d9ba0   Dulshani Gunawardhana   btrfs: Replace km...
1236
  	pages = kmalloc_array(max_cluster, sizeof(struct page *),
4cb5300bc   Chris Mason   Btrfs: add mount ...
1237
1238
1239
1240
1241
1242
1243
  			GFP_NOFS);
  	if (!pages) {
  		ret = -ENOMEM;
  		goto out_ra;
  	}
  
  	/* find the last page to defrag */
1e701a329   Chris Mason   Btrfs: add new de...
1244
  	if (range->start + range->len > range->start) {
151a31b25   Li Zefan   Btrfs: use i_size...
1245
  		last_index = min_t(u64, isize - 1,
1e701a329   Chris Mason   Btrfs: add new de...
1246
1247
  			 range->start + range->len - 1) >> PAGE_CACHE_SHIFT;
  	} else {
151a31b25   Li Zefan   Btrfs: use i_size...
1248
  		last_index = (isize - 1) >> PAGE_CACHE_SHIFT;
1e701a329   Chris Mason   Btrfs: add new de...
1249
  	}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
  	if (newer_than) {
  		ret = find_new_extents(root, inode, newer_than,
  				       &newer_off, 64 * 1024);
  		if (!ret) {
  			range->start = newer_off;
  			/*
  			 * we always align our defrag to help keep
  			 * the extents in the file evenly spaced
  			 */
  			i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1260
1261
1262
1263
1264
1265
  		} else
  			goto out_ra;
  	} else {
  		i = range->start >> PAGE_CACHE_SHIFT;
  	}
  	if (!max_to_defrag)
7ec31b548   Liu Bo   Btrfs: do not def...
1266
  		max_to_defrag = last_index + 1;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1267

2a0f7f576   Li Zefan   Btrfs: fix recurs...
1268
1269
1270
1271
1272
1273
  	/*
  	 * make writeback starts from i, so the defrag range can be
  	 * written sequentially.
  	 */
  	if (i < inode->i_mapping->writeback_index)
  		inode->i_mapping->writeback_index = i;
f7f43cc84   Chris Mason   Btrfs: make sure ...
1274
1275
1276
  	while (i <= last_index && defrag_count < max_to_defrag &&
  	       (i < (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
  		PAGE_CACHE_SHIFT)) {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1277
1278
1279
1280
1281
1282
  		/*
  		 * make sure we stop running if someone unmounts
  		 * the FS
  		 */
  		if (!(inode->i_sb->s_flags & MS_ACTIVE))
  			break;
210549ebe   David Sterba   btrfs: add cancel...
1283
  		if (btrfs_defrag_cancelled(root->fs_info)) {
efe120a06   Frank Holton   Btrfs: convert pr...
1284
1285
  			printk(KERN_DEBUG "BTRFS: defrag_file cancelled
  ");
210549ebe   David Sterba   btrfs: add cancel...
1286
1287
1288
  			ret = -EAGAIN;
  			break;
  		}
66c268922   Liu Bo   Btrfs: do not bot...
1289
  		if (!should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT,
6c282eb40   Li Zefan   Btrfs: fix defrag...
1290
  					 extent_thresh, &last_len, &skip,
a43a21113   Andrew Mahone   btrfs: ignore unf...
1291
1292
  					 &defrag_end, range->flags &
  					 BTRFS_DEFRAG_RANGE_COMPRESS)) {
940100a4a   Chris Mason   Btrfs: be more se...
1293
1294
1295
1296
1297
1298
1299
1300
1301
  			unsigned long next;
  			/*
  			 * the should_defrag function tells us how much to skip
  			 * bump our counter by the suggested amount
  			 */
  			next = (skip + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
  			i = max(i + 1, next);
  			continue;
  		}
008873eaf   Li Zefan   Btrfs: honor exte...
1302
1303
1304
1305
1306
1307
1308
1309
  
  		if (!newer_than) {
  			cluster = (PAGE_CACHE_ALIGN(defrag_end) >>
  				   PAGE_CACHE_SHIFT) - i;
  			cluster = min(cluster, max_cluster);
  		} else {
  			cluster = max_cluster;
  		}
008873eaf   Li Zefan   Btrfs: honor exte...
1310
1311
1312
1313
1314
1315
  		if (i + cluster > ra_index) {
  			ra_index = max(i, ra_index);
  			btrfs_force_ra(inode->i_mapping, ra, file, ra_index,
  				       cluster);
  			ra_index += max_cluster;
  		}
940100a4a   Chris Mason   Btrfs: be more se...
1316

ecb8bea87   Liu Bo   Btrfs: fix race b...
1317
  		mutex_lock(&inode->i_mutex);
633085c79   Filipe David Borba Manana   Btrfs: reset forc...
1318
1319
  		if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
  			BTRFS_I(inode)->force_compress = compress_type;
008873eaf   Li Zefan   Btrfs: honor exte...
1320
  		ret = cluster_pages_for_defrag(inode, pages, i, cluster);
ecb8bea87   Liu Bo   Btrfs: fix race b...
1321
1322
  		if (ret < 0) {
  			mutex_unlock(&inode->i_mutex);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1323
  			goto out_ra;
ecb8bea87   Liu Bo   Btrfs: fix race b...
1324
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1325
1326
  
  		defrag_count += ret;
d0e1d66b5   Namjae Jeon   writeback: remove...
1327
  		balance_dirty_pages_ratelimited(inode->i_mapping);
ecb8bea87   Liu Bo   Btrfs: fix race b...
1328
  		mutex_unlock(&inode->i_mutex);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1329
1330
1331
1332
  
  		if (newer_than) {
  			if (newer_off == (u64)-1)
  				break;
e1f041e14   Liu Bo   Btrfs: update to ...
1333
1334
  			if (ret > 0)
  				i += ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1335
1336
1337
1338
1339
1340
1341
1342
1343
  			newer_off = max(newer_off + 1,
  					(u64)i << PAGE_CACHE_SHIFT);
  
  			ret = find_new_extents(root, inode,
  					       newer_than, &newer_off,
  					       64 * 1024);
  			if (!ret) {
  				range->start = newer_off;
  				i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1344
1345
  			} else {
  				break;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1346
  			}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1347
  		} else {
008873eaf   Li Zefan   Btrfs: honor exte...
1348
  			if (ret > 0) {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1349
  				i += ret;
008873eaf   Li Zefan   Btrfs: honor exte...
1350
1351
  				last_len += ret << PAGE_CACHE_SHIFT;
  			} else {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1352
  				i++;
008873eaf   Li Zefan   Btrfs: honor exte...
1353
1354
  				last_len = 0;
  			}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1355
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1356
  	}
dec8ef905   Filipe Manana   Btrfs: correctly ...
1357
  	if ((range->flags & BTRFS_DEFRAG_RANGE_START_IO)) {
1e701a329   Chris Mason   Btrfs: add new de...
1358
  		filemap_flush(inode->i_mapping);
dec8ef905   Filipe Manana   Btrfs: correctly ...
1359
1360
1361
1362
  		if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
  			     &BTRFS_I(inode)->runtime_flags))
  			filemap_flush(inode->i_mapping);
  	}
1e701a329   Chris Mason   Btrfs: add new de...
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
  
  	if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) {
  		/* the filemap_flush will queue IO into the worker threads, but
  		 * we have to make sure the IO is actually started and that
  		 * ordered extents get created before we return
  		 */
  		atomic_inc(&root->fs_info->async_submit_draining);
  		while (atomic_read(&root->fs_info->nr_async_submits) ||
  		      atomic_read(&root->fs_info->async_delalloc_pages)) {
  			wait_event(root->fs_info->async_submit_wait,
  			   (atomic_read(&root->fs_info->nr_async_submits) == 0 &&
  			    atomic_read(&root->fs_info->async_delalloc_pages) == 0));
  		}
  		atomic_dec(&root->fs_info->async_submit_draining);
1e701a329   Chris Mason   Btrfs: add new de...
1377
  	}
1a419d85a   Li Zefan   btrfs: Allow to s...
1378
  	if (range->compress_type == BTRFS_COMPRESS_LZO) {
2b0ce2c29   Mitch Harder   Btrfs: Check INCO...
1379
  		btrfs_set_fs_incompat(root->fs_info, COMPRESS_LZO);
1a419d85a   Li Zefan   btrfs: Allow to s...
1380
  	}
60ccf82f5   Diego Calleja   btrfs: fix memory...
1381
  	ret = defrag_count;
940100a4a   Chris Mason   Btrfs: be more se...
1382

4cb5300bc   Chris Mason   Btrfs: add mount ...
1383
  out_ra:
633085c79   Filipe David Borba Manana   Btrfs: reset forc...
1384
1385
1386
1387
1388
  	if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
  		mutex_lock(&inode->i_mutex);
  		BTRFS_I(inode)->force_compress = BTRFS_COMPRESS_NONE;
  		mutex_unlock(&inode->i_mutex);
  	}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1389
1390
1391
  	if (!file)
  		kfree(ra);
  	kfree(pages);
940100a4a   Chris Mason   Btrfs: be more se...
1392
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1393
  }
198605a8e   Miao Xie   Btrfs: get write ...
1394
  static noinline int btrfs_ioctl_resize(struct file *file,
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1395
  					void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1396
1397
1398
1399
  {
  	u64 new_size;
  	u64 old_size;
  	u64 devid = 1;
496ad9aa8   Al Viro   new helper: file_...
1400
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1401
1402
1403
1404
  	struct btrfs_ioctl_vol_args *vol_args;
  	struct btrfs_trans_handle *trans;
  	struct btrfs_device *device = NULL;
  	char *sizestr;
9a40f1222   Gui Hecheng   btrfs: filter inv...
1405
  	char *retptr;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1406
1407
  	char *devstr = NULL;
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1408
  	int mod = 0;
e441d54de   Chris Mason   Btrfs: add permis...
1409
1410
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
198605a8e   Miao Xie   Btrfs: get write ...
1411
1412
1413
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5ac00addc   Stefan Behrens   Btrfs: disallow m...
1414
1415
  	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
975476765   Miao Xie   Btrfs: fix missin...
1416
  		mnt_drop_write_file(file);
e57138b3e   Anand Jain   btrfs: return btr...
1417
  		return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1418
  	}
5ac00addc   Stefan Behrens   Btrfs: disallow m...
1419
  	mutex_lock(&root->fs_info->volume_mutex);
dae7b665c   Li Zefan   btrfs: use memdup...
1420
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1421
1422
1423
1424
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
  		goto out;
  	}
5516e5957   Mark Fasheh   Btrfs: Null termi...
1425
1426
  
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1427

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1428
1429
1430
1431
1432
1433
1434
1435
  	sizestr = vol_args->name;
  	devstr = strchr(sizestr, ':');
  	if (devstr) {
  		char *end;
  		sizestr = devstr + 1;
  		*devstr = '\0';
  		devstr = vol_args->name;
  		devid = simple_strtoull(devstr, &end, 10);
dfd79829b   Miao Xie   Btrfs: fix trivia...
1436
1437
1438
1439
  		if (!devid) {
  			ret = -EINVAL;
  			goto out_free;
  		}
efe120a06   Frank Holton   Btrfs: convert pr...
1440
  		btrfs_info(root->fs_info, "resizing devid %llu", devid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1441
  	}
dba60f3f5   Miao Xie   Btrfs: fix resize...
1442

aa1b8cd40   Stefan Behrens   Btrfs: pass fs_in...
1443
  	device = btrfs_find_device(root->fs_info, devid, NULL, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1444
  	if (!device) {
efe120a06   Frank Holton   Btrfs: convert pr...
1445
  		btrfs_info(root->fs_info, "resizer unable to find device %llu",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
1446
  		       devid);
dfd79829b   Miao Xie   Btrfs: fix trivia...
1447
  		ret = -ENODEV;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1448
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1449
  	}
dba60f3f5   Miao Xie   Btrfs: fix resize...
1450
1451
  
  	if (!device->writeable) {
efe120a06   Frank Holton   Btrfs: convert pr...
1452
1453
  		btrfs_info(root->fs_info,
  			   "resizer unable to apply on readonly device %llu",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
1454
  		       devid);
dfd79829b   Miao Xie   Btrfs: fix trivia...
1455
  		ret = -EPERM;
4e42ae1bd   Liu Bo   Btrfs: do not res...
1456
1457
  		goto out_free;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
  	if (!strcmp(sizestr, "max"))
  		new_size = device->bdev->bd_inode->i_size;
  	else {
  		if (sizestr[0] == '-') {
  			mod = -1;
  			sizestr++;
  		} else if (sizestr[0] == '+') {
  			mod = 1;
  			sizestr++;
  		}
9a40f1222   Gui Hecheng   btrfs: filter inv...
1468
1469
  		new_size = memparse(sizestr, &retptr);
  		if (*retptr != '\0' || new_size == 0) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1470
  			ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1471
  			goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1472
1473
  		}
  	}
63a212abc   Stefan Behrens   Btrfs: disallow s...
1474
  	if (device->is_tgtdev_for_dev_replace) {
dfd79829b   Miao Xie   Btrfs: fix trivia...
1475
  		ret = -EPERM;
63a212abc   Stefan Behrens   Btrfs: disallow s...
1476
1477
  		goto out_free;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1478
1479
1480
1481
1482
  	old_size = device->total_bytes;
  
  	if (mod < 0) {
  		if (new_size > old_size) {
  			ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1483
  			goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1484
1485
1486
  		}
  		new_size = old_size - new_size;
  	} else if (mod > 0) {
eb8052e01   Wenliang Fan   fs/btrfs: Integer...
1487
1488
1489
1490
  		if (new_size > ULLONG_MAX - old_size) {
  			ret = -EINVAL;
  			goto out_free;
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1491
1492
1493
1494
1495
  		new_size = old_size + new_size;
  	}
  
  	if (new_size < 256 * 1024 * 1024) {
  		ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1496
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1497
1498
1499
  	}
  	if (new_size > device->bdev->bd_inode->i_size) {
  		ret = -EFBIG;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1500
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1501
1502
1503
1504
  	}
  
  	do_div(new_size, root->sectorsize);
  	new_size *= root->sectorsize;
efe120a06   Frank Holton   Btrfs: convert pr...
1505
1506
  	printk_in_rcu(KERN_INFO "BTRFS: new size for %s is %llu
  ",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
1507
  		      rcu_str_deref(device->name), new_size);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1508
1509
  
  	if (new_size > old_size) {
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
1510
  		trans = btrfs_start_transaction(root, 0);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
1511
1512
  		if (IS_ERR(trans)) {
  			ret = PTR_ERR(trans);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1513
  			goto out_free;
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
1514
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1515
1516
  		ret = btrfs_grow_device(trans, device, new_size);
  		btrfs_commit_transaction(trans, root);
ece7d20e8   Mike Fleetwood   Btrfs: Don't erro...
1517
  	} else if (new_size < old_size) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1518
  		ret = btrfs_shrink_device(device, new_size);
0253f40ef   jeff.liu   Btrfs: Remove the...
1519
  	} /* equal, nothing need to do */
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1520

c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1521
  out_free:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1522
  	kfree(vol_args);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1523
1524
  out:
  	mutex_unlock(&root->fs_info->volume_mutex);
5ac00addc   Stefan Behrens   Btrfs: disallow m...
1525
  	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
18f39c416   Ilya Dryomov   Btrfs: fix unlock...
1526
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1527
1528
  	return ret;
  }
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1529
  static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1530
1531
  				char *name, unsigned long fd, int subvol,
  				u64 *transid, bool readonly,
8696c5330   Miao Xie   Btrfs: fix memory...
1532
  				struct btrfs_qgroup_inherit *inherit)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1533
  {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1534
  	int namelen;
3de4586c5   Chris Mason   Btrfs: Allow subv...
1535
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1536

a874a63e1   Liu Bo   Btrfs: check writ...
1537
1538
1539
  	ret = mnt_want_write_file(file);
  	if (ret)
  		goto out;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1540
1541
  	namelen = strlen(name);
  	if (strchr(name, '/')) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1542
  		ret = -EINVAL;
a874a63e1   Liu Bo   Btrfs: check writ...
1543
  		goto out_drop_write;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1544
  	}
16780cabb   Chris Mason   Btrfs: add extra ...
1545
1546
1547
  	if (name[0] == '.' &&
  	   (namelen == 1 || (name[1] == '.' && namelen == 2))) {
  		ret = -EEXIST;
a874a63e1   Liu Bo   Btrfs: check writ...
1548
  		goto out_drop_write;
16780cabb   Chris Mason   Btrfs: add extra ...
1549
  	}
3de4586c5   Chris Mason   Btrfs: Allow subv...
1550
  	if (subvol) {
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1551
  		ret = btrfs_mksubvol(&file->f_path, name, namelen,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1552
  				     NULL, transid, readonly, inherit);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
1553
  	} else {
2903ff019   Al Viro   switch simple cas...
1554
  		struct fd src = fdget(fd);
3de4586c5   Chris Mason   Btrfs: Allow subv...
1555
  		struct inode *src_inode;
2903ff019   Al Viro   switch simple cas...
1556
  		if (!src.file) {
3de4586c5   Chris Mason   Btrfs: Allow subv...
1557
  			ret = -EINVAL;
a874a63e1   Liu Bo   Btrfs: check writ...
1558
  			goto out_drop_write;
3de4586c5   Chris Mason   Btrfs: Allow subv...
1559
  		}
496ad9aa8   Al Viro   new helper: file_...
1560
1561
  		src_inode = file_inode(src.file);
  		if (src_inode->i_sb != file_inode(file)->i_sb) {
efe120a06   Frank Holton   Btrfs: convert pr...
1562
1563
  			btrfs_info(BTRFS_I(src_inode)->root->fs_info,
  				   "Snapshot src from another FS");
23ad5b17d   Kusanagi Kouichi   btrfs: Return EXD...
1564
  			ret = -EXDEV;
d02420613   David Sterba   btrfs: restrict s...
1565
1566
1567
1568
1569
1570
  		} else if (!inode_owner_or_capable(src_inode)) {
  			/*
  			 * Subvolume creation is not restricted, but snapshots
  			 * are limited to own subvolumes only
  			 */
  			ret = -EPERM;
ecd188159   Al Viro   switch btrfs_ioct...
1571
1572
1573
1574
  		} else {
  			ret = btrfs_mksubvol(&file->f_path, name, namelen,
  					     BTRFS_I(src_inode)->root,
  					     transid, readonly, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
1575
  		}
2903ff019   Al Viro   switch simple cas...
1576
  		fdput(src);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
1577
  	}
a874a63e1   Liu Bo   Btrfs: check writ...
1578
1579
  out_drop_write:
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1580
  out:
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1581
1582
1583
1584
  	return ret;
  }
  
  static noinline int btrfs_ioctl_snap_create(struct file *file,
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1585
  					    void __user *arg, int subvol)
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1586
  {
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1587
  	struct btrfs_ioctl_vol_args *vol_args;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1588
  	int ret;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1589
1590
1591
1592
  	vol_args = memdup_user(arg, sizeof(*vol_args));
  	if (IS_ERR(vol_args))
  		return PTR_ERR(vol_args);
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1593

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1594
  	ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
b83cc9693   Li Zefan   Btrfs: Add readon...
1595
  					      vol_args->fd, subvol,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1596
  					      NULL, false, NULL);
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1597

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1598
1599
1600
  	kfree(vol_args);
  	return ret;
  }
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1601

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1602
1603
1604
1605
1606
1607
1608
  static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
  					       void __user *arg, int subvol)
  {
  	struct btrfs_ioctl_vol_args_v2 *vol_args;
  	int ret;
  	u64 transid = 0;
  	u64 *ptr = NULL;
b83cc9693   Li Zefan   Btrfs: Add readon...
1609
  	bool readonly = false;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1610
  	struct btrfs_qgroup_inherit *inherit = NULL;
75eaa0e22   Sage Weil   Btrfs: fix sync s...
1611

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1612
1613
1614
1615
  	vol_args = memdup_user(arg, sizeof(*vol_args));
  	if (IS_ERR(vol_args))
  		return PTR_ERR(vol_args);
  	vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
75eaa0e22   Sage Weil   Btrfs: fix sync s...
1616

b83cc9693   Li Zefan   Btrfs: Add readon...
1617
  	if (vol_args->flags &
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1618
1619
  	    ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY |
  	      BTRFS_SUBVOL_QGROUP_INHERIT)) {
b83cc9693   Li Zefan   Btrfs: Add readon...
1620
  		ret = -EOPNOTSUPP;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1621
  		goto out;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1622
  	}
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1623
1624
1625
  
  	if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
  		ptr = &transid;
b83cc9693   Li Zefan   Btrfs: Add readon...
1626
1627
  	if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
  		readonly = true;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
  	if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
  		if (vol_args->size > PAGE_CACHE_SIZE) {
  			ret = -EINVAL;
  			goto out;
  		}
  		inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size);
  		if (IS_ERR(inherit)) {
  			ret = PTR_ERR(inherit);
  			goto out;
  		}
  	}
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1639
1640
  
  	ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1641
  					      vol_args->fd, subvol, ptr,
8696c5330   Miao Xie   Btrfs: fix memory...
1642
  					      readonly, inherit);
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1643
1644
1645
1646
1647
1648
  
  	if (ret == 0 && ptr &&
  	    copy_to_user(arg +
  			 offsetof(struct btrfs_ioctl_vol_args_v2,
  				  transid), ptr, sizeof(*ptr)))
  		ret = -EFAULT;
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1649
  out:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1650
  	kfree(vol_args);
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1651
  	kfree(inherit);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1652
1653
  	return ret;
  }
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1654
1655
1656
  static noinline int btrfs_ioctl_subvol_getflags(struct file *file,
  						void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
1657
  	struct inode *inode = file_inode(file);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1658
1659
1660
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret = 0;
  	u64 flags = 0;
33345d015   Li Zefan   Btrfs: Always use...
1661
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID)
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
  		return -EINVAL;
  
  	down_read(&root->fs_info->subvol_sem);
  	if (btrfs_root_readonly(root))
  		flags |= BTRFS_SUBVOL_RDONLY;
  	up_read(&root->fs_info->subvol_sem);
  
  	if (copy_to_user(arg, &flags, sizeof(flags)))
  		ret = -EFAULT;
  
  	return ret;
  }
  
  static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
  					      void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
1678
  	struct inode *inode = file_inode(file);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1679
1680
1681
1682
1683
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
  	u64 root_flags;
  	u64 flags;
  	int ret = 0;
bd60ea0fe   David Sterba   btrfs: call permi...
1684
1685
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
b9ca0664d   Liu Bo   Btrfs: do not set...
1686
1687
1688
  	ret = mnt_want_write_file(file);
  	if (ret)
  		goto out;
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1689

b9ca0664d   Liu Bo   Btrfs: do not set...
1690
1691
1692
1693
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
  		ret = -EINVAL;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1694

b9ca0664d   Liu Bo   Btrfs: do not set...
1695
1696
1697
1698
  	if (copy_from_user(&flags, arg, sizeof(flags))) {
  		ret = -EFAULT;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1699

b9ca0664d   Liu Bo   Btrfs: do not set...
1700
1701
1702
1703
  	if (flags & BTRFS_SUBVOL_CREATE_ASYNC) {
  		ret = -EINVAL;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1704

b9ca0664d   Liu Bo   Btrfs: do not set...
1705
1706
1707
1708
  	if (flags & ~BTRFS_SUBVOL_RDONLY) {
  		ret = -EOPNOTSUPP;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1709
1710
1711
1712
1713
  
  	down_write(&root->fs_info->subvol_sem);
  
  	/* nothing to do */
  	if (!!(flags & BTRFS_SUBVOL_RDONLY) == btrfs_root_readonly(root))
b9ca0664d   Liu Bo   Btrfs: do not set...
1714
  		goto out_drop_sem;
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1715
1716
  
  	root_flags = btrfs_root_flags(&root->root_item);
2c6865378   David Sterba   btrfs: Check read...
1717
  	if (flags & BTRFS_SUBVOL_RDONLY) {
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1718
1719
  		btrfs_set_root_flags(&root->root_item,
  				     root_flags | BTRFS_ROOT_SUBVOL_RDONLY);
2c6865378   David Sterba   btrfs: Check read...
1720
1721
1722
1723
1724
1725
1726
1727
  	} else {
  		/*
  		 * Block RO -> RW transition if this subvolume is involved in
  		 * send
  		 */
  		spin_lock(&root->root_item_lock);
  		if (root->send_in_progress == 0) {
  			btrfs_set_root_flags(&root->root_item,
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1728
  				     root_flags & ~BTRFS_ROOT_SUBVOL_RDONLY);
2c6865378   David Sterba   btrfs: Check read...
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
  			spin_unlock(&root->root_item_lock);
  		} else {
  			spin_unlock(&root->root_item_lock);
  			btrfs_warn(root->fs_info,
  			"Attempt to set subvolume %llu read-write during send",
  					root->root_key.objectid);
  			ret = -EPERM;
  			goto out_drop_sem;
  		}
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1739
1740
1741
1742
1743
1744
  
  	trans = btrfs_start_transaction(root, 1);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_reset;
  	}
b4dc2b8c6   Li Zefan   Btrfs: Fix BTRFS_...
1745
  	ret = btrfs_update_root(trans, root->fs_info->tree_root,
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1746
1747
1748
1749
1750
1751
  				&root->root_key, &root->root_item);
  
  	btrfs_commit_transaction(trans, root);
  out_reset:
  	if (ret)
  		btrfs_set_root_flags(&root->root_item, root_flags);
b9ca0664d   Liu Bo   Btrfs: do not set...
1752
  out_drop_sem:
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1753
  	up_write(&root->fs_info->subvol_sem);
b9ca0664d   Liu Bo   Btrfs: do not set...
1754
1755
1756
  out_drop_write:
  	mnt_drop_write_file(file);
  out:
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1757
1758
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1759
1760
1761
1762
1763
1764
  /*
   * helper to check if the subvolume references other subvolumes
   */
  static noinline int may_destroy_subvol(struct btrfs_root *root)
  {
  	struct btrfs_path *path;
175a2b871   Josef Bacik   Btrfs: don't allo...
1765
  	struct btrfs_dir_item *di;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1766
  	struct btrfs_key key;
175a2b871   Josef Bacik   Btrfs: don't allo...
1767
  	u64 dir_id;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1768
1769
1770
1771
1772
  	int ret;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
175a2b871   Josef Bacik   Btrfs: don't allo...
1773
1774
1775
1776
1777
1778
1779
  	/* Make sure this root isn't set as the default subvol */
  	dir_id = btrfs_super_root_dir(root->fs_info->super_copy);
  	di = btrfs_lookup_dir_item(NULL, root->fs_info->tree_root, path,
  				   dir_id, "default", 7, 0);
  	if (di && !IS_ERR(di)) {
  		btrfs_dir_item_key_to_cpu(path->nodes[0], di, &key);
  		if (key.objectid == root->root_key.objectid) {
72de6b539   Guangyu Sun   Btrfs: return EPE...
1780
1781
1782
  			ret = -EPERM;
  			btrfs_err(root->fs_info, "deleting default subvolume "
  				  "%llu is not allowed", key.objectid);
175a2b871   Josef Bacik   Btrfs: don't allo...
1783
1784
1785
1786
  			goto out;
  		}
  		btrfs_release_path(path);
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
  	key.objectid = root->root_key.objectid;
  	key.type = BTRFS_ROOT_REF_KEY;
  	key.offset = (u64)-1;
  
  	ret = btrfs_search_slot(NULL, root->fs_info->tree_root,
  				&key, path, 0, 0);
  	if (ret < 0)
  		goto out;
  	BUG_ON(ret == 0);
  
  	ret = 0;
  	if (path->slots[0] > 0) {
  		path->slots[0]--;
  		btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
  		if (key.objectid == root->root_key.objectid &&
  		    key.type == BTRFS_ROOT_REF_KEY)
  			ret = -ENOTEMPTY;
  	}
  out:
  	btrfs_free_path(path);
  	return ret;
  }
ac8e9819d   Chris Mason   Btrfs: add search...
1809
1810
1811
  static noinline int key_in_sk(struct btrfs_key *key,
  			      struct btrfs_ioctl_search_key *sk)
  {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1812
1813
1814
1815
1816
1817
1818
1819
1820
  	struct btrfs_key test;
  	int ret;
  
  	test.objectid = sk->min_objectid;
  	test.type = sk->min_type;
  	test.offset = sk->min_offset;
  
  	ret = btrfs_comp_cpu_keys(key, &test);
  	if (ret < 0)
ac8e9819d   Chris Mason   Btrfs: add search...
1821
  		return 0;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1822
1823
1824
1825
1826
1827
1828
  
  	test.objectid = sk->max_objectid;
  	test.type = sk->max_type;
  	test.offset = sk->max_offset;
  
  	ret = btrfs_comp_cpu_keys(key, &test);
  	if (ret > 0)
ac8e9819d   Chris Mason   Btrfs: add search...
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
  		return 0;
  	return 1;
  }
  
  static noinline int copy_to_sk(struct btrfs_root *root,
  			       struct btrfs_path *path,
  			       struct btrfs_key *key,
  			       struct btrfs_ioctl_search_key *sk,
  			       char *buf,
  			       unsigned long *sk_offset,
  			       int *num_found)
  {
  	u64 found_transid;
  	struct extent_buffer *leaf;
  	struct btrfs_ioctl_search_header sh;
  	unsigned long item_off;
  	unsigned long item_len;
  	int nritems;
  	int i;
  	int slot;
ac8e9819d   Chris Mason   Btrfs: add search...
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
  	int ret = 0;
  
  	leaf = path->nodes[0];
  	slot = path->slots[0];
  	nritems = btrfs_header_nritems(leaf);
  
  	if (btrfs_header_generation(leaf) > sk->max_transid) {
  		i = nritems;
  		goto advance_key;
  	}
  	found_transid = btrfs_header_generation(leaf);
  
  	for (i = slot; i < nritems; i++) {
  		item_off = btrfs_item_ptr_offset(leaf, i);
  		item_len = btrfs_item_size_nr(leaf, i);
03b71c6ca   Gabriel de Perthuis   btrfs: don't stop...
1864
1865
1866
1867
1868
  		btrfs_item_key_to_cpu(leaf, key, i);
  		if (!key_in_sk(key, sk))
  			continue;
  
  		if (sizeof(sh) + item_len > BTRFS_SEARCH_ARGS_BUFSIZE)
ac8e9819d   Chris Mason   Btrfs: add search...
1869
1870
1871
1872
1873
1874
1875
  			item_len = 0;
  
  		if (sizeof(sh) + item_len + *sk_offset >
  		    BTRFS_SEARCH_ARGS_BUFSIZE) {
  			ret = 1;
  			goto overflow;
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
  		sh.objectid = key->objectid;
  		sh.offset = key->offset;
  		sh.type = key->type;
  		sh.len = item_len;
  		sh.transid = found_transid;
  
  		/* copy search result header */
  		memcpy(buf + *sk_offset, &sh, sizeof(sh));
  		*sk_offset += sizeof(sh);
  
  		if (item_len) {
  			char *p = buf + *sk_offset;
  			/* copy the item */
  			read_extent_buffer(leaf, p,
  					   item_off, item_len);
  			*sk_offset += item_len;
ac8e9819d   Chris Mason   Btrfs: add search...
1892
  		}
e21568671   Hugo Mills   btrfs: Ensure the...
1893
  		(*num_found)++;
ac8e9819d   Chris Mason   Btrfs: add search...
1894
1895
1896
1897
1898
  
  		if (*num_found >= sk->nr_items)
  			break;
  	}
  advance_key:
abc6e1341   Chris Mason   Btrfs: fix key ch...
1899
1900
  	ret = 0;
  	if (key->offset < (u64)-1 && key->offset < sk->max_offset)
ac8e9819d   Chris Mason   Btrfs: add search...
1901
  		key->offset++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1902
1903
  	else if (key->type < (u8)-1 && key->type < sk->max_type) {
  		key->offset = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1904
  		key->type++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1905
1906
1907
  	} else if (key->objectid < (u64)-1 && key->objectid < sk->max_objectid) {
  		key->offset = 0;
  		key->type = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1908
  		key->objectid++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1909
1910
  	} else
  		ret = 1;
ac8e9819d   Chris Mason   Btrfs: add search...
1911
  overflow:
ac8e9819d   Chris Mason   Btrfs: add search...
1912
1913
1914
1915
1916
1917
1918
1919
  	return ret;
  }
  
  static noinline int search_ioctl(struct inode *inode,
  				 struct btrfs_ioctl_search_args *args)
  {
  	struct btrfs_root *root;
  	struct btrfs_key key;
ac8e9819d   Chris Mason   Btrfs: add search...
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
  	struct btrfs_path *path;
  	struct btrfs_ioctl_search_key *sk = &args->key;
  	struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info;
  	int ret;
  	int num_found = 0;
  	unsigned long sk_offset = 0;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  
  	if (sk->tree_id == 0) {
  		/* search the root of the inode that was passed */
  		root = BTRFS_I(inode)->root;
  	} else {
  		key.objectid = sk->tree_id;
  		key.type = BTRFS_ROOT_ITEM_KEY;
  		key.offset = (u64)-1;
  		root = btrfs_read_fs_root_no_name(info, &key);
  		if (IS_ERR(root)) {
efe120a06   Frank Holton   Btrfs: convert pr...
1940
1941
  			printk(KERN_ERR "BTRFS: could not find root %llu
  ",
ac8e9819d   Chris Mason   Btrfs: add search...
1942
1943
1944
1945
1946
1947
1948
1949
1950
  			       sk->tree_id);
  			btrfs_free_path(path);
  			return -ENOENT;
  		}
  	}
  
  	key.objectid = sk->min_objectid;
  	key.type = sk->min_type;
  	key.offset = sk->min_offset;
ac8e9819d   Chris Mason   Btrfs: add search...
1951
  	path->keep_locks = 1;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
1952
  	while (1) {
6174d3cb4   Filipe David Borba Manana   Btrfs: remove unu...
1953
  		ret = btrfs_search_forward(root, &key, path, sk->min_transid);
ac8e9819d   Chris Mason   Btrfs: add search...
1954
1955
1956
1957
1958
1959
1960
  		if (ret != 0) {
  			if (ret > 0)
  				ret = 0;
  			goto err;
  		}
  		ret = copy_to_sk(root, path, &key, sk, args->buf,
  				 &sk_offset, &num_found);
b3b4aa74b   David Sterba   btrfs: drop unuse...
1961
  		btrfs_release_path(path);
ac8e9819d   Chris Mason   Btrfs: add search...
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
  		if (ret || num_found >= sk->nr_items)
  			break;
  
  	}
  	ret = 0;
  err:
  	sk->nr_items = num_found;
  	btrfs_free_path(path);
  	return ret;
  }
  
  static noinline int btrfs_ioctl_tree_search(struct file *file,
  					   void __user *argp)
  {
  	 struct btrfs_ioctl_search_args *args;
  	 struct inode *inode;
  	 int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
2354d08fe   Julia Lawall   Btrfs: use memdup...
1982
1983
1984
  	args = memdup_user(argp, sizeof(*args));
  	if (IS_ERR(args))
  		return PTR_ERR(args);
ac8e9819d   Chris Mason   Btrfs: add search...
1985

496ad9aa8   Al Viro   new helper: file_...
1986
  	inode = file_inode(file);
ac8e9819d   Chris Mason   Btrfs: add search...
1987
1988
1989
1990
1991
1992
  	ret = search_ioctl(inode, args);
  	if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
  		ret = -EFAULT;
  	kfree(args);
  	return ret;
  }
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1993
  /*
ac8e9819d   Chris Mason   Btrfs: add search...
1994
1995
1996
   * Search INODE_REFs to identify path name of 'dirid' directory
   * in a 'tree_id' tree. and sets path name to 'name'.
   */
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1997
1998
1999
2000
2001
  static noinline int btrfs_search_path_in_tree(struct btrfs_fs_info *info,
  				u64 tree_id, u64 dirid, char *name)
  {
  	struct btrfs_root *root;
  	struct btrfs_key key;
ac8e9819d   Chris Mason   Btrfs: add search...
2002
  	char *ptr;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
  	int ret = -1;
  	int slot;
  	int len;
  	int total_len = 0;
  	struct btrfs_inode_ref *iref;
  	struct extent_buffer *l;
  	struct btrfs_path *path;
  
  	if (dirid == BTRFS_FIRST_FREE_OBJECTID) {
  		name[0]='\0';
  		return 0;
  	}
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
ac8e9819d   Chris Mason   Btrfs: add search...
2019
  	ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX];
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2020
2021
2022
2023
2024
2025
  
  	key.objectid = tree_id;
  	key.type = BTRFS_ROOT_ITEM_KEY;
  	key.offset = (u64)-1;
  	root = btrfs_read_fs_root_no_name(info, &key);
  	if (IS_ERR(root)) {
efe120a06   Frank Holton   Btrfs: convert pr...
2026
2027
  		printk(KERN_ERR "BTRFS: could not find root %llu
  ", tree_id);
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2028
2029
  		ret = -ENOENT;
  		goto out;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2030
2031
2032
2033
  	}
  
  	key.objectid = dirid;
  	key.type = BTRFS_INODE_REF_KEY;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2034
  	key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2035

678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2036
  	while (1) {
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2037
2038
2039
  		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  		if (ret < 0)
  			goto out;
18674c6cc   Filipe David Borba Manana   Btrfs: don't miss...
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
  		else if (ret > 0) {
  			ret = btrfs_previous_item(root, path, dirid,
  						  BTRFS_INODE_REF_KEY);
  			if (ret < 0)
  				goto out;
  			else if (ret > 0) {
  				ret = -ENOENT;
  				goto out;
  			}
  		}
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2050
2051
2052
2053
  
  		l = path->nodes[0];
  		slot = path->slots[0];
  		btrfs_item_key_to_cpu(l, &key, slot);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2054
2055
2056
2057
  		iref = btrfs_item_ptr(l, slot, struct btrfs_inode_ref);
  		len = btrfs_inode_ref_name_len(l, iref);
  		ptr -= len + 1;
  		total_len += len + 1;
a696cf352   Filipe David Borba Manana   Btrfs: add missin...
2058
2059
  		if (ptr < name) {
  			ret = -ENAMETOOLONG;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2060
  			goto out;
a696cf352   Filipe David Borba Manana   Btrfs: add missin...
2061
  		}
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2062
2063
  
  		*(ptr + len) = '/';
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2064
  		read_extent_buffer(l, ptr, (unsigned long)(iref + 1), len);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2065
2066
2067
  
  		if (key.offset == BTRFS_FIRST_FREE_OBJECTID)
  			break;
b3b4aa74b   David Sterba   btrfs: drop unuse...
2068
  		btrfs_release_path(path);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2069
  		key.objectid = key.offset;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2070
  		key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2071
  		dirid = key.objectid;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2072
  	}
77906a507   Li Zefan   Btrfs: copy strin...
2073
  	memmove(name, ptr, total_len);
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2074
  	name[total_len] = '\0';
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2075
2076
2077
  	ret = 0;
  out:
  	btrfs_free_path(path);
ac8e9819d   Chris Mason   Btrfs: add search...
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
  	return ret;
  }
  
  static noinline int btrfs_ioctl_ino_lookup(struct file *file,
  					   void __user *argp)
  {
  	 struct btrfs_ioctl_ino_lookup_args *args;
  	 struct inode *inode;
  	 int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
2354d08fe   Julia Lawall   Btrfs: use memdup...
2090
2091
2092
  	args = memdup_user(argp, sizeof(*args));
  	if (IS_ERR(args))
  		return PTR_ERR(args);
c2b96929e   Dan Carpenter   Btrfs: handle kma...
2093

496ad9aa8   Al Viro   new helper: file_...
2094
  	inode = file_inode(file);
ac8e9819d   Chris Mason   Btrfs: add search...
2095

1b53ac4d1   Chris Mason   Btrfs: allow tree...
2096
2097
  	if (args->treeid == 0)
  		args->treeid = BTRFS_I(inode)->root->root_key.objectid;
ac8e9819d   Chris Mason   Btrfs: add search...
2098
2099
2100
2101
2102
2103
2104
2105
  	ret = btrfs_search_path_in_tree(BTRFS_I(inode)->root->fs_info,
  					args->treeid, args->objectid,
  					args->name);
  
  	if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
  		ret = -EFAULT;
  
  	kfree(args);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2106
2107
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2108
2109
2110
  static noinline int btrfs_ioctl_snap_destroy(struct file *file,
  					     void __user *arg)
  {
54563d41a   Al Viro   btrfs: get rid of...
2111
  	struct dentry *parent = file->f_path.dentry;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2112
2113
2114
2115
2116
2117
2118
  	struct dentry *dentry;
  	struct inode *dir = parent->d_inode;
  	struct inode *inode;
  	struct btrfs_root *root = BTRFS_I(dir)->root;
  	struct btrfs_root *dest = NULL;
  	struct btrfs_ioctl_vol_args *vol_args;
  	struct btrfs_trans_handle *trans;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2119
2120
  	struct btrfs_block_rsv block_rsv;
  	u64 qgroup_reserved;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2121
2122
2123
  	int namelen;
  	int ret;
  	int err = 0;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
  	vol_args = memdup_user(arg, sizeof(*vol_args));
  	if (IS_ERR(vol_args))
  		return PTR_ERR(vol_args);
  
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
  	namelen = strlen(vol_args->name);
  	if (strchr(vol_args->name, '/') ||
  	    strncmp(vol_args->name, "..", namelen) == 0) {
  		err = -EINVAL;
  		goto out;
  	}
a561be710   Al Viro   switch a bunch of...
2135
  	err = mnt_want_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2136
2137
  	if (err)
  		goto out;
5c50c9b89   David Sterba   btrfs: make subvo...
2138
2139
  	err = mutex_lock_killable_nested(&dir->i_mutex, I_MUTEX_PARENT);
  	if (err == -EINTR)
e43f998e4   David Sterba   btrfs: call mnt_d...
2140
  		goto out_drop_write;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
  	dentry = lookup_one_len(vol_args->name, parent, namelen);
  	if (IS_ERR(dentry)) {
  		err = PTR_ERR(dentry);
  		goto out_unlock_dir;
  	}
  
  	if (!dentry->d_inode) {
  		err = -ENOENT;
  		goto out_dput;
  	}
  
  	inode = dentry->d_inode;
4260f7c75   Sage Weil   Btrfs: allow subv...
2153
  	dest = BTRFS_I(inode)->root;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2154
  	if (!capable(CAP_SYS_ADMIN)) {
4260f7c75   Sage Weil   Btrfs: allow subv...
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
  		/*
  		 * Regular user.  Only allow this with a special mount
  		 * option, when the user has write+exec access to the
  		 * subvol root, and when rmdir(2) would have been
  		 * allowed.
  		 *
  		 * Note that this is _not_ check that the subvol is
  		 * empty or doesn't contain data that we wouldn't
  		 * otherwise be able to delete.
  		 *
  		 * Users who want to delete empty subvols should try
  		 * rmdir(2).
  		 */
  		err = -EPERM;
  		if (!btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED))
  			goto out_dput;
  
  		/*
  		 * Do not allow deletion if the parent dir is the same
  		 * as the dir to be deleted.  That means the ioctl
  		 * must be called on the dentry referencing the root
  		 * of the subvol, not a random directory contained
  		 * within it.
  		 */
  		err = -EINVAL;
  		if (root == dest)
  			goto out_dput;
  
  		err = inode_permission(inode, MAY_WRITE | MAY_EXEC);
  		if (err)
  			goto out_dput;
4260f7c75   Sage Weil   Btrfs: allow subv...
2186
  	}
5c39da5b6   Miao Xie   Btrfs: do not del...
2187
2188
2189
2190
  	/* check if subvolume may be deleted by a user */
  	err = btrfs_may_delete(dir, dentry, 1);
  	if (err)
  		goto out_dput;
33345d015   Li Zefan   Btrfs: Always use...
2191
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2192
2193
2194
  		err = -EINVAL;
  		goto out_dput;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
  	mutex_lock(&inode->i_mutex);
  	err = d_invalidate(dentry);
  	if (err)
  		goto out_unlock;
  
  	down_write(&root->fs_info->subvol_sem);
  
  	err = may_destroy_subvol(dest);
  	if (err)
  		goto out_up_write;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2205
2206
2207
2208
2209
2210
  	btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
  	/*
  	 * One for dir inode, two for dir entries, two for root
  	 * ref/backref.
  	 */
  	err = btrfs_subvolume_reserve_metadata(root, &block_rsv,
ee3441b49   Jeff Mahoney   btrfs: fall back ...
2211
  					       5, &qgroup_reserved, true);
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2212
2213
  	if (err)
  		goto out_up_write;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2214
2215
2216
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		err = PTR_ERR(trans);
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2217
  		goto out_release;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2218
  	}
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2219
2220
  	trans->block_rsv = &block_rsv;
  	trans->bytes_reserved = block_rsv.size;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2221

76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2222
2223
2224
2225
  	ret = btrfs_unlink_subvol(trans, root, dir,
  				dest->root_key.objectid,
  				dentry->d_name.name,
  				dentry->d_name.len);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2226
2227
2228
2229
2230
  	if (ret) {
  		err = ret;
  		btrfs_abort_transaction(trans, root, ret);
  		goto out_end_trans;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2231
2232
2233
2234
2235
2236
2237
  
  	btrfs_record_root_in_trans(trans, dest);
  
  	memset(&dest->root_item.drop_progress, 0,
  		sizeof(dest->root_item.drop_progress));
  	dest->root_item.drop_level = 0;
  	btrfs_set_root_refs(&dest->root_item, 0);
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
2238
2239
2240
2241
  	if (!xchg(&dest->orphan_item_inserted, 1)) {
  		ret = btrfs_insert_orphan_item(trans,
  					root->fs_info->tree_root,
  					dest->root_key.objectid);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2242
2243
2244
2245
2246
  		if (ret) {
  			btrfs_abort_transaction(trans, root, ret);
  			err = ret;
  			goto out_end_trans;
  		}
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
2247
  	}
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
  
  	ret = btrfs_uuid_tree_rem(trans, root->fs_info->uuid_root,
  				  dest->root_item.uuid, BTRFS_UUID_KEY_SUBVOL,
  				  dest->root_key.objectid);
  	if (ret && ret != -ENOENT) {
  		btrfs_abort_transaction(trans, root, ret);
  		err = ret;
  		goto out_end_trans;
  	}
  	if (!btrfs_is_empty_uuid(dest->root_item.received_uuid)) {
  		ret = btrfs_uuid_tree_rem(trans, root->fs_info->uuid_root,
  					  dest->root_item.received_uuid,
  					  BTRFS_UUID_KEY_RECEIVED_SUBVOL,
  					  dest->root_key.objectid);
  		if (ret && ret != -ENOENT) {
  			btrfs_abort_transaction(trans, root, ret);
  			err = ret;
  			goto out_end_trans;
  		}
  	}
79787eaab   Jeff Mahoney   btrfs: replace ma...
2268
  out_end_trans:
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2269
2270
  	trans->block_rsv = NULL;
  	trans->bytes_reserved = 0;
531cb13f1   Sage Weil   Btrfs: make SNAP_...
2271
  	ret = btrfs_end_transaction(trans, root);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2272
2273
  	if (ret && !err)
  		err = ret;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2274
  	inode->i_flags |= S_DEAD;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2275
2276
  out_release:
  	btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2277
2278
2279
2280
2281
  out_up_write:
  	up_write(&root->fs_info->subvol_sem);
  out_unlock:
  	mutex_unlock(&inode->i_mutex);
  	if (!err) {
efefb1438   Yan, Zheng   Btrfs: remove neg...
2282
  		shrink_dcache_sb(root->fs_info->sb);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2283
2284
  		btrfs_invalidate_inodes(dest);
  		d_delete(dentry);
fa6ac8765   Liu Bo   Btrfs: fix cleane...
2285
2286
2287
2288
2289
2290
  
  		/* the last ref */
  		if (dest->cache_inode) {
  			iput(dest->cache_inode);
  			dest->cache_inode = NULL;
  		}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2291
2292
2293
2294
2295
  	}
  out_dput:
  	dput(dentry);
  out_unlock_dir:
  	mutex_unlock(&dir->i_mutex);
e43f998e4   David Sterba   btrfs: call mnt_d...
2296
  out_drop_write:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
2297
  	mnt_drop_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2298
2299
2300
2301
  out:
  	kfree(vol_args);
  	return err;
  }
1e701a329   Chris Mason   Btrfs: add new de...
2302
  static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2303
  {
496ad9aa8   Al Viro   new helper: file_...
2304
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2305
  	struct btrfs_root *root = BTRFS_I(inode)->root;
1e701a329   Chris Mason   Btrfs: add new de...
2306
  	struct btrfs_ioctl_defrag_range_args *range;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2307
  	int ret;
25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2308
2309
2310
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
b83cc9693   Li Zefan   Btrfs: Add readon...
2311

25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2312
2313
2314
  	if (btrfs_root_readonly(root)) {
  		ret = -EROFS;
  		goto out;
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2315
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2316
2317
2318
  
  	switch (inode->i_mode & S_IFMT) {
  	case S_IFDIR:
e441d54de   Chris Mason   Btrfs: add permis...
2319
2320
2321
2322
  		if (!capable(CAP_SYS_ADMIN)) {
  			ret = -EPERM;
  			goto out;
  		}
de78b51a2   Eric Sandeen   btrfs: remove cac...
2323
  		ret = btrfs_defrag_root(root);
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
2324
2325
  		if (ret)
  			goto out;
de78b51a2   Eric Sandeen   btrfs: remove cac...
2326
  		ret = btrfs_defrag_root(root->fs_info->extent_root);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2327
2328
  		break;
  	case S_IFREG:
e441d54de   Chris Mason   Btrfs: add permis...
2329
2330
2331
2332
  		if (!(file->f_mode & FMODE_WRITE)) {
  			ret = -EINVAL;
  			goto out;
  		}
1e701a329   Chris Mason   Btrfs: add new de...
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
  
  		range = kzalloc(sizeof(*range), GFP_KERNEL);
  		if (!range) {
  			ret = -ENOMEM;
  			goto out;
  		}
  
  		if (argp) {
  			if (copy_from_user(range, argp,
  					   sizeof(*range))) {
  				ret = -EFAULT;
  				kfree(range);
683be16eb   Dan Carpenter   Btrfs: dereferenc...
2345
  				goto out;
1e701a329   Chris Mason   Btrfs: add new de...
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
  			}
  			/* compression requires us to start the IO */
  			if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) {
  				range->flags |= BTRFS_DEFRAG_RANGE_START_IO;
  				range->extent_thresh = (u32)-1;
  			}
  		} else {
  			/* the rest are all set to zero by kzalloc */
  			range->len = (u64)-1;
  		}
496ad9aa8   Al Viro   new helper: file_...
2356
  		ret = btrfs_defrag_file(file_inode(file), file,
4cb5300bc   Chris Mason   Btrfs: add mount ...
2357
2358
2359
  					range, 0, 0);
  		if (ret > 0)
  			ret = 0;
1e701a329   Chris Mason   Btrfs: add new de...
2360
  		kfree(range);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2361
  		break;
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
2362
2363
  	default:
  		ret = -EINVAL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2364
  	}
e441d54de   Chris Mason   Btrfs: add permis...
2365
  out:
25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2366
  	mnt_drop_write_file(file);
e441d54de   Chris Mason   Btrfs: add permis...
2367
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2368
  }
b2950863c   Christoph Hellwig   Btrfs: make thing...
2369
  static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2370
2371
2372
  {
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2373
2374
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2375
2376
  	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
e57138b3e   Anand Jain   btrfs: return btr...
2377
  		return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2378
  	}
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2379
  	mutex_lock(&root->fs_info->volume_mutex);
dae7b665c   Li Zefan   btrfs: use memdup...
2380
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2381
2382
2383
2384
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
  		goto out;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2385

5516e5957   Mark Fasheh   Btrfs: Null termi...
2386
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2387
  	ret = btrfs_init_new_device(root, vol_args->name);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2388
  	kfree(vol_args);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2389
2390
  out:
  	mutex_unlock(&root->fs_info->volume_mutex);
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2391
  	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2392
2393
  	return ret;
  }
da24927b1   Miao Xie   Btrfs: get write ...
2394
  static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2395
  {
496ad9aa8   Al Viro   new helper: file_...
2396
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2397
2398
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2399
2400
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
da24927b1   Miao Xie   Btrfs: get write ...
2401
2402
2403
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2404

dae7b665c   Li Zefan   btrfs: use memdup...
2405
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2406
2407
2408
2409
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
  		goto out;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2410

5516e5957   Mark Fasheh   Btrfs: Null termi...
2411
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2412

183860f6a   Anand Jain   btrfs: device del...
2413
2414
2415
2416
2417
2418
2419
2420
  	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
  		ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
  		goto out;
  	}
  
  	mutex_lock(&root->fs_info->volume_mutex);
  	ret = btrfs_rm_device(root, vol_args->name);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2421
  	mutex_unlock(&root->fs_info->volume_mutex);
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2422
  	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
183860f6a   Anand Jain   btrfs: device del...
2423
2424
2425
  
  out:
  	kfree(vol_args);
4ac20c70b   Ilya Dryomov   Btrfs: fix unlock...
2426
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2427
2428
  	return ret;
  }
475f63874   Jan Schmidt   btrfs: new ioctls...
2429
2430
  static long btrfs_ioctl_fs_info(struct btrfs_root *root, void __user *arg)
  {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2431
  	struct btrfs_ioctl_fs_info_args *fi_args;
475f63874   Jan Schmidt   btrfs: new ioctls...
2432
2433
2434
  	struct btrfs_device *device;
  	struct btrfs_device *next;
  	struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
027ed2f00   Li Zefan   Btrfs: avoid stac...
2435
  	int ret = 0;
475f63874   Jan Schmidt   btrfs: new ioctls...
2436
2437
2438
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
027ed2f00   Li Zefan   Btrfs: avoid stac...
2439
2440
2441
  	fi_args = kzalloc(sizeof(*fi_args), GFP_KERNEL);
  	if (!fi_args)
  		return -ENOMEM;
f71717502   Filipe David Borba Manana   Btrfs: fix race c...
2442
  	mutex_lock(&fs_devices->device_list_mutex);
027ed2f00   Li Zefan   Btrfs: avoid stac...
2443
2444
  	fi_args->num_devices = fs_devices->num_devices;
  	memcpy(&fi_args->fsid, root->fs_info->fsid, sizeof(fi_args->fsid));
475f63874   Jan Schmidt   btrfs: new ioctls...
2445

475f63874   Jan Schmidt   btrfs: new ioctls...
2446
  	list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2447
2448
  		if (device->devid > fi_args->max_id)
  			fi_args->max_id = device->devid;
475f63874   Jan Schmidt   btrfs: new ioctls...
2449
2450
  	}
  	mutex_unlock(&fs_devices->device_list_mutex);
027ed2f00   Li Zefan   Btrfs: avoid stac...
2451
2452
  	if (copy_to_user(arg, fi_args, sizeof(*fi_args)))
  		ret = -EFAULT;
475f63874   Jan Schmidt   btrfs: new ioctls...
2453

027ed2f00   Li Zefan   Btrfs: avoid stac...
2454
2455
  	kfree(fi_args);
  	return ret;
475f63874   Jan Schmidt   btrfs: new ioctls...
2456
2457
2458
2459
2460
2461
2462
2463
2464
  }
  
  static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg)
  {
  	struct btrfs_ioctl_dev_info_args *di_args;
  	struct btrfs_device *dev;
  	struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
  	int ret = 0;
  	char *s_uuid = NULL;
475f63874   Jan Schmidt   btrfs: new ioctls...
2465
2466
2467
2468
2469
2470
2471
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	di_args = memdup_user(arg, sizeof(*di_args));
  	if (IS_ERR(di_args))
  		return PTR_ERR(di_args);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2472
  	if (!btrfs_is_empty_uuid(di_args->uuid))
475f63874   Jan Schmidt   btrfs: new ioctls...
2473
2474
2475
  		s_uuid = di_args->uuid;
  
  	mutex_lock(&fs_devices->device_list_mutex);
aa1b8cd40   Stefan Behrens   Btrfs: pass fs_in...
2476
  	dev = btrfs_find_device(root->fs_info, di_args->devid, s_uuid, NULL);
475f63874   Jan Schmidt   btrfs: new ioctls...
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
  
  	if (!dev) {
  		ret = -ENODEV;
  		goto out;
  	}
  
  	di_args->devid = dev->devid;
  	di_args->bytes_used = dev->bytes_used;
  	di_args->total_bytes = dev->total_bytes;
  	memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
a27202fbe   Jim Meyering   Btrfs: NUL-termin...
2487
  	if (dev->name) {
606686eea   Josef Bacik   Btrfs: use rcu to...
2488
2489
2490
2491
2492
2493
  		struct rcu_string *name;
  
  		rcu_read_lock();
  		name = rcu_dereference(dev->name);
  		strncpy(di_args->path, name->str, sizeof(di_args->path));
  		rcu_read_unlock();
a27202fbe   Jim Meyering   Btrfs: NUL-termin...
2494
2495
  		di_args->path[sizeof(di_args->path) - 1] = 0;
  	} else {
99ba55ad6   Stefan Behrens   Btrfs: fix btrfs_...
2496
  		di_args->path[0] = '\0';
a27202fbe   Jim Meyering   Btrfs: NUL-termin...
2497
  	}
475f63874   Jan Schmidt   btrfs: new ioctls...
2498
2499
  
  out:
55793c0d0   David Sterba   btrfs: read entir...
2500
  	mutex_unlock(&fs_devices->device_list_mutex);
475f63874   Jan Schmidt   btrfs: new ioctls...
2501
2502
2503
2504
2505
2506
  	if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args)))
  		ret = -EFAULT;
  
  	kfree(di_args);
  	return ret;
  }
416161db9   Mark Fasheh   btrfs: offline de...
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
  static struct page *extent_same_get_page(struct inode *inode, u64 off)
  {
  	struct page *page;
  	pgoff_t index;
  	struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
  
  	index = off >> PAGE_CACHE_SHIFT;
  
  	page = grab_cache_page(inode->i_mapping, index);
  	if (!page)
  		return NULL;
  
  	if (!PageUptodate(page)) {
  		if (extent_read_full_page_nolock(tree, page, btrfs_get_extent,
  						 0))
  			return NULL;
  		lock_page(page);
  		if (!PageUptodate(page)) {
  			unlock_page(page);
  			page_cache_release(page);
  			return NULL;
  		}
  	}
  	unlock_page(page);
  
  	return page;
  }
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
  static inline void lock_extent_range(struct inode *inode, u64 off, u64 len)
  {
  	/* do any pending delalloc/csum calc on src, one way or
  	   another, and lock file content */
  	while (1) {
  		struct btrfs_ordered_extent *ordered;
  		lock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
  		ordered = btrfs_lookup_first_ordered_extent(inode,
  							    off + len - 1);
  		if (!ordered &&
  		    !test_range_bit(&BTRFS_I(inode)->io_tree, off,
  				    off + len - 1, EXTENT_DELALLOC, 0, NULL))
  			break;
  		unlock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
  		if (ordered)
  			btrfs_put_ordered_extent(ordered);
  		btrfs_wait_ordered_range(inode, off, len);
  	}
  }
416161db9   Mark Fasheh   btrfs: offline de...
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
  static void btrfs_double_unlock(struct inode *inode1, u64 loff1,
  				struct inode *inode2, u64 loff2, u64 len)
  {
  	unlock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1);
  	unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1);
  
  	mutex_unlock(&inode1->i_mutex);
  	mutex_unlock(&inode2->i_mutex);
  }
  
  static void btrfs_double_lock(struct inode *inode1, u64 loff1,
  			      struct inode *inode2, u64 loff2, u64 len)
  {
  	if (inode1 < inode2) {
  		swap(inode1, inode2);
  		swap(loff1, loff2);
  	}
  
  	mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT);
  	lock_extent_range(inode1, loff1, len);
  	if (inode1 != inode2) {
  		mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
  		lock_extent_range(inode2, loff2, len);
  	}
  }
  
  static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst,
  			  u64 dst_loff, u64 len)
  {
  	int ret = 0;
  	struct page *src_page, *dst_page;
  	unsigned int cmp_len = PAGE_CACHE_SIZE;
  	void *addr, *dst_addr;
  
  	while (len) {
  		if (len < PAGE_CACHE_SIZE)
  			cmp_len = len;
  
  		src_page = extent_same_get_page(src, loff);
  		if (!src_page)
  			return -EINVAL;
  		dst_page = extent_same_get_page(dst, dst_loff);
  		if (!dst_page) {
  			page_cache_release(src_page);
  			return -EINVAL;
  		}
  		addr = kmap_atomic(src_page);
  		dst_addr = kmap_atomic(dst_page);
  
  		flush_dcache_page(src_page);
  		flush_dcache_page(dst_page);
  
  		if (memcmp(addr, dst_addr, cmp_len))
  			ret = BTRFS_SAME_DATA_DIFFERS;
  
  		kunmap_atomic(addr);
  		kunmap_atomic(dst_addr);
  		page_cache_release(src_page);
  		page_cache_release(dst_page);
  
  		if (ret)
  			break;
  
  		loff += cmp_len;
  		dst_loff += cmp_len;
  		len -= cmp_len;
  	}
  
  	return ret;
  }
  
  static int extent_same_check_offsets(struct inode *inode, u64 off, u64 len)
  {
  	u64 bs = BTRFS_I(inode)->root->fs_info->sb->s_blocksize;
  
  	if (off + len > inode->i_size || off + len < off)
  		return -EINVAL;
  	/* Check that we are block aligned - btrfs_clone() requires this */
  	if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs))
  		return -EINVAL;
  
  	return 0;
  }
  
  static int btrfs_extent_same(struct inode *src, u64 loff, u64 len,
  			     struct inode *dst, u64 dst_loff)
  {
  	int ret;
  
  	/*
  	 * btrfs_clone() can't handle extents in the same file
  	 * yet. Once that works, we can drop this check and replace it
  	 * with a check for the same inode, but overlapping extents.
  	 */
  	if (src == dst)
  		return -EINVAL;
  
  	btrfs_double_lock(src, loff, dst, dst_loff, len);
  
  	ret = extent_same_check_offsets(src, loff, len);
  	if (ret)
  		goto out_unlock;
  
  	ret = extent_same_check_offsets(dst, dst_loff, len);
  	if (ret)
  		goto out_unlock;
  
  	/* don't make the dst file partly checksummed */
  	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
  	    (BTRFS_I(dst)->flags & BTRFS_INODE_NODATASUM)) {
  		ret = -EINVAL;
  		goto out_unlock;
  	}
  
  	ret = btrfs_cmp_data(src, loff, dst, dst_loff, len);
  	if (ret == 0)
  		ret = btrfs_clone(src, dst, loff, len, len, dst_loff);
  
  out_unlock:
  	btrfs_double_unlock(src, loff, dst, dst_loff, len);
  
  	return ret;
  }
  
  #define BTRFS_MAX_DEDUPE_LEN	(16 * 1024 * 1024)
  
  static long btrfs_ioctl_file_extent_same(struct file *file,
1c1c8747c   Al Viro   btrfs: sanitize B...
2680
  			struct btrfs_ioctl_same_args __user *argp)
416161db9   Mark Fasheh   btrfs: offline de...
2681
  {
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2682
2683
  	struct btrfs_ioctl_same_args *same;
  	struct btrfs_ioctl_same_extent_info *info;
1c1c8747c   Al Viro   btrfs: sanitize B...
2684
  	struct inode *src = file_inode(file);
416161db9   Mark Fasheh   btrfs: offline de...
2685
2686
2687
2688
  	u64 off;
  	u64 len;
  	int i;
  	int ret;
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2689
  	unsigned long size;
416161db9   Mark Fasheh   btrfs: offline de...
2690
2691
  	u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
  	bool is_admin = capable(CAP_SYS_ADMIN);
1c1c8747c   Al Viro   btrfs: sanitize B...
2692
  	u16 count;
416161db9   Mark Fasheh   btrfs: offline de...
2693
2694
2695
2696
2697
2698
2699
  
  	if (!(file->f_mode & FMODE_READ))
  		return -EINVAL;
  
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
1c1c8747c   Al Viro   btrfs: sanitize B...
2700
  	if (get_user(count, &argp->dest_count)) {
416161db9   Mark Fasheh   btrfs: offline de...
2701
2702
2703
  		ret = -EFAULT;
  		goto out;
  	}
1c1c8747c   Al Viro   btrfs: sanitize B...
2704
  	size = offsetof(struct btrfs_ioctl_same_args __user, info[count]);
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2705

1c1c8747c   Al Viro   btrfs: sanitize B...
2706
  	same = memdup_user(argp, size);
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2707

229eed434   Geyslan G. Bem   btrfs: simplify k...
2708
2709
  	if (IS_ERR(same)) {
  		ret = PTR_ERR(same);
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2710
2711
2712
2713
2714
  		goto out;
  	}
  
  	off = same->logical_offset;
  	len = same->length;
416161db9   Mark Fasheh   btrfs: offline de...
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
  
  	/*
  	 * Limit the total length we will dedupe for each operation.
  	 * This is intended to bound the total time spent in this
  	 * ioctl to something sane.
  	 */
  	if (len > BTRFS_MAX_DEDUPE_LEN)
  		len = BTRFS_MAX_DEDUPE_LEN;
  
  	if (WARN_ON_ONCE(bs < PAGE_CACHE_SIZE)) {
  		/*
  		 * Btrfs does not support blocksize < page_size. As a
  		 * result, btrfs_cmp_data() won't correctly handle
  		 * this situation without an update.
  		 */
  		ret = -EINVAL;
  		goto out;
  	}
  
  	ret = -EISDIR;
  	if (S_ISDIR(src->i_mode))
  		goto out;
  
  	ret = -EACCES;
  	if (!S_ISREG(src->i_mode))
  		goto out;
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2741
  	/* pre-format output fields to sane values */
1c1c8747c   Al Viro   btrfs: sanitize B...
2742
  	for (i = 0; i < count; i++) {
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2743
2744
2745
  		same->info[i].bytes_deduped = 0ULL;
  		same->info[i].status = 0;
  	}
416161db9   Mark Fasheh   btrfs: offline de...
2746

1c1c8747c   Al Viro   btrfs: sanitize B...
2747
2748
2749
2750
  	for (i = 0, info = same->info; i < count; i++, info++) {
  		struct inode *dst;
  		struct fd dst_file = fdget(info->fd);
  		if (!dst_file.file) {
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2751
  			info->status = -EBADF;
1c1c8747c   Al Viro   btrfs: sanitize B...
2752
  			continue;
416161db9   Mark Fasheh   btrfs: offline de...
2753
  		}
1c1c8747c   Al Viro   btrfs: sanitize B...
2754
  		dst = file_inode(dst_file.file);
416161db9   Mark Fasheh   btrfs: offline de...
2755

1c1c8747c   Al Viro   btrfs: sanitize B...
2756
  		if (!(is_admin || (dst_file.file->f_mode & FMODE_WRITE))) {
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2757
  			info->status = -EINVAL;
1c1c8747c   Al Viro   btrfs: sanitize B...
2758
2759
2760
  		} else if (file->f_path.mnt != dst_file.file->f_path.mnt) {
  			info->status = -EXDEV;
  		} else if (S_ISDIR(dst->i_mode)) {
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2761
  			info->status = -EISDIR;
1c1c8747c   Al Viro   btrfs: sanitize B...
2762
  		} else if (!S_ISREG(dst->i_mode)) {
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2763
  			info->status = -EACCES;
1c1c8747c   Al Viro   btrfs: sanitize B...
2764
2765
2766
2767
2768
  		} else {
  			info->status = btrfs_extent_same(src, off, len, dst,
  							info->logical_offset);
  			if (info->status == 0)
  				info->bytes_deduped += len;
416161db9   Mark Fasheh   btrfs: offline de...
2769
  		}
1c1c8747c   Al Viro   btrfs: sanitize B...
2770
  		fdput(dst_file);
416161db9   Mark Fasheh   btrfs: offline de...
2771
  	}
cbf8b8ca3   Mark Fasheh   btrfs: change ext...
2772
2773
2774
  	ret = copy_to_user(argp, same, size);
  	if (ret)
  		ret = -EFAULT;
416161db9   Mark Fasheh   btrfs: offline de...
2775
2776
2777
2778
  out:
  	mnt_drop_write_file(file);
  	return ret;
  }
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
  /**
   * btrfs_clone() - clone a range from inode file to another
   *
   * @src: Inode to clone from
   * @inode: Inode to clone to
   * @off: Offset within source to start clone from
   * @olen: Original length, passed by user, of range to clone
   * @olen_aligned: Block-aligned value of olen, extent_same uses
   *               identical values here
   * @destoff: Offset within @inode to start clone
   */
  static int btrfs_clone(struct inode *src, struct inode *inode,
  		       u64 off, u64 olen, u64 olen_aligned, u64 destoff)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2792
  {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2793
  	struct btrfs_root *root = BTRFS_I(inode)->root;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
2794
  	struct btrfs_path *path = NULL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2795
  	struct extent_buffer *leaf;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
2796
2797
  	struct btrfs_trans_handle *trans;
  	char *buf = NULL;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2798
  	struct btrfs_key key;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2799
2800
  	u32 nritems;
  	int slot;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2801
  	int ret;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
2802
  	u64 len = olen_aligned;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2803
2804
2805
2806
  
  	ret = -ENOMEM;
  	buf = vmalloc(btrfs_level_size(root, 0));
  	if (!buf)
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
2807
  		return ret;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2808
2809
2810
2811
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		vfree(buf);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
2812
  		return ret;
d525e8ab0   Li Zefan   Btrfs: add dummy ...
2813
  	}
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
2814
  	path->reada = 2;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2815
  	/* clone data */
33345d015   Li Zefan   Btrfs: Always use...
2816
  	key.objectid = btrfs_ino(src);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2817
2818
  	key.type = BTRFS_EXTENT_DATA_KEY;
  	key.offset = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2819
2820
2821
2822
2823
2824
  
  	while (1) {
  		/*
  		 * note the key will change type as we walk through the
  		 * tree.
  		 */
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
2825
  		path->leave_spinning = 1;
362a20c5e   David Sterba   btrfs: allow cros...
2826
2827
  		ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path,
  				0, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2828
2829
  		if (ret < 0)
  			goto out;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2830
  		nritems = btrfs_header_nritems(path->nodes[0]);
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
2831
  process_slot:
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2832
  		if (path->slots[0] >= nritems) {
362a20c5e   David Sterba   btrfs: allow cros...
2833
  			ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2834
2835
2836
2837
  			if (ret < 0)
  				goto out;
  			if (ret > 0)
  				break;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2838
  			nritems = btrfs_header_nritems(path->nodes[0]);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2839
2840
2841
  		}
  		leaf = path->nodes[0];
  		slot = path->slots[0];
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2842

ae01a0abf   Yan Zheng   Btrfs: Update clo...
2843
  		btrfs_item_key_to_cpu(leaf, &key, slot);
d20f7043f   Chris Mason   Btrfs: move data ...
2844
  		if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
33345d015   Li Zefan   Btrfs: Always use...
2845
  		    key.objectid != btrfs_ino(src))
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2846
  			break;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2847
2848
2849
  		if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
  			struct btrfs_file_extent_item *extent;
  			int type;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2850
2851
  			u32 size;
  			struct btrfs_key new_key;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2852
2853
2854
  			u64 disko = 0, diskl = 0;
  			u64 datao = 0, datal = 0;
  			u8 comp;
b5384d48f   Sage Weil   Btrfs: fix CLONE ...
2855
  			u64 endoff;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2856

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2857
2858
2859
2860
  			extent = btrfs_item_ptr(leaf, slot,
  						struct btrfs_file_extent_item);
  			comp = btrfs_file_extent_compression(leaf, extent);
  			type = btrfs_file_extent_type(leaf, extent);
c8a894d77   Chris Mason   Btrfs: fix the fi...
2861
2862
  			if (type == BTRFS_FILE_EXTENT_REG ||
  			    type == BTRFS_FILE_EXTENT_PREALLOC) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
2863
2864
2865
2866
  				disko = btrfs_file_extent_disk_bytenr(leaf,
  								      extent);
  				diskl = btrfs_file_extent_disk_num_bytes(leaf,
  								 extent);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2867
  				datao = btrfs_file_extent_offset(leaf, extent);
d397712bc   Chris Mason   Btrfs: Fix checkp...
2868
2869
  				datal = btrfs_file_extent_num_bytes(leaf,
  								    extent);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2870
2871
2872
2873
2874
  			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
  				/* take upper bound, may be compressed */
  				datal = btrfs_file_extent_ram_bytes(leaf,
  								    extent);
  			}
31840ae1a   Zheng Yan   Btrfs: Full back ...
2875

050006a75   Sage Weil   Btrfs: fix clone ...
2876
  			if (key.offset + datal <= off ||
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
  			    key.offset >= off + len - 1) {
  				path->slots[0]++;
  				goto process_slot;
  			}
  
  			size = btrfs_item_size_nr(leaf, slot);
  			read_extent_buffer(leaf, buf,
  					   btrfs_item_ptr_offset(leaf, slot),
  					   size);
  
  			btrfs_release_path(path);
  			path->leave_spinning = 0;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2889

31840ae1a   Zheng Yan   Btrfs: Full back ...
2890
  			memcpy(&new_key, &key, sizeof(new_key));
33345d015   Li Zefan   Btrfs: Always use...
2891
  			new_key.objectid = btrfs_ino(inode);
4d728ec7a   Li Zefan   Btrfs: Fix file c...
2892
2893
2894
2895
  			if (off <= key.offset)
  				new_key.offset = key.offset + destoff - off;
  			else
  				new_key.offset = destoff;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2896

b6f3409b2   Sage Weil   Btrfs: reserve su...
2897
2898
2899
2900
2901
2902
  			/*
  			 * 1 - adjusting old extent (we may have to split it)
  			 * 1 - add new extent
  			 * 1 - inode update
  			 */
  			trans = btrfs_start_transaction(root, 3);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2903
2904
2905
2906
  			if (IS_ERR(trans)) {
  				ret = PTR_ERR(trans);
  				goto out;
  			}
c8a894d77   Chris Mason   Btrfs: fix the fi...
2907
2908
  			if (type == BTRFS_FILE_EXTENT_REG ||
  			    type == BTRFS_FILE_EXTENT_PREALLOC) {
d72c0842f   Li Zefan   Btrfs: calc file ...
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
  				/*
  				 *    a  | --- range to clone ---|  b
  				 * | ------------- extent ------------- |
  				 */
  
  				/* substract range b */
  				if (key.offset + datal > off + len)
  					datal = off + len - key.offset;
  
  				/* substract range a */
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2919
2920
2921
2922
  				if (off > key.offset) {
  					datao += off - key.offset;
  					datal -= off - key.offset;
  				}
5dc562c54   Josef Bacik   Btrfs: turbo char...
2923
  				ret = btrfs_drop_extents(trans, root, inode,
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2924
2925
  							 new_key.offset,
  							 new_key.offset + datal,
2671485d3   Josef Bacik   Btrfs: remove unu...
2926
  							 1);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2927
  				if (ret) {
00fdf13a2   Liu Bo   Btrfs: fix a cras...
2928
2929
2930
  					if (ret != -EINVAL)
  						btrfs_abort_transaction(trans,
  								root, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2931
2932
2933
  					btrfs_end_transaction(trans, root);
  					goto out;
  				}
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2934

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2935
2936
  				ret = btrfs_insert_empty_item(trans, root, path,
  							      &new_key, size);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2937
2938
2939
2940
2941
2942
  				if (ret) {
  					btrfs_abort_transaction(trans, root,
  								ret);
  					btrfs_end_transaction(trans, root);
  					goto out;
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2943
2944
2945
2946
  
  				leaf = path->nodes[0];
  				slot = path->slots[0];
  				write_extent_buffer(leaf, buf,
31840ae1a   Zheng Yan   Btrfs: Full back ...
2947
2948
  					    btrfs_item_ptr_offset(leaf, slot),
  					    size);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2949

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2950
  				extent = btrfs_item_ptr(leaf, slot,
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2951
  						struct btrfs_file_extent_item);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2952

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2953
2954
2955
  				/* disko == 0 means it's a hole */
  				if (!disko)
  					datao = 0;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2956
2957
2958
2959
2960
2961
2962
  
  				btrfs_set_file_extent_offset(leaf, extent,
  							     datao);
  				btrfs_set_file_extent_num_bytes(leaf, extent,
  								datal);
  				if (disko) {
  					inode_add_bytes(inode, datal);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2963
  					ret = btrfs_inc_extent_ref(trans, root,
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2964
2965
  							disko, diskl, 0,
  							root->root_key.objectid,
33345d015   Li Zefan   Btrfs: Always use...
2966
  							btrfs_ino(inode),
66d7e7f09   Arne Jansen   Btrfs: mark delay...
2967
2968
  							new_key.offset - datao,
  							0);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2969
2970
2971
2972
2973
2974
2975
2976
2977
  					if (ret) {
  						btrfs_abort_transaction(trans,
  									root,
  									ret);
  						btrfs_end_transaction(trans,
  								      root);
  						goto out;
  
  					}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2978
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2979
2980
2981
2982
2983
2984
2985
  			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
  				u64 skip = 0;
  				u64 trim = 0;
  				if (off > key.offset) {
  					skip = off - key.offset;
  					new_key.offset += skip;
  				}
d397712bc   Chris Mason   Btrfs: Fix checkp...
2986

aa42ffd91   Liu Bo   Btrfs: fix off-by...
2987
2988
  				if (key.offset + datal > off + len)
  					trim = key.offset + datal - (off + len);
d397712bc   Chris Mason   Btrfs: Fix checkp...
2989

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2990
  				if (comp && (skip || trim)) {
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2991
  					ret = -EINVAL;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2992
  					btrfs_end_transaction(trans, root);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2993
2994
2995
2996
  					goto out;
  				}
  				size -= skip + trim;
  				datal -= skip + trim;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2997

5dc562c54   Josef Bacik   Btrfs: turbo char...
2998
  				ret = btrfs_drop_extents(trans, root, inode,
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2999
3000
  							 new_key.offset,
  							 new_key.offset + datal,
2671485d3   Josef Bacik   Btrfs: remove unu...
3001
  							 1);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3002
  				if (ret) {
3a29bc092   Chris Mason   Btrfs: fix EINVAL...
3003
3004
3005
  					if (ret != -EINVAL)
  						btrfs_abort_transaction(trans,
  							root, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3006
3007
3008
  					btrfs_end_transaction(trans, root);
  					goto out;
  				}
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3009

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3010
3011
  				ret = btrfs_insert_empty_item(trans, root, path,
  							      &new_key, size);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3012
3013
3014
3015
3016
3017
  				if (ret) {
  					btrfs_abort_transaction(trans, root,
  								ret);
  					btrfs_end_transaction(trans, root);
  					goto out;
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3018
3019
  
  				if (skip) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
3020
3021
  					u32 start =
  					  btrfs_file_extent_calc_inline_size(0);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
  					memmove(buf+start, buf+start+skip,
  						datal);
  				}
  
  				leaf = path->nodes[0];
  				slot = path->slots[0];
  				write_extent_buffer(leaf, buf,
  					    btrfs_item_ptr_offset(leaf, slot),
  					    size);
  				inode_add_bytes(inode, datal);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3032
  			}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3033
3034
  
  			btrfs_mark_buffer_dirty(leaf);
b3b4aa74b   David Sterba   btrfs: drop unuse...
3035
  			btrfs_release_path(path);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3036

0c4d2d95d   Josef Bacik   Btrfs: use i_vers...
3037
  			inode_inc_iversion(inode);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3038
  			inode->i_mtime = inode->i_ctime = CURRENT_TIME;
b5384d48f   Sage Weil   Btrfs: fix CLONE ...
3039
3040
3041
3042
3043
3044
3045
  
  			/*
  			 * we round up to the block size at eof when
  			 * determining which extents to clone above,
  			 * but shouldn't round up the file size
  			 */
  			endoff = new_key.offset + datal;
5f3888ff6   Li Zefan   btrfs: Set file s...
3046
3047
  			if (endoff > destoff+olen)
  				endoff = destoff+olen;
b5384d48f   Sage Weil   Btrfs: fix CLONE ...
3048
3049
  			if (endoff > inode->i_size)
  				btrfs_i_size_write(inode, endoff);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3050
  			ret = btrfs_update_inode(trans, root, inode);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3051
3052
3053
3054
3055
3056
  			if (ret) {
  				btrfs_abort_transaction(trans, root, ret);
  				btrfs_end_transaction(trans, root);
  				goto out;
  			}
  			ret = btrfs_end_transaction(trans, root);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3057
  		}
b3b4aa74b   David Sterba   btrfs: drop unuse...
3058
  		btrfs_release_path(path);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3059
  		key.offset++;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3060
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3061
  	ret = 0;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3062

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3063
  out:
b3b4aa74b   David Sterba   btrfs: drop unuse...
3064
  	btrfs_release_path(path);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3065
3066
3067
3068
3069
3070
3071
3072
  	btrfs_free_path(path);
  	vfree(buf);
  	return ret;
  }
  
  static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
  				       u64 off, u64 olen, u64 destoff)
  {
54563d41a   Al Viro   btrfs: get rid of...
3073
  	struct inode *inode = file_inode(file);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct fd src_file;
  	struct inode *src;
  	int ret;
  	u64 len = olen;
  	u64 bs = root->fs_info->sb->s_blocksize;
  	int same_inode = 0;
  
  	/*
  	 * TODO:
  	 * - split compressed inline extents.  annoying: we need to
  	 *   decompress into destination's address_space (the file offset
  	 *   may change, so source mapping won't do), then recompress (or
  	 *   otherwise reinsert) a subrange.
00fdf13a2   Liu Bo   Btrfs: fix a cras...
3088
3089
3090
  	 *
  	 * - split destination inode's inline extents.  The inline extents can
  	 *   be either compressed or non-compressed.
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
  	 */
  
  	/* the destination must be opened for writing */
  	if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND))
  		return -EINVAL;
  
  	if (btrfs_root_readonly(root))
  		return -EROFS;
  
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
  
  	src_file = fdget(srcfd);
  	if (!src_file.file) {
  		ret = -EBADF;
  		goto out_drop_write;
  	}
  
  	ret = -EXDEV;
  	if (src_file.file->f_path.mnt != file->f_path.mnt)
  		goto out_fput;
  
  	src = file_inode(src_file.file);
  
  	ret = -EINVAL;
  	if (src == inode)
  		same_inode = 1;
  
  	/* the src must be open for reading */
  	if (!(src_file.file->f_mode & FMODE_READ))
  		goto out_fput;
  
  	/* don't make the dst file partly checksummed */
  	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
  	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
  		goto out_fput;
  
  	ret = -EISDIR;
  	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
  		goto out_fput;
  
  	ret = -EXDEV;
  	if (src->i_sb != inode->i_sb)
  		goto out_fput;
  
  	if (!same_inode) {
  		if (inode < src) {
  			mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
  			mutex_lock_nested(&src->i_mutex, I_MUTEX_CHILD);
  		} else {
  			mutex_lock_nested(&src->i_mutex, I_MUTEX_PARENT);
  			mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
  		}
  	} else {
  		mutex_lock(&src->i_mutex);
  	}
  
  	/* determine range to clone */
  	ret = -EINVAL;
  	if (off + len > src->i_size || off + len < off)
  		goto out_unlock;
  	if (len == 0)
  		olen = len = src->i_size - off;
  	/* if we extend to eof, continue to block boundary */
  	if (off + len == src->i_size)
  		len = ALIGN(src->i_size, bs) - off;
  
  	/* verify the end result is block aligned */
  	if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
  	    !IS_ALIGNED(destoff, bs))
  		goto out_unlock;
  
  	/* verify if ranges are overlapped within the same file */
  	if (same_inode) {
  		if (destoff + len > off && destoff < off + len)
  			goto out_unlock;
  	}
  
  	if (destoff > inode->i_size) {
  		ret = btrfs_cont_expand(inode, inode->i_size, destoff);
  		if (ret)
  			goto out_unlock;
  	}
  
  	/* truncate page cache pages from target inode range */
  	truncate_inode_pages_range(&inode->i_data, destoff,
  				   PAGE_CACHE_ALIGN(destoff + len) - 1);
  
  	lock_extent_range(src, off, len);
  
  	ret = btrfs_clone(src, inode, off, olen, len, destoff);
aa42ffd91   Liu Bo   Btrfs: fix off-by...
3183
  	unlock_extent(&BTRFS_I(src)->io_tree, off, off + len - 1);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3184
  out_unlock:
c57c2b3ed   Filipe David Borba Manana   Btrfs: unlock ino...
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
  	if (!same_inode) {
  		if (inode < src) {
  			mutex_unlock(&src->i_mutex);
  			mutex_unlock(&inode->i_mutex);
  		} else {
  			mutex_unlock(&inode->i_mutex);
  			mutex_unlock(&src->i_mutex);
  		}
  	} else {
  		mutex_unlock(&src->i_mutex);
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3196
  out_fput:
2903ff019   Al Viro   switch simple cas...
3197
  	fdput(src_file);
ab67b7c1f   Yan Zheng   Btrfs: Add missin...
3198
  out_drop_write:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
3199
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3200
3201
  	return ret;
  }
7a865e8ac   Christoph Hellwig   Btrfs: btrfs: pas...
3202
  static long btrfs_ioctl_clone_range(struct file *file, void __user *argp)
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3203
3204
  {
  	struct btrfs_ioctl_clone_range_args args;
7a865e8ac   Christoph Hellwig   Btrfs: btrfs: pas...
3205
  	if (copy_from_user(&args, argp, sizeof(args)))
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3206
3207
3208
3209
  		return -EFAULT;
  	return btrfs_ioctl_clone(file, args.src_fd, args.src_offset,
  				 args.src_length, args.dest_offset);
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3210
3211
3212
3213
3214
3215
  /*
   * there are many ways the trans_start and trans_end ioctls can lead
   * to deadlocks.  They should only be used by applications that
   * basically own the machine, and have a very in depth understanding
   * of all the possible deadlocks and enospc problems.
   */
b2950863c   Christoph Hellwig   Btrfs: make thing...
3216
  static long btrfs_ioctl_trans_start(struct file *file)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3217
  {
496ad9aa8   Al Viro   new helper: file_...
3218
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3219
3220
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
1ab86aedb   Sage Weil   Btrfs: fix error ...
3221
  	int ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3222

1ab86aedb   Sage Weil   Btrfs: fix error ...
3223
  	ret = -EPERM;
df5b5520b   Christoph Hellwig   BTRFS_IOC_TRANS_S...
3224
  	if (!capable(CAP_SYS_ADMIN))
1ab86aedb   Sage Weil   Btrfs: fix error ...
3225
  		goto out;
df5b5520b   Christoph Hellwig   BTRFS_IOC_TRANS_S...
3226

1ab86aedb   Sage Weil   Btrfs: fix error ...
3227
3228
  	ret = -EINPROGRESS;
  	if (file->private_data)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3229
  		goto out;
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3230

b83cc9693   Li Zefan   Btrfs: Add readon...
3231
3232
3233
  	ret = -EROFS;
  	if (btrfs_root_readonly(root))
  		goto out;
a561be710   Al Viro   switch a bunch of...
3234
  	ret = mnt_want_write_file(file);
c146afad2   Yan Zheng   Btrfs: mount ro a...
3235
3236
  	if (ret)
  		goto out;
a4abeea41   Josef Bacik   Btrfs: kill trans...
3237
  	atomic_inc(&root->fs_info->open_ioctl_trans);
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3238

1ab86aedb   Sage Weil   Btrfs: fix error ...
3239
  	ret = -ENOMEM;
7a7eaa40a   Josef Bacik   Btrfs: take away ...
3240
  	trans = btrfs_start_ioctl_transaction(root);
abd30bb0a   Tsutomu Itoh   btrfs: check retu...
3241
  	if (IS_ERR(trans))
1ab86aedb   Sage Weil   Btrfs: fix error ...
3242
3243
3244
3245
3246
3247
  		goto out_drop;
  
  	file->private_data = trans;
  	return 0;
  
  out_drop:
a4abeea41   Josef Bacik   Btrfs: kill trans...
3248
  	atomic_dec(&root->fs_info->open_ioctl_trans);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
3249
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3250
  out:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3251
3252
  	return ret;
  }
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3253
3254
  static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
  {
496ad9aa8   Al Viro   new helper: file_...
3255
  	struct inode *inode = file_inode(file);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3256
3257
3258
3259
3260
3261
3262
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_root *new_root;
  	struct btrfs_dir_item *di;
  	struct btrfs_trans_handle *trans;
  	struct btrfs_path *path;
  	struct btrfs_key location;
  	struct btrfs_disk_key disk_key;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3263
3264
  	u64 objectid = 0;
  	u64 dir_id;
3c04ce010   Miao Xie   Btrfs: get write ...
3265
  	int ret;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3266
3267
3268
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
3c04ce010   Miao Xie   Btrfs: get write ...
3269
3270
3271
3272
3273
3274
3275
3276
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
  
  	if (copy_from_user(&objectid, argp, sizeof(objectid))) {
  		ret = -EFAULT;
  		goto out;
  	}
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3277
3278
  
  	if (!objectid)
1cecf579d   chandan   Btrfs: btrfs_ioct...
3279
  		objectid = BTRFS_FS_TREE_OBJECTID;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3280
3281
3282
3283
3284
3285
  
  	location.objectid = objectid;
  	location.type = BTRFS_ROOT_ITEM_KEY;
  	location.offset = (u64)-1;
  
  	new_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
3c04ce010   Miao Xie   Btrfs: get write ...
3286
3287
3288
3289
  	if (IS_ERR(new_root)) {
  		ret = PTR_ERR(new_root);
  		goto out;
  	}
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3290

6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3291
  	path = btrfs_alloc_path();
3c04ce010   Miao Xie   Btrfs: get write ...
3292
3293
3294
3295
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3296
3297
3298
  	path->leave_spinning = 1;
  
  	trans = btrfs_start_transaction(root, 1);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
3299
  	if (IS_ERR(trans)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3300
  		btrfs_free_path(path);
3c04ce010   Miao Xie   Btrfs: get write ...
3301
3302
  		ret = PTR_ERR(trans);
  		goto out;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3303
  	}
6c41761fc   David Sterba   btrfs: separate s...
3304
  	dir_id = btrfs_super_root_dir(root->fs_info->super_copy);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3305
3306
  	di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path,
  				   dir_id, "default", 7, 1);
cf1e99a4e   Dan Carpenter   Btrfs: btrfs_look...
3307
  	if (IS_ERR_OR_NULL(di)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3308
3309
  		btrfs_free_path(path);
  		btrfs_end_transaction(trans, root);
efe120a06   Frank Holton   Btrfs: convert pr...
3310
3311
  		btrfs_err(new_root->fs_info, "Umm, you don't have the default dir"
  			   "item, this isn't going to work");
3c04ce010   Miao Xie   Btrfs: get write ...
3312
3313
  		ret = -ENOENT;
  		goto out;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3314
3315
3316
3317
3318
3319
  	}
  
  	btrfs_cpu_key_to_disk(&disk_key, &new_root->root_key);
  	btrfs_set_dir_item_key(path->nodes[0], di, &disk_key);
  	btrfs_mark_buffer_dirty(path->nodes[0]);
  	btrfs_free_path(path);
2b0ce2c29   Mitch Harder   Btrfs: Check INCO...
3320
  	btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3321
  	btrfs_end_transaction(trans, root);
3c04ce010   Miao Xie   Btrfs: get write ...
3322
3323
3324
  out:
  	mnt_drop_write_file(file);
  	return ret;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3325
  }
5af3e8cce   Stefan Behrens   Btrfs: make files...
3326
3327
  void btrfs_get_block_group_info(struct list_head *groups_list,
  				struct btrfs_ioctl_space_info *space)
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
  {
  	struct btrfs_block_group_cache *block_group;
  
  	space->total_bytes = 0;
  	space->used_bytes = 0;
  	space->flags = 0;
  	list_for_each_entry(block_group, groups_list, list) {
  		space->flags = block_group->flags;
  		space->total_bytes += block_group->key.offset;
  		space->used_bytes +=
  			btrfs_block_group_used(&block_group->item);
  	}
  }
48a3b6366   Eric Sandeen   btrfs: make stati...
3341
  static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
1406e4327   Josef Bacik   Btrfs: add a "df"...
3342
3343
3344
3345
  {
  	struct btrfs_ioctl_space_args space_args;
  	struct btrfs_ioctl_space_info space;
  	struct btrfs_ioctl_space_info *dest;
7fde62bff   Chris Mason   Btrfs: buffer res...
3346
  	struct btrfs_ioctl_space_info *dest_orig;
13f2696f1   Daniel J Blueman   fix user annotati...
3347
  	struct btrfs_ioctl_space_info __user *user_dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3348
  	struct btrfs_space_info *info;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3349
3350
3351
3352
3353
  	u64 types[] = {BTRFS_BLOCK_GROUP_DATA,
  		       BTRFS_BLOCK_GROUP_SYSTEM,
  		       BTRFS_BLOCK_GROUP_METADATA,
  		       BTRFS_BLOCK_GROUP_DATA | BTRFS_BLOCK_GROUP_METADATA};
  	int num_types = 4;
7fde62bff   Chris Mason   Btrfs: buffer res...
3354
  	int alloc_size;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3355
  	int ret = 0;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
3356
  	u64 slot_count = 0;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3357
  	int i, c;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3358
3359
3360
3361
3362
  
  	if (copy_from_user(&space_args,
  			   (struct btrfs_ioctl_space_args __user *)arg,
  			   sizeof(space_args)))
  		return -EFAULT;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
  	for (i = 0; i < num_types; i++) {
  		struct btrfs_space_info *tmp;
  
  		info = NULL;
  		rcu_read_lock();
  		list_for_each_entry_rcu(tmp, &root->fs_info->space_info,
  					list) {
  			if (tmp->flags == types[i]) {
  				info = tmp;
  				break;
  			}
  		}
  		rcu_read_unlock();
  
  		if (!info)
  			continue;
  
  		down_read(&info->groups_sem);
  		for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
  			if (!list_empty(&info->block_groups[c]))
  				slot_count++;
  		}
  		up_read(&info->groups_sem);
  	}
7fde62bff   Chris Mason   Btrfs: buffer res...
3387

36523e951   David Sterba   btrfs: export glo...
3388
3389
3390
3391
  	/*
  	 * Global block reserve, exported as a space_info
  	 */
  	slot_count++;
7fde62bff   Chris Mason   Btrfs: buffer res...
3392
3393
3394
3395
3396
  	/* space_slots == 0 means they are asking for a count */
  	if (space_args.space_slots == 0) {
  		space_args.total_spaces = slot_count;
  		goto out;
  	}
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3397

51788b1bd   Dan Rosenberg   btrfs: prevent he...
3398
  	slot_count = min_t(u64, space_args.space_slots, slot_count);
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3399

7fde62bff   Chris Mason   Btrfs: buffer res...
3400
  	alloc_size = sizeof(*dest) * slot_count;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3401

7fde62bff   Chris Mason   Btrfs: buffer res...
3402
3403
3404
3405
3406
  	/* we generally have at most 6 or so space infos, one for each raid
  	 * level.  So, a whole page should be more than enough for everyone
  	 */
  	if (alloc_size > PAGE_CACHE_SIZE)
  		return -ENOMEM;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3407
  	space_args.total_spaces = 0;
7fde62bff   Chris Mason   Btrfs: buffer res...
3408
3409
3410
3411
  	dest = kmalloc(alloc_size, GFP_NOFS);
  	if (!dest)
  		return -ENOMEM;
  	dest_orig = dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3412

7fde62bff   Chris Mason   Btrfs: buffer res...
3413
  	/* now we have a buffer to copy into */
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3414
3415
  	for (i = 0; i < num_types; i++) {
  		struct btrfs_space_info *tmp;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
3416
3417
  		if (!slot_count)
  			break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
  		info = NULL;
  		rcu_read_lock();
  		list_for_each_entry_rcu(tmp, &root->fs_info->space_info,
  					list) {
  			if (tmp->flags == types[i]) {
  				info = tmp;
  				break;
  			}
  		}
  		rcu_read_unlock();
7fde62bff   Chris Mason   Btrfs: buffer res...
3428

bf5fc093c   Josef Bacik   Btrfs: fix the df...
3429
3430
3431
3432
3433
  		if (!info)
  			continue;
  		down_read(&info->groups_sem);
  		for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
  			if (!list_empty(&info->block_groups[c])) {
5af3e8cce   Stefan Behrens   Btrfs: make files...
3434
3435
  				btrfs_get_block_group_info(
  					&info->block_groups[c], &space);
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3436
3437
3438
  				memcpy(dest, &space, sizeof(space));
  				dest++;
  				space_args.total_spaces++;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
3439
  				slot_count--;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3440
  			}
51788b1bd   Dan Rosenberg   btrfs: prevent he...
3441
3442
  			if (!slot_count)
  				break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3443
3444
  		}
  		up_read(&info->groups_sem);
1406e4327   Josef Bacik   Btrfs: add a "df"...
3445
  	}
1406e4327   Josef Bacik   Btrfs: add a "df"...
3446

36523e951   David Sterba   btrfs: export glo...
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
  	/*
  	 * Add global block reserve
  	 */
  	if (slot_count) {
  		struct btrfs_block_rsv *block_rsv = &root->fs_info->global_block_rsv;
  
  		spin_lock(&block_rsv->lock);
  		space.total_bytes = block_rsv->size;
  		space.used_bytes = block_rsv->size - block_rsv->reserved;
  		spin_unlock(&block_rsv->lock);
  		space.flags = BTRFS_SPACE_INFO_GLOBAL_RSV;
  		memcpy(dest, &space, sizeof(space));
  		space_args.total_spaces++;
  	}
2eec6c810   Daniel J Blueman   Fix minor type is...
3461
  	user_dest = (struct btrfs_ioctl_space_info __user *)
7fde62bff   Chris Mason   Btrfs: buffer res...
3462
3463
3464
3465
3466
3467
3468
3469
  		(arg + sizeof(struct btrfs_ioctl_space_args));
  
  	if (copy_to_user(user_dest, dest_orig, alloc_size))
  		ret = -EFAULT;
  
  	kfree(dest_orig);
  out:
  	if (ret == 0 && copy_to_user(arg, &space_args, sizeof(space_args)))
1406e4327   Josef Bacik   Btrfs: add a "df"...
3470
3471
3472
3473
  		ret = -EFAULT;
  
  	return ret;
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3474
3475
3476
3477
3478
3479
3480
3481
  /*
   * there are many ways the trans_start and trans_end ioctls can lead
   * to deadlocks.  They should only be used by applications that
   * basically own the machine, and have a very in depth understanding
   * of all the possible deadlocks and enospc problems.
   */
  long btrfs_ioctl_trans_end(struct file *file)
  {
496ad9aa8   Al Viro   new helper: file_...
3482
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3483
3484
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3485

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3486
  	trans = file->private_data;
1ab86aedb   Sage Weil   Btrfs: fix error ...
3487
3488
  	if (!trans)
  		return -EINVAL;
b214107ed   Christoph Hellwig   Btrfs: trivial sp...
3489
  	file->private_data = NULL;
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3490

1ab86aedb   Sage Weil   Btrfs: fix error ...
3491
  	btrfs_end_transaction(trans, root);
a4abeea41   Josef Bacik   Btrfs: kill trans...
3492
  	atomic_dec(&root->fs_info->open_ioctl_trans);
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3493

2a79f17e4   Al Viro   vfs: mnt_drop_wri...
3494
  	mnt_drop_write_file(file);
1ab86aedb   Sage Weil   Btrfs: fix error ...
3495
  	return 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3496
  }
9a8c28bec   Miao Xie   Btrfs: pass root ...
3497
3498
  static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
  					    void __user *argp)
462045928   Sage Weil   Btrfs: add START_...
3499
  {
462045928   Sage Weil   Btrfs: add START_...
3500
3501
  	struct btrfs_trans_handle *trans;
  	u64 transid;
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
3502
  	int ret;
462045928   Sage Weil   Btrfs: add START_...
3503

d4edf39bd   Miao Xie   Btrfs: fix uncomp...
3504
  	trans = btrfs_attach_transaction_barrier(root);
ff7c1d335   Miao Xie   Btrfs: don't star...
3505
3506
3507
3508
3509
3510
3511
3512
  	if (IS_ERR(trans)) {
  		if (PTR_ERR(trans) != -ENOENT)
  			return PTR_ERR(trans);
  
  		/* No running transaction, don't bother */
  		transid = root->fs_info->last_trans_committed;
  		goto out;
  	}
462045928   Sage Weil   Btrfs: add START_...
3513
  	transid = trans->transid;
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
3514
  	ret = btrfs_commit_transaction_async(trans, root, 0);
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
3515
3516
  	if (ret) {
  		btrfs_end_transaction(trans, root);
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
3517
  		return ret;
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
3518
  	}
ff7c1d335   Miao Xie   Btrfs: don't star...
3519
  out:
462045928   Sage Weil   Btrfs: add START_...
3520
3521
3522
3523
3524
  	if (argp)
  		if (copy_to_user(argp, &transid, sizeof(transid)))
  			return -EFAULT;
  	return 0;
  }
9a8c28bec   Miao Xie   Btrfs: pass root ...
3525
3526
  static noinline long btrfs_ioctl_wait_sync(struct btrfs_root *root,
  					   void __user *argp)
462045928   Sage Weil   Btrfs: add START_...
3527
  {
462045928   Sage Weil   Btrfs: add START_...
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
  	u64 transid;
  
  	if (argp) {
  		if (copy_from_user(&transid, argp, sizeof(transid)))
  			return -EFAULT;
  	} else {
  		transid = 0;  /* current trans */
  	}
  	return btrfs_wait_for_commit(root, transid);
  }
b8e95489b   Miao Xie   Btrfs: get write ...
3538
  static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
475f63874   Jan Schmidt   btrfs: new ioctls...
3539
  {
496ad9aa8   Al Viro   new helper: file_...
3540
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
475f63874   Jan Schmidt   btrfs: new ioctls...
3541
  	struct btrfs_ioctl_scrub_args *sa;
b8e95489b   Miao Xie   Btrfs: get write ...
3542
  	int ret;
475f63874   Jan Schmidt   btrfs: new ioctls...
3543
3544
3545
3546
3547
3548
3549
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
b8e95489b   Miao Xie   Btrfs: get write ...
3550
3551
3552
3553
3554
  	if (!(sa->flags & BTRFS_SCRUB_READONLY)) {
  		ret = mnt_want_write_file(file);
  		if (ret)
  			goto out;
  	}
aa1b8cd40   Stefan Behrens   Btrfs: pass fs_in...
3555
  	ret = btrfs_scrub_dev(root->fs_info, sa->devid, sa->start, sa->end,
63a212abc   Stefan Behrens   Btrfs: disallow s...
3556
3557
  			      &sa->progress, sa->flags & BTRFS_SCRUB_READONLY,
  			      0);
475f63874   Jan Schmidt   btrfs: new ioctls...
3558
3559
3560
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
b8e95489b   Miao Xie   Btrfs: get write ...
3561
3562
3563
  	if (!(sa->flags & BTRFS_SCRUB_READONLY))
  		mnt_drop_write_file(file);
  out:
475f63874   Jan Schmidt   btrfs: new ioctls...
3564
3565
3566
3567
3568
3569
3570
3571
  	kfree(sa);
  	return ret;
  }
  
  static long btrfs_ioctl_scrub_cancel(struct btrfs_root *root, void __user *arg)
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
aa1b8cd40   Stefan Behrens   Btrfs: pass fs_in...
3572
  	return btrfs_scrub_cancel(root->fs_info);
475f63874   Jan Schmidt   btrfs: new ioctls...
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
  }
  
  static long btrfs_ioctl_scrub_progress(struct btrfs_root *root,
  				       void __user *arg)
  {
  	struct btrfs_ioctl_scrub_args *sa;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
  
  	ret = btrfs_scrub_progress(root, sa->devid, &sa->progress);
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
  
  	kfree(sa);
  	return ret;
  }
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
3596
  static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root,
b27f7c0c1   David Sterba   btrfs: join DEV_S...
3597
  				      void __user *arg)
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
3598
3599
3600
  {
  	struct btrfs_ioctl_get_dev_stats *sa;
  	int ret;
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
3601
3602
3603
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
b27f7c0c1   David Sterba   btrfs: join DEV_S...
3604
3605
3606
3607
3608
3609
  	if ((sa->flags & BTRFS_DEV_STATS_RESET) && !capable(CAP_SYS_ADMIN)) {
  		kfree(sa);
  		return -EPERM;
  	}
  
  	ret = btrfs_get_dev_stats(root, sa);
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
3610
3611
3612
3613
3614
3615
3616
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
  
  	kfree(sa);
  	return ret;
  }
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
  static long btrfs_ioctl_dev_replace(struct btrfs_root *root, void __user *arg)
  {
  	struct btrfs_ioctl_dev_replace_args *p;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	p = memdup_user(arg, sizeof(*p));
  	if (IS_ERR(p))
  		return PTR_ERR(p);
  
  	switch (p->cmd) {
  	case BTRFS_IOCTL_DEV_REPLACE_CMD_START:
adfa97cbd   Ilya Dryomov   Btrfs: don't leak...
3631
3632
3633
3634
  		if (root->fs_info->sb->s_flags & MS_RDONLY) {
  			ret = -EROFS;
  			goto out;
  		}
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
3635
3636
3637
  		if (atomic_xchg(
  			&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
e57138b3e   Anand Jain   btrfs: return btr...
3638
  			ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
  		} else {
  			ret = btrfs_dev_replace_start(root, p);
  			atomic_set(
  			 &root->fs_info->mutually_exclusive_operation_running,
  			 0);
  		}
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS:
  		btrfs_dev_replace_status(root->fs_info, p);
  		ret = 0;
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL:
  		ret = btrfs_dev_replace_cancel(root->fs_info, p);
  		break;
  	default:
  		ret = -EINVAL;
  		break;
  	}
  
  	if (copy_to_user(arg, p, sizeof(*p)))
  		ret = -EFAULT;
adfa97cbd   Ilya Dryomov   Btrfs: don't leak...
3660
  out:
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
3661
3662
3663
  	kfree(p);
  	return ret;
  }
d7728c960   Jan Schmidt   btrfs: new ioctls...
3664
3665
3666
3667
  static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
  {
  	int ret = 0;
  	int i;
740c3d226   Chris Mason   Btrfs: fix the ne...
3668
  	u64 rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
3669
  	int size;
806468f8b   Chris Mason   Merge git://git.j...
3670
  	struct btrfs_ioctl_ino_path_args *ipa = NULL;
d7728c960   Jan Schmidt   btrfs: new ioctls...
3671
3672
  	struct inode_fs_paths *ipath = NULL;
  	struct btrfs_path *path;
82b22ac8f   Kusanagi Kouichi   Btrfs: Check CAP_...
3673
  	if (!capable(CAP_DAC_READ_SEARCH))
d7728c960   Jan Schmidt   btrfs: new ioctls...
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
  		return -EPERM;
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
  
  	ipa = memdup_user(arg, sizeof(*ipa));
  	if (IS_ERR(ipa)) {
  		ret = PTR_ERR(ipa);
  		ipa = NULL;
  		goto out;
  	}
  
  	size = min_t(u32, ipa->size, 4096);
  	ipath = init_ipath(size, root, path);
  	if (IS_ERR(ipath)) {
  		ret = PTR_ERR(ipath);
  		ipath = NULL;
  		goto out;
  	}
  
  	ret = paths_from_inode(ipa->inum, ipath);
  	if (ret < 0)
  		goto out;
  
  	for (i = 0; i < ipath->fspath->elem_cnt; ++i) {
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
3702
3703
  		rel_ptr = ipath->fspath->val[i] -
  			  (u64)(unsigned long)ipath->fspath->val;
740c3d226   Chris Mason   Btrfs: fix the ne...
3704
  		ipath->fspath->val[i] = rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
3705
  	}
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
3706
3707
  	ret = copy_to_user((void *)(unsigned long)ipa->fspath,
  			   (void *)(unsigned long)ipath->fspath, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
  	if (ret) {
  		ret = -EFAULT;
  		goto out;
  	}
  
  out:
  	btrfs_free_path(path);
  	free_ipath(ipath);
  	kfree(ipa);
  
  	return ret;
  }
  
  static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx)
  {
  	struct btrfs_data_container *inodes = ctx;
  	const size_t c = 3 * sizeof(u64);
  
  	if (inodes->bytes_left >= c) {
  		inodes->bytes_left -= c;
  		inodes->val[inodes->elem_cnt] = inum;
  		inodes->val[inodes->elem_cnt + 1] = offset;
  		inodes->val[inodes->elem_cnt + 2] = root;
  		inodes->elem_cnt += 3;
  	} else {
  		inodes->bytes_missing += c - inodes->bytes_left;
  		inodes->bytes_left = 0;
  		inodes->elem_missed += 3;
  	}
  
  	return 0;
  }
  
  static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
  					void __user *arg)
  {
  	int ret = 0;
  	int size;
d7728c960   Jan Schmidt   btrfs: new ioctls...
3746
3747
3748
  	struct btrfs_ioctl_logical_ino_args *loi;
  	struct btrfs_data_container *inodes = NULL;
  	struct btrfs_path *path = NULL;
d7728c960   Jan Schmidt   btrfs: new ioctls...
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	loi = memdup_user(arg, sizeof(*loi));
  	if (IS_ERR(loi)) {
  		ret = PTR_ERR(loi);
  		loi = NULL;
  		goto out;
  	}
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
425d17a29   Liu Bo   Btrfs: use larger...
3765
  	size = min_t(u32, loi->size, 64 * 1024);
d7728c960   Jan Schmidt   btrfs: new ioctls...
3766
3767
3768
3769
3770
3771
  	inodes = init_data_container(size);
  	if (IS_ERR(inodes)) {
  		ret = PTR_ERR(inodes);
  		inodes = NULL;
  		goto out;
  	}
df031f075   Liu Bo   Btrfs: use helper...
3772
3773
3774
  	ret = iterate_inodes_from_logical(loi->logical, root->fs_info, path,
  					  build_ino_list, inodes);
  	if (ret == -EINVAL)
d7728c960   Jan Schmidt   btrfs: new ioctls...
3775
3776
3777
  		ret = -ENOENT;
  	if (ret < 0)
  		goto out;
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
3778
3779
  	ret = copy_to_user((void *)(unsigned long)loi->inodes,
  			   (void *)(unsigned long)inodes, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
3780
3781
3782
3783
3784
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	btrfs_free_path(path);
425d17a29   Liu Bo   Btrfs: use larger...
3785
  	vfree(inodes);
d7728c960   Jan Schmidt   btrfs: new ioctls...
3786
3787
3788
3789
  	kfree(loi);
  
  	return ret;
  }
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
3790
  void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3791
3792
3793
3794
3795
  			       struct btrfs_ioctl_balance_args *bargs)
  {
  	struct btrfs_balance_control *bctl = fs_info->balance_ctl;
  
  	bargs->flags = bctl->flags;
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
3796
3797
3798
3799
  	if (atomic_read(&fs_info->balance_running))
  		bargs->state |= BTRFS_BALANCE_STATE_RUNNING;
  	if (atomic_read(&fs_info->balance_pause_req))
  		bargs->state |= BTRFS_BALANCE_STATE_PAUSE_REQ;
a7e99c691   Ilya Dryomov   Btrfs: allow for ...
3800
3801
  	if (atomic_read(&fs_info->balance_cancel_req))
  		bargs->state |= BTRFS_BALANCE_STATE_CANCEL_REQ;
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
3802

c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3803
3804
3805
  	memcpy(&bargs->data, &bctl->data, sizeof(bargs->data));
  	memcpy(&bargs->meta, &bctl->meta, sizeof(bargs->meta));
  	memcpy(&bargs->sys, &bctl->sys, sizeof(bargs->sys));
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
3806
3807
3808
3809
3810
3811
3812
3813
  
  	if (lock) {
  		spin_lock(&fs_info->balance_lock);
  		memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
  		spin_unlock(&fs_info->balance_lock);
  	} else {
  		memcpy(&bargs->stat, &bctl->stat, sizeof(bargs->stat));
  	}
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3814
  }
9ba1f6e44   Liu Bo   Btrfs: do not do ...
3815
  static long btrfs_ioctl_balance(struct file *file, void __user *arg)
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3816
  {
496ad9aa8   Al Viro   new helper: file_...
3817
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3818
3819
3820
  	struct btrfs_fs_info *fs_info = root->fs_info;
  	struct btrfs_ioctl_balance_args *bargs;
  	struct btrfs_balance_control *bctl;
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3821
  	bool need_unlock; /* for mut. excl. ops lock */
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3822
3823
3824
3825
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
e54bfa310   Liu Bo   Btrfs: use mnt_wa...
3826
  	ret = mnt_want_write_file(file);
9ba1f6e44   Liu Bo   Btrfs: do not do ...
3827
3828
  	if (ret)
  		return ret;
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
  again:
  	if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
  		mutex_lock(&fs_info->volume_mutex);
  		mutex_lock(&fs_info->balance_mutex);
  		need_unlock = true;
  		goto locked;
  	}
  
  	/*
  	 * mut. excl. ops lock is locked.  Three possibilites:
  	 *   (1) some other op is running
  	 *   (2) balance is running
  	 *   (3) balance is paused -- special case (think resume)
  	 */
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3843
  	mutex_lock(&fs_info->balance_mutex);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
  	if (fs_info->balance_ctl) {
  		/* this is either (2) or (3) */
  		if (!atomic_read(&fs_info->balance_running)) {
  			mutex_unlock(&fs_info->balance_mutex);
  			if (!mutex_trylock(&fs_info->volume_mutex))
  				goto again;
  			mutex_lock(&fs_info->balance_mutex);
  
  			if (fs_info->balance_ctl &&
  			    !atomic_read(&fs_info->balance_running)) {
  				/* this is (3) */
  				need_unlock = false;
  				goto locked;
  			}
  
  			mutex_unlock(&fs_info->balance_mutex);
  			mutex_unlock(&fs_info->volume_mutex);
  			goto again;
  		} else {
  			/* this is (2) */
  			mutex_unlock(&fs_info->balance_mutex);
  			ret = -EINPROGRESS;
  			goto out;
  		}
  	} else {
  		/* this is (1) */
  		mutex_unlock(&fs_info->balance_mutex);
e57138b3e   Anand Jain   btrfs: return btr...
3871
  		ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3872
3873
3874
3875
3876
  		goto out;
  	}
  
  locked:
  	BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3877
3878
3879
3880
3881
  
  	if (arg) {
  		bargs = memdup_user(arg, sizeof(*bargs));
  		if (IS_ERR(bargs)) {
  			ret = PTR_ERR(bargs);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3882
  			goto out_unlock;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3883
  		}
de322263d   Ilya Dryomov   Btrfs: allow for ...
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
  
  		if (bargs->flags & BTRFS_BALANCE_RESUME) {
  			if (!fs_info->balance_ctl) {
  				ret = -ENOTCONN;
  				goto out_bargs;
  			}
  
  			bctl = fs_info->balance_ctl;
  			spin_lock(&fs_info->balance_lock);
  			bctl->flags |= BTRFS_BALANCE_RESUME;
  			spin_unlock(&fs_info->balance_lock);
  
  			goto do_balance;
  		}
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3898
3899
3900
  	} else {
  		bargs = NULL;
  	}
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3901
  	if (fs_info->balance_ctl) {
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
3902
3903
3904
  		ret = -EINPROGRESS;
  		goto out_bargs;
  	}
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
  	bctl = kzalloc(sizeof(*bctl), GFP_NOFS);
  	if (!bctl) {
  		ret = -ENOMEM;
  		goto out_bargs;
  	}
  
  	bctl->fs_info = fs_info;
  	if (arg) {
  		memcpy(&bctl->data, &bargs->data, sizeof(bctl->data));
  		memcpy(&bctl->meta, &bargs->meta, sizeof(bctl->meta));
  		memcpy(&bctl->sys, &bargs->sys, sizeof(bctl->sys));
  
  		bctl->flags = bargs->flags;
f43ffb60f   Ilya Dryomov   Btrfs: add basic ...
3918
3919
3920
  	} else {
  		/* balance everything - no filters */
  		bctl->flags |= BTRFS_BALANCE_TYPE_MASK;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3921
  	}
de322263d   Ilya Dryomov   Btrfs: allow for ...
3922
  do_balance:
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3923
  	/*
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3924
3925
3926
3927
3928
  	 * Ownership of bctl and mutually_exclusive_operation_running
  	 * goes to to btrfs_balance.  bctl is freed in __cancel_balance,
  	 * or, if restriper was paused all the way until unmount, in
  	 * free_fs_info.  mutually_exclusive_operation_running is
  	 * cleared in __cancel_balance.
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3929
  	 */
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3930
3931
3932
  	need_unlock = false;
  
  	ret = btrfs_balance(bctl, bargs);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3933
3934
3935
3936
3937
3938
3939
  	if (arg) {
  		if (copy_to_user(arg, bargs, sizeof(*bargs)))
  			ret = -EFAULT;
  	}
  
  out_bargs:
  	kfree(bargs);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3940
  out_unlock:
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3941
3942
  	mutex_unlock(&fs_info->balance_mutex);
  	mutex_unlock(&fs_info->volume_mutex);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
3943
3944
3945
  	if (need_unlock)
  		atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
  out:
e54bfa310   Liu Bo   Btrfs: use mnt_wa...
3946
  	mnt_drop_write_file(file);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
3947
3948
  	return ret;
  }
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
3949
3950
3951
3952
3953
3954
3955
3956
  static long btrfs_ioctl_balance_ctl(struct btrfs_root *root, int cmd)
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	switch (cmd) {
  	case BTRFS_BALANCE_CTL_PAUSE:
  		return btrfs_pause_balance(root->fs_info);
a7e99c691   Ilya Dryomov   Btrfs: allow for ...
3957
3958
  	case BTRFS_BALANCE_CTL_CANCEL:
  		return btrfs_cancel_balance(root->fs_info);
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
3959
3960
3961
3962
  	}
  
  	return -EINVAL;
  }
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
  static long btrfs_ioctl_balance_progress(struct btrfs_root *root,
  					 void __user *arg)
  {
  	struct btrfs_fs_info *fs_info = root->fs_info;
  	struct btrfs_ioctl_balance_args *bargs;
  	int ret = 0;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	mutex_lock(&fs_info->balance_mutex);
  	if (!fs_info->balance_ctl) {
  		ret = -ENOTCONN;
  		goto out;
  	}
  
  	bargs = kzalloc(sizeof(*bargs), GFP_NOFS);
  	if (!bargs) {
  		ret = -ENOMEM;
  		goto out;
  	}
  
  	update_ioctl_balance_args(fs_info, 1, bargs);
  
  	if (copy_to_user(arg, bargs, sizeof(*bargs)))
  		ret = -EFAULT;
  
  	kfree(bargs);
  out:
  	mutex_unlock(&fs_info->balance_mutex);
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
3995
  static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
3996
  {
496ad9aa8   Al Viro   new helper: file_...
3997
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
3998
3999
4000
4001
4002
4003
4004
  	struct btrfs_ioctl_quota_ctl_args *sa;
  	struct btrfs_trans_handle *trans = NULL;
  	int ret;
  	int err;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
905b0dda0   Miao Xie   Btrfs: get write ...
4005
4006
4007
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4008
4009
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4010
4011
4012
4013
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4014

7708f029d   Wang Shilong   Btrfs: creating t...
4015
  	down_write(&root->fs_info->subvol_sem);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4016
4017
4018
4019
  	trans = btrfs_start_transaction(root->fs_info->tree_root, 2);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4020
4021
4022
4023
4024
4025
4026
4027
4028
  	}
  
  	switch (sa->cmd) {
  	case BTRFS_QUOTA_CTL_ENABLE:
  		ret = btrfs_quota_enable(trans, root->fs_info);
  		break;
  	case BTRFS_QUOTA_CTL_DISABLE:
  		ret = btrfs_quota_disable(trans, root->fs_info);
  		break;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4029
4030
4031
4032
  	default:
  		ret = -EINVAL;
  		break;
  	}
2f2320360   Jan Schmidt   Btrfs: rescan for...
4033
4034
4035
  	err = btrfs_commit_transaction(trans, root->fs_info->tree_root);
  	if (err && !ret)
  		ret = err;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4036
4037
  out:
  	kfree(sa);
7708f029d   Wang Shilong   Btrfs: creating t...
4038
  	up_write(&root->fs_info->subvol_sem);
905b0dda0   Miao Xie   Btrfs: get write ...
4039
4040
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4041
4042
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4043
  static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4044
  {
496ad9aa8   Al Viro   new helper: file_...
4045
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4046
4047
4048
4049
4050
4051
4052
  	struct btrfs_ioctl_qgroup_assign_args *sa;
  	struct btrfs_trans_handle *trans;
  	int ret;
  	int err;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
905b0dda0   Miao Xie   Btrfs: get write ...
4053
4054
4055
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4056
4057
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4058
4059
4060
4061
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
  
  	trans = btrfs_join_transaction(root);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
  	}
  
  	/* FIXME: check if the IDs really exist */
  	if (sa->assign) {
  		ret = btrfs_add_qgroup_relation(trans, root->fs_info,
  						sa->src, sa->dst);
  	} else {
  		ret = btrfs_del_qgroup_relation(trans, root->fs_info,
  						sa->src, sa->dst);
  	}
  
  	err = btrfs_end_transaction(trans, root);
  	if (err && !ret)
  		ret = err;
  
  out:
  	kfree(sa);
905b0dda0   Miao Xie   Btrfs: get write ...
4084
4085
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4086
4087
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4088
  static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4089
  {
496ad9aa8   Al Viro   new helper: file_...
4090
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4091
4092
4093
4094
4095
4096
4097
  	struct btrfs_ioctl_qgroup_create_args *sa;
  	struct btrfs_trans_handle *trans;
  	int ret;
  	int err;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
905b0dda0   Miao Xie   Btrfs: get write ...
4098
4099
4100
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4101
4102
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4103
4104
4105
4106
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4107

d86e56cf7   Miao Xie   Btrfs: disable qg...
4108
4109
4110
4111
  	if (!sa->qgroupid) {
  		ret = -EINVAL;
  		goto out;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
  	trans = btrfs_join_transaction(root);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
  	}
  
  	/* FIXME: check if the IDs really exist */
  	if (sa->create) {
  		ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid,
  					  NULL);
  	} else {
  		ret = btrfs_remove_qgroup(trans, root->fs_info, sa->qgroupid);
  	}
  
  	err = btrfs_end_transaction(trans, root);
  	if (err && !ret)
  		ret = err;
  
  out:
  	kfree(sa);
905b0dda0   Miao Xie   Btrfs: get write ...
4132
4133
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4134
4135
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4136
  static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4137
  {
496ad9aa8   Al Viro   new helper: file_...
4138
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4139
4140
4141
4142
4143
4144
4145
4146
  	struct btrfs_ioctl_qgroup_limit_args *sa;
  	struct btrfs_trans_handle *trans;
  	int ret;
  	int err;
  	u64 qgroupid;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
905b0dda0   Miao Xie   Btrfs: get write ...
4147
4148
4149
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4150
4151
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4152
4153
4154
4155
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
  
  	trans = btrfs_join_transaction(root);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
  	}
  
  	qgroupid = sa->qgroupid;
  	if (!qgroupid) {
  		/* take the current subvol as qgroup */
  		qgroupid = root->root_key.objectid;
  	}
  
  	/* FIXME: check if the IDs really exist */
  	ret = btrfs_limit_qgroup(trans, root->fs_info, qgroupid, &sa->lim);
  
  	err = btrfs_end_transaction(trans, root);
  	if (err && !ret)
  		ret = err;
  
  out:
  	kfree(sa);
905b0dda0   Miao Xie   Btrfs: get write ...
4178
4179
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4180
4181
  	return ret;
  }
2f2320360   Jan Schmidt   Btrfs: rescan for...
4182
4183
  static long btrfs_ioctl_quota_rescan(struct file *file, void __user *arg)
  {
6d0379ec4   Al Viro   btrfs: more open-...
4184
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
2f2320360   Jan Schmidt   Btrfs: rescan for...
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
  	struct btrfs_ioctl_quota_rescan_args *qsa;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
  
  	qsa = memdup_user(arg, sizeof(*qsa));
  	if (IS_ERR(qsa)) {
  		ret = PTR_ERR(qsa);
  		goto drop_write;
  	}
  
  	if (qsa->flags) {
  		ret = -EINVAL;
  		goto out;
  	}
  
  	ret = btrfs_qgroup_rescan(root->fs_info);
  
  out:
  	kfree(qsa);
  drop_write:
  	mnt_drop_write_file(file);
  	return ret;
  }
  
  static long btrfs_ioctl_quota_rescan_status(struct file *file, void __user *arg)
  {
6d0379ec4   Al Viro   btrfs: more open-...
4217
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
2f2320360   Jan Schmidt   Btrfs: rescan for...
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
  	struct btrfs_ioctl_quota_rescan_args *qsa;
  	int ret = 0;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	qsa = kzalloc(sizeof(*qsa), GFP_NOFS);
  	if (!qsa)
  		return -ENOMEM;
  
  	if (root->fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
  		qsa->flags = 1;
  		qsa->progress = root->fs_info->qgroup_rescan_progress.objectid;
  	}
  
  	if (copy_to_user(arg, qsa, sizeof(*qsa)))
  		ret = -EFAULT;
  
  	kfree(qsa);
  	return ret;
  }
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4239
4240
  static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg)
  {
54563d41a   Al Viro   btrfs: get rid of...
4241
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4242
4243
4244
4245
4246
4247
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	return btrfs_qgroup_wait_for_completion(root->fs_info);
  }
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4248
4249
  static long _btrfs_ioctl_set_received_subvol(struct file *file,
  					    struct btrfs_ioctl_received_subvol_args *sa)
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4250
  {
496ad9aa8   Al Viro   new helper: file_...
4251
  	struct inode *inode = file_inode(file);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4252
4253
4254
4255
4256
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_root_item *root_item = &root->root_item;
  	struct btrfs_trans_handle *trans;
  	struct timespec ct = CURRENT_TIME;
  	int ret = 0;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4257
  	int received_uuid_changed;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4258

bd60ea0fe   David Sterba   btrfs: call permi...
4259
4260
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
  	ret = mnt_want_write_file(file);
  	if (ret < 0)
  		return ret;
  
  	down_write(&root->fs_info->subvol_sem);
  
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
  		ret = -EINVAL;
  		goto out;
  	}
  
  	if (btrfs_root_readonly(root)) {
  		ret = -EROFS;
  		goto out;
  	}
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4276
4277
4278
4279
4280
  	/*
  	 * 1 - root item
  	 * 2 - uuid items (received uuid + subvol uuid)
  	 */
  	trans = btrfs_start_transaction(root, 3);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4281
4282
4283
4284
4285
4286
4287
4288
4289
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		trans = NULL;
  		goto out;
  	}
  
  	sa->rtransid = trans->transid;
  	sa->rtime.sec = ct.tv_sec;
  	sa->rtime.nsec = ct.tv_nsec;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4290
4291
4292
4293
4294
4295
4296
4297
  	received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid,
  				       BTRFS_UUID_SIZE);
  	if (received_uuid_changed &&
  	    !btrfs_is_empty_uuid(root_item->received_uuid))
  		btrfs_uuid_tree_rem(trans, root->fs_info->uuid_root,
  				    root_item->received_uuid,
  				    BTRFS_UUID_KEY_RECEIVED_SUBVOL,
  				    root->root_key.objectid);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4298
4299
4300
  	memcpy(root_item->received_uuid, sa->uuid, BTRFS_UUID_SIZE);
  	btrfs_set_root_stransid(root_item, sa->stransid);
  	btrfs_set_root_rtransid(root_item, sa->rtransid);
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
4301
4302
4303
4304
  	btrfs_set_stack_timespec_sec(&root_item->stime, sa->stime.sec);
  	btrfs_set_stack_timespec_nsec(&root_item->stime, sa->stime.nsec);
  	btrfs_set_stack_timespec_sec(&root_item->rtime, sa->rtime.sec);
  	btrfs_set_stack_timespec_nsec(&root_item->rtime, sa->rtime.nsec);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4305
4306
4307
4308
4309
  
  	ret = btrfs_update_root(trans, root->fs_info->tree_root,
  				&root->root_key, &root->root_item);
  	if (ret < 0) {
  		btrfs_end_transaction(trans, root);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4310
  		goto out;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4311
4312
4313
4314
4315
4316
4317
4318
  	}
  	if (received_uuid_changed && !btrfs_is_empty_uuid(sa->uuid)) {
  		ret = btrfs_uuid_tree_add(trans, root->fs_info->uuid_root,
  					  sa->uuid,
  					  BTRFS_UUID_KEY_RECEIVED_SUBVOL,
  					  root->root_key.objectid);
  		if (ret < 0 && ret != -EEXIST) {
  			btrfs_abort_transaction(trans, root, ret);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4319
  			goto out;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4320
4321
4322
4323
4324
4325
  		}
  	}
  	ret = btrfs_commit_transaction(trans, root);
  	if (ret < 0) {
  		btrfs_abort_transaction(trans, root, ret);
  		goto out;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4326
  	}
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
  out:
  	up_write(&root->fs_info->subvol_sem);
  	mnt_drop_write_file(file);
  	return ret;
  }
  
  #ifdef CONFIG_64BIT
  static long btrfs_ioctl_set_received_subvol_32(struct file *file,
  						void __user *arg)
  {
  	struct btrfs_ioctl_received_subvol_args_32 *args32 = NULL;
  	struct btrfs_ioctl_received_subvol_args *args64 = NULL;
  	int ret = 0;
  
  	args32 = memdup_user(arg, sizeof(*args32));
  	if (IS_ERR(args32)) {
  		ret = PTR_ERR(args32);
  		args32 = NULL;
  		goto out;
  	}
  
  	args64 = kmalloc(sizeof(*args64), GFP_NOFS);
84dbeb87d   Dan Carpenter   Btrfs: kmalloc() ...
4349
4350
  	if (!args64) {
  		ret = -ENOMEM;
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
  		goto out;
  	}
  
  	memcpy(args64->uuid, args32->uuid, BTRFS_UUID_SIZE);
  	args64->stransid = args32->stransid;
  	args64->rtransid = args32->rtransid;
  	args64->stime.sec = args32->stime.sec;
  	args64->stime.nsec = args32->stime.nsec;
  	args64->rtime.sec = args32->rtime.sec;
  	args64->rtime.nsec = args32->rtime.nsec;
  	args64->flags = args32->flags;
  
  	ret = _btrfs_ioctl_set_received_subvol(file, args64);
  	if (ret)
  		goto out;
  
  	memcpy(args32->uuid, args64->uuid, BTRFS_UUID_SIZE);
  	args32->stransid = args64->stransid;
  	args32->rtransid = args64->rtransid;
  	args32->stime.sec = args64->stime.sec;
  	args32->stime.nsec = args64->stime.nsec;
  	args32->rtime.sec = args64->rtime.sec;
  	args32->rtime.nsec = args64->rtime.nsec;
  	args32->flags = args64->flags;
  
  	ret = copy_to_user(arg, args32, sizeof(*args32));
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	kfree(args32);
  	kfree(args64);
  	return ret;
  }
  #endif
  
  static long btrfs_ioctl_set_received_subvol(struct file *file,
  					    void __user *arg)
  {
  	struct btrfs_ioctl_received_subvol_args *sa = NULL;
  	int ret = 0;
  
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		sa = NULL;
  		goto out;
  	}
  
  	ret = _btrfs_ioctl_set_received_subvol(file, sa);
  
  	if (ret)
  		goto out;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4404
4405
4406
4407
4408
4409
  	ret = copy_to_user(arg, sa, sizeof(*sa));
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	kfree(sa);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4410
4411
  	return ret;
  }
867ab667e   jeff.liu   Btrfs: Add a new ...
4412
4413
  static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg)
  {
6d0379ec4   Al Viro   btrfs: more open-...
4414
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
a1b83ac52   Anand Jain   btrfs: fix get se...
4415
  	size_t len;
867ab667e   jeff.liu   Btrfs: Add a new ...
4416
  	int ret;
a1b83ac52   Anand Jain   btrfs: fix get se...
4417
4418
4419
4420
4421
4422
4423
  	char label[BTRFS_LABEL_SIZE];
  
  	spin_lock(&root->fs_info->super_lock);
  	memcpy(label, root->fs_info->super_copy->label, BTRFS_LABEL_SIZE);
  	spin_unlock(&root->fs_info->super_lock);
  
  	len = strnlen(label, BTRFS_LABEL_SIZE);
867ab667e   jeff.liu   Btrfs: Add a new ...
4424
4425
  
  	if (len == BTRFS_LABEL_SIZE) {
efe120a06   Frank Holton   Btrfs: convert pr...
4426
4427
  		btrfs_warn(root->fs_info,
  			"label is too long, return the first %zu bytes", --len);
867ab667e   jeff.liu   Btrfs: Add a new ...
4428
  	}
867ab667e   jeff.liu   Btrfs: Add a new ...
4429
  	ret = copy_to_user(arg, label, len);
867ab667e   jeff.liu   Btrfs: Add a new ...
4430
4431
4432
  
  	return ret ? -EFAULT : 0;
  }
a8bfd4abe   jeff.liu   Btrfs: set/change...
4433
4434
  static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
  {
6d0379ec4   Al Viro   btrfs: more open-...
4435
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
a8bfd4abe   jeff.liu   Btrfs: set/change...
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
  	struct btrfs_super_block *super_block = root->fs_info->super_copy;
  	struct btrfs_trans_handle *trans;
  	char label[BTRFS_LABEL_SIZE];
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	if (copy_from_user(label, arg, sizeof(label)))
  		return -EFAULT;
  
  	if (strnlen(label, BTRFS_LABEL_SIZE) == BTRFS_LABEL_SIZE) {
efe120a06   Frank Holton   Btrfs: convert pr...
4448
  		btrfs_err(root->fs_info, "unable to set label with more than %d bytes",
a8bfd4abe   jeff.liu   Btrfs: set/change...
4449
4450
4451
4452
4453
4454
4455
  		       BTRFS_LABEL_SIZE - 1);
  		return -EINVAL;
  	}
  
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
a8bfd4abe   jeff.liu   Btrfs: set/change...
4456
4457
4458
4459
4460
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_unlock;
  	}
a1b83ac52   Anand Jain   btrfs: fix get se...
4461
  	spin_lock(&root->fs_info->super_lock);
a8bfd4abe   jeff.liu   Btrfs: set/change...
4462
  	strcpy(super_block->label, label);
a1b83ac52   Anand Jain   btrfs: fix get se...
4463
  	spin_unlock(&root->fs_info->super_lock);
d0270aca8   Jeff Mahoney   btrfs: commit tra...
4464
  	ret = btrfs_commit_transaction(trans, root);
a8bfd4abe   jeff.liu   Btrfs: set/change...
4465
4466
  
  out_unlock:
a8bfd4abe   jeff.liu   Btrfs: set/change...
4467
4468
4469
  	mnt_drop_write_file(file);
  	return ret;
  }
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
  #define INIT_FEATURE_FLAGS(suffix) \
  	{ .compat_flags = BTRFS_FEATURE_COMPAT_##suffix, \
  	  .compat_ro_flags = BTRFS_FEATURE_COMPAT_RO_##suffix, \
  	  .incompat_flags = BTRFS_FEATURE_INCOMPAT_##suffix }
  
  static int btrfs_ioctl_get_supported_features(struct file *file,
  					      void __user *arg)
  {
  	static struct btrfs_ioctl_feature_flags features[3] = {
  		INIT_FEATURE_FLAGS(SUPP),
  		INIT_FEATURE_FLAGS(SAFE_SET),
  		INIT_FEATURE_FLAGS(SAFE_CLEAR)
  	};
  
  	if (copy_to_user(arg, &features, sizeof(features)))
  		return -EFAULT;
  
  	return 0;
  }
  
  static int btrfs_ioctl_get_features(struct file *file, void __user *arg)
  {
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
  	struct btrfs_super_block *super_block = root->fs_info->super_copy;
  	struct btrfs_ioctl_feature_flags features;
  
  	features.compat_flags = btrfs_super_compat_flags(super_block);
  	features.compat_ro_flags = btrfs_super_compat_ro_flags(super_block);
  	features.incompat_flags = btrfs_super_incompat_flags(super_block);
  
  	if (copy_to_user(arg, &features, sizeof(features)))
  		return -EFAULT;
  
  	return 0;
  }
3b02a68a6   Jeff Mahoney   btrfs: use featur...
4505
4506
  static int check_feature_bits(struct btrfs_root *root,
  			      enum btrfs_feature_set set,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4507
4508
4509
  			      u64 change_mask, u64 flags, u64 supported_flags,
  			      u64 safe_set, u64 safe_clear)
  {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
4510
4511
  	const char *type = btrfs_feature_set_names[set];
  	char *names;
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4512
4513
4514
4515
4516
4517
  	u64 disallowed, unsupported;
  	u64 set_mask = flags & change_mask;
  	u64 clear_mask = ~flags & change_mask;
  
  	unsupported = set_mask & ~supported_flags;
  	if (unsupported) {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
4518
4519
4520
4521
4522
4523
4524
4525
  		names = btrfs_printable_features(set, unsupported);
  		if (names) {
  			btrfs_warn(root->fs_info,
  			   "this kernel does not support the %s feature bit%s",
  			   names, strchr(names, ',') ? "s" : "");
  			kfree(names);
  		} else
  			btrfs_warn(root->fs_info,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4526
4527
4528
4529
4530
4531
4532
  			   "this kernel does not support %s bits 0x%llx",
  			   type, unsupported);
  		return -EOPNOTSUPP;
  	}
  
  	disallowed = set_mask & ~safe_set;
  	if (disallowed) {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
4533
4534
4535
4536
4537
4538
4539
4540
  		names = btrfs_printable_features(set, disallowed);
  		if (names) {
  			btrfs_warn(root->fs_info,
  			   "can't set the %s feature bit%s while mounted",
  			   names, strchr(names, ',') ? "s" : "");
  			kfree(names);
  		} else
  			btrfs_warn(root->fs_info,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4541
4542
4543
4544
4545
4546
4547
  			   "can't set %s bits 0x%llx while mounted",
  			   type, disallowed);
  		return -EPERM;
  	}
  
  	disallowed = clear_mask & ~safe_clear;
  	if (disallowed) {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
4548
4549
4550
4551
4552
4553
4554
4555
  		names = btrfs_printable_features(set, disallowed);
  		if (names) {
  			btrfs_warn(root->fs_info,
  			   "can't clear the %s feature bit%s while mounted",
  			   names, strchr(names, ',') ? "s" : "");
  			kfree(names);
  		} else
  			btrfs_warn(root->fs_info,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4556
4557
4558
4559
4560
4561
4562
4563
4564
  			   "can't clear %s bits 0x%llx while mounted",
  			   type, disallowed);
  		return -EPERM;
  	}
  
  	return 0;
  }
  
  #define check_feature(root, change_mask, flags, mask_base)	\
3b02a68a6   Jeff Mahoney   btrfs: use featur...
4565
  check_feature_bits(root, FEAT_##mask_base, change_mask, flags,	\
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
  		   BTRFS_FEATURE_ ## mask_base ## _SUPP,	\
  		   BTRFS_FEATURE_ ## mask_base ## _SAFE_SET,	\
  		   BTRFS_FEATURE_ ## mask_base ## _SAFE_CLEAR)
  
  static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
  {
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
  	struct btrfs_super_block *super_block = root->fs_info->super_copy;
  	struct btrfs_ioctl_feature_flags flags[2];
  	struct btrfs_trans_handle *trans;
  	u64 newflags;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	if (copy_from_user(flags, arg, sizeof(flags)))
  		return -EFAULT;
  
  	/* Nothing to do */
  	if (!flags[0].compat_flags && !flags[0].compat_ro_flags &&
  	    !flags[0].incompat_flags)
  		return 0;
  
  	ret = check_feature(root, flags[0].compat_flags,
  			    flags[1].compat_flags, COMPAT);
  	if (ret)
  		return ret;
  
  	ret = check_feature(root, flags[0].compat_ro_flags,
  			    flags[1].compat_ro_flags, COMPAT_RO);
  	if (ret)
  		return ret;
  
  	ret = check_feature(root, flags[0].incompat_flags,
  			    flags[1].incompat_flags, INCOMPAT);
  	if (ret)
  		return ret;
8051aa1a3   David Sterba   btrfs: reserve no...
4604
  	trans = btrfs_start_transaction(root, 0);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
  	if (IS_ERR(trans))
  		return PTR_ERR(trans);
  
  	spin_lock(&root->fs_info->super_lock);
  	newflags = btrfs_super_compat_flags(super_block);
  	newflags |= flags[0].compat_flags & flags[1].compat_flags;
  	newflags &= ~(flags[0].compat_flags & ~flags[1].compat_flags);
  	btrfs_set_super_compat_flags(super_block, newflags);
  
  	newflags = btrfs_super_compat_ro_flags(super_block);
  	newflags |= flags[0].compat_ro_flags & flags[1].compat_ro_flags;
  	newflags &= ~(flags[0].compat_ro_flags & ~flags[1].compat_ro_flags);
  	btrfs_set_super_compat_ro_flags(super_block, newflags);
  
  	newflags = btrfs_super_incompat_flags(super_block);
  	newflags |= flags[0].incompat_flags & flags[1].incompat_flags;
  	newflags &= ~(flags[0].incompat_flags & ~flags[1].incompat_flags);
  	btrfs_set_super_incompat_flags(super_block, newflags);
  	spin_unlock(&root->fs_info->super_lock);
d0270aca8   Jeff Mahoney   btrfs: commit tra...
4624
  	return btrfs_commit_transaction(trans, root);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4625
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4626
4627
4628
  long btrfs_ioctl(struct file *file, unsigned int
  		cmd, unsigned long arg)
  {
496ad9aa8   Al Viro   new helper: file_...
4629
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
4630
  	void __user *argp = (void __user *)arg;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4631
4632
  
  	switch (cmd) {
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
4633
4634
4635
4636
4637
4638
  	case FS_IOC_GETFLAGS:
  		return btrfs_ioctl_getflags(file, argp);
  	case FS_IOC_SETFLAGS:
  		return btrfs_ioctl_setflags(file, argp);
  	case FS_IOC_GETVERSION:
  		return btrfs_ioctl_getversion(file, argp);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
4639
4640
  	case FITRIM:
  		return btrfs_ioctl_fitrim(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4641
  	case BTRFS_IOC_SNAP_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
4642
  		return btrfs_ioctl_snap_create(file, argp, 0);
fdfb1e4f6   Li Zefan   Btrfs: Make async...
4643
  	case BTRFS_IOC_SNAP_CREATE_V2:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
4644
  		return btrfs_ioctl_snap_create_v2(file, argp, 0);
3de4586c5   Chris Mason   Btrfs: Allow subv...
4645
  	case BTRFS_IOC_SUBVOL_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
4646
  		return btrfs_ioctl_snap_create(file, argp, 1);
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
4647
4648
  	case BTRFS_IOC_SUBVOL_CREATE_V2:
  		return btrfs_ioctl_snap_create_v2(file, argp, 1);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
4649
4650
  	case BTRFS_IOC_SNAP_DESTROY:
  		return btrfs_ioctl_snap_destroy(file, argp);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
4651
4652
4653
4654
  	case BTRFS_IOC_SUBVOL_GETFLAGS:
  		return btrfs_ioctl_subvol_getflags(file, argp);
  	case BTRFS_IOC_SUBVOL_SETFLAGS:
  		return btrfs_ioctl_subvol_setflags(file, argp);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
4655
4656
  	case BTRFS_IOC_DEFAULT_SUBVOL:
  		return btrfs_ioctl_default_subvol(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4657
  	case BTRFS_IOC_DEFRAG:
1e701a329   Chris Mason   Btrfs: add new de...
4658
4659
4660
  		return btrfs_ioctl_defrag(file, NULL);
  	case BTRFS_IOC_DEFRAG_RANGE:
  		return btrfs_ioctl_defrag(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4661
  	case BTRFS_IOC_RESIZE:
198605a8e   Miao Xie   Btrfs: get write ...
4662
  		return btrfs_ioctl_resize(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4663
  	case BTRFS_IOC_ADD_DEV:
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
4664
  		return btrfs_ioctl_add_dev(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4665
  	case BTRFS_IOC_RM_DEV:
da24927b1   Miao Xie   Btrfs: get write ...
4666
  		return btrfs_ioctl_rm_dev(file, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
4667
4668
4669
4670
  	case BTRFS_IOC_FS_INFO:
  		return btrfs_ioctl_fs_info(root, argp);
  	case BTRFS_IOC_DEV_INFO:
  		return btrfs_ioctl_dev_info(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4671
  	case BTRFS_IOC_BALANCE:
9ba1f6e44   Liu Bo   Btrfs: do not do ...
4672
  		return btrfs_ioctl_balance(file, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4673
  	case BTRFS_IOC_CLONE:
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
4674
4675
  		return btrfs_ioctl_clone(file, arg, 0, 0, 0);
  	case BTRFS_IOC_CLONE_RANGE:
7a865e8ac   Christoph Hellwig   Btrfs: btrfs: pas...
4676
  		return btrfs_ioctl_clone_range(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4677
4678
4679
4680
  	case BTRFS_IOC_TRANS_START:
  		return btrfs_ioctl_trans_start(file);
  	case BTRFS_IOC_TRANS_END:
  		return btrfs_ioctl_trans_end(file);
ac8e9819d   Chris Mason   Btrfs: add search...
4681
4682
4683
4684
  	case BTRFS_IOC_TREE_SEARCH:
  		return btrfs_ioctl_tree_search(file, argp);
  	case BTRFS_IOC_INO_LOOKUP:
  		return btrfs_ioctl_ino_lookup(file, argp);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4685
4686
4687
4688
  	case BTRFS_IOC_INO_PATHS:
  		return btrfs_ioctl_ino_to_path(root, argp);
  	case BTRFS_IOC_LOGICAL_INO:
  		return btrfs_ioctl_logical_to_ino(root, argp);
1406e4327   Josef Bacik   Btrfs: add a "df"...
4689
4690
  	case BTRFS_IOC_SPACE_INFO:
  		return btrfs_ioctl_space_info(root, argp);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
4691
4692
  	case BTRFS_IOC_SYNC: {
  		int ret;
6c255e67c   Miao Xie   Btrfs: don't flus...
4693
  		ret = btrfs_start_delalloc_roots(root->fs_info, 0, -1);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
4694
4695
4696
4697
4698
  		if (ret)
  			return ret;
  		ret = btrfs_sync_fs(file->f_dentry->d_sb, 1);
  		return ret;
  	}
462045928   Sage Weil   Btrfs: add START_...
4699
  	case BTRFS_IOC_START_SYNC:
9a8c28bec   Miao Xie   Btrfs: pass root ...
4700
  		return btrfs_ioctl_start_sync(root, argp);
462045928   Sage Weil   Btrfs: add START_...
4701
  	case BTRFS_IOC_WAIT_SYNC:
9a8c28bec   Miao Xie   Btrfs: pass root ...
4702
  		return btrfs_ioctl_wait_sync(root, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
4703
  	case BTRFS_IOC_SCRUB:
b8e95489b   Miao Xie   Btrfs: get write ...
4704
  		return btrfs_ioctl_scrub(file, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
4705
4706
4707
4708
  	case BTRFS_IOC_SCRUB_CANCEL:
  		return btrfs_ioctl_scrub_cancel(root, argp);
  	case BTRFS_IOC_SCRUB_PROGRESS:
  		return btrfs_ioctl_scrub_progress(root, argp);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4709
  	case BTRFS_IOC_BALANCE_V2:
9ba1f6e44   Liu Bo   Btrfs: do not do ...
4710
  		return btrfs_ioctl_balance(file, argp);
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4711
4712
  	case BTRFS_IOC_BALANCE_CTL:
  		return btrfs_ioctl_balance_ctl(root, arg);
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4713
4714
  	case BTRFS_IOC_BALANCE_PROGRESS:
  		return btrfs_ioctl_balance_progress(root, argp);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4715
4716
  	case BTRFS_IOC_SET_RECEIVED_SUBVOL:
  		return btrfs_ioctl_set_received_subvol(file, argp);
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4717
4718
4719
4720
  #ifdef CONFIG_64BIT
  	case BTRFS_IOC_SET_RECEIVED_SUBVOL_32:
  		return btrfs_ioctl_set_received_subvol_32(file, argp);
  #endif
31db9f7c2   Alexander Block   Btrfs: introduce ...
4721
4722
  	case BTRFS_IOC_SEND:
  		return btrfs_ioctl_send(file, argp);
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
4723
  	case BTRFS_IOC_GET_DEV_STATS:
b27f7c0c1   David Sterba   btrfs: join DEV_S...
4724
  		return btrfs_ioctl_get_dev_stats(root, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4725
  	case BTRFS_IOC_QUOTA_CTL:
905b0dda0   Miao Xie   Btrfs: get write ...
4726
  		return btrfs_ioctl_quota_ctl(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4727
  	case BTRFS_IOC_QGROUP_ASSIGN:
905b0dda0   Miao Xie   Btrfs: get write ...
4728
  		return btrfs_ioctl_qgroup_assign(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4729
  	case BTRFS_IOC_QGROUP_CREATE:
905b0dda0   Miao Xie   Btrfs: get write ...
4730
  		return btrfs_ioctl_qgroup_create(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4731
  	case BTRFS_IOC_QGROUP_LIMIT:
905b0dda0   Miao Xie   Btrfs: get write ...
4732
  		return btrfs_ioctl_qgroup_limit(file, argp);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4733
4734
4735
4736
  	case BTRFS_IOC_QUOTA_RESCAN:
  		return btrfs_ioctl_quota_rescan(file, argp);
  	case BTRFS_IOC_QUOTA_RESCAN_STATUS:
  		return btrfs_ioctl_quota_rescan_status(file, argp);
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4737
4738
  	case BTRFS_IOC_QUOTA_RESCAN_WAIT:
  		return btrfs_ioctl_quota_rescan_wait(file, argp);
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4739
4740
  	case BTRFS_IOC_DEV_REPLACE:
  		return btrfs_ioctl_dev_replace(root, argp);
867ab667e   jeff.liu   Btrfs: Add a new ...
4741
4742
  	case BTRFS_IOC_GET_FSLABEL:
  		return btrfs_ioctl_get_fslabel(file, argp);
a8bfd4abe   jeff.liu   Btrfs: set/change...
4743
4744
  	case BTRFS_IOC_SET_FSLABEL:
  		return btrfs_ioctl_set_fslabel(file, argp);
416161db9   Mark Fasheh   btrfs: offline de...
4745
4746
  	case BTRFS_IOC_FILE_EXTENT_SAME:
  		return btrfs_ioctl_file_extent_same(file, argp);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
4747
4748
4749
4750
4751
4752
  	case BTRFS_IOC_GET_SUPPORTED_FEATURES:
  		return btrfs_ioctl_get_supported_features(file, argp);
  	case BTRFS_IOC_GET_FEATURES:
  		return btrfs_ioctl_get_features(file, argp);
  	case BTRFS_IOC_SET_FEATURES:
  		return btrfs_ioctl_set_features(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4753
4754
4755
4756
  	}
  
  	return -ENOTTY;
  }