Blame view

fs/btrfs/ioctl.c 137 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"
fcebe4562   Josef Bacik   Btrfs: rework qgr...
61
  #include "qgroup.h"
1ec9a1ae1   Filipe Manana   Btrfs: fix unrepl...
62
  #include "tree-log.h"
ebb8765b2   Anand Jain   btrfs: move btrfs...
63
  #include "compression.h"
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
64

abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  #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...
89
  static int btrfs_clone(struct inode *src, struct inode *inode,
1c919a5e1   Mark Fasheh   btrfs: don't upda...
90
91
  		       u64 off, u64 olen, u64 olen_aligned, u64 destoff,
  		       int no_time_update);
416161db9   Mark Fasheh   btrfs: offline de...
92

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
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
118
119
120
121
122
  /* 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...
123
124
  	if (flags & BTRFS_INODE_NODATACOW)
  		iflags |= FS_NOCOW_FL;
13f48dc90   Satoru Takeuchi   btrfs: Simplify c...
125
  	if (flags & BTRFS_INODE_NOCOMPRESS)
d0092bdda   Li Zefan   Btrfs: fix FS_IOC...
126
  		iflags |= FS_NOCOMP_FL;
13f48dc90   Satoru Takeuchi   btrfs: Simplify c...
127
128
  	else if (flags & BTRFS_INODE_COMPRESS)
  		iflags |= FS_COMPR_FL;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
129
130
131
132
133
134
135
136
137
138
  
  	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);
3cc793925   Filipe Manana   Btrfs: atomically...
139
  	unsigned int new_fl = 0;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
140
141
  
  	if (ip->flags & BTRFS_INODE_SYNC)
3cc793925   Filipe Manana   Btrfs: atomically...
142
  		new_fl |= S_SYNC;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
143
  	if (ip->flags & BTRFS_INODE_IMMUTABLE)
3cc793925   Filipe Manana   Btrfs: atomically...
144
  		new_fl |= S_IMMUTABLE;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
145
  	if (ip->flags & BTRFS_INODE_APPEND)
3cc793925   Filipe Manana   Btrfs: atomically...
146
  		new_fl |= S_APPEND;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
147
  	if (ip->flags & BTRFS_INODE_NOATIME)
3cc793925   Filipe Manana   Btrfs: atomically...
148
  		new_fl |= S_NOATIME;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
149
  	if (ip->flags & BTRFS_INODE_DIRSYNC)
3cc793925   Filipe Manana   Btrfs: atomically...
150
151
152
153
154
  		new_fl |= S_DIRSYNC;
  
  	set_mask_bits(&inode->i_flags,
  		      S_SYNC | S_APPEND | S_IMMUTABLE | S_NOATIME | S_DIRSYNC,
  		      new_fl);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
155
156
157
158
159
  }
  
  /*
   * Inherit flags from the parent inode.
   *
e27425d61   Josef Bacik   Btrfs: only inher...
160
   * Currently only the compression flags and the cow flags are inherited.
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
161
162
163
   */
  void btrfs_inherit_iflags(struct inode *inode, struct inode *dir)
  {
0b4dcea57   Chris Mason   Btrfs: fix oops w...
164
165
166
167
168
169
  	unsigned int flags;
  
  	if (!dir)
  		return;
  
  	flags = BTRFS_I(dir)->flags;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
170

e27425d61   Josef Bacik   Btrfs: only inher...
171
172
173
174
175
176
177
  	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 ...
178
  	if (flags & BTRFS_INODE_NODATACOW) {
e27425d61   Josef Bacik   Btrfs: only inher...
179
  		BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
213490b30   Liu Bo   Btrfs: fix a bug ...
180
181
182
  		if (S_ISREG(inode->i_mode))
  			BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
183

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
184
185
186
187
188
  	btrfs_update_iflags(inode);
  }
  
  static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
189
  	struct btrfs_inode *ip = BTRFS_I(file_inode(file));
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
190
191
192
193
194
195
  	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...
196
197
198
199
200
  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
201
202
  		      FS_NOCOMP_FL | FS_COMPR_FL |
  		      FS_NOCOW_FL))
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
203
204
205
206
  		return -EOPNOTSUPP;
  
  	if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
  		return -EINVAL;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
207
208
  	return 0;
  }
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
209
210
  static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
211
  	struct inode *inode = file_inode(file);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
212
213
214
215
216
  	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...
217
218
  	u64 ip_oldflags;
  	unsigned int i_oldflags;
7e97b8daf   David Sterba   btrfs: allow sett...
219
  	umode_t mode;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
220

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

e7848683a   Jan Kara   btrfs: Push mnt_w...
231
232
233
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5955102c9   Al Viro   wrappers for ->i_...
234
  	inode_lock(inode);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
235

f062abf08   Li Zefan   Btrfs: remove BUG...
236
237
  	ip_oldflags = ip->flags;
  	i_oldflags = inode->i_flags;
7e97b8daf   David Sterba   btrfs: allow sett...
238
  	mode = inode->i_mode;
f062abf08   Li Zefan   Btrfs: remove BUG...
239

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
240
241
242
243
244
245
246
247
  	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 ...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  	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...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  	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 {
  		/*
013276101   Nicholas D Steeves   btrfs: fix string...
287
  		 * Revert back under same assumptions as above
7e97b8daf   David Sterba   btrfs: allow sett...
288
289
290
291
292
293
294
295
296
  		 */
  		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 ...
297

75e7cb7fe   Liu Bo   Btrfs: Per file/d...
298
299
300
301
302
303
304
305
  	/*
  	 * 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...
306
307
308
309
  
  		ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0);
  		if (ret && ret != -ENODATA)
  			goto out_drop;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
310
  	} else if (flags & FS_COMPR_FL) {
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
311
  		const char *comp;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
312
313
  		ip->flags |= BTRFS_INODE_COMPRESS;
  		ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
314
315
316
317
318
319
320
321
322
  
  		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...
323
  	} else {
78a017a2c   Filipe Manana   Btrfs: add missin...
324
325
326
  		ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0);
  		if (ret && ret != -ENODATA)
  			goto out_drop;
ebcb904df   Li Zefan   Btrfs: fix FS_IOC...
327
  		ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
328
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
329

4da6f1a33   Li Zefan   Btrfs: reserve me...
330
  	trans = btrfs_start_transaction(root, 1);
f062abf08   Li Zefan   Btrfs: remove BUG...
331
332
333
334
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_drop;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
335

306424cc8   Li Zefan   Btrfs: fix ctime ...
336
  	btrfs_update_iflags(inode);
0c4d2d95d   Josef Bacik   Btrfs: use i_vers...
337
  	inode_inc_iversion(inode);
c2050a454   Deepa Dinamani   fs: Replace curre...
338
  	inode->i_ctime = current_time(inode);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
339
  	ret = btrfs_update_inode(trans, root, inode);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
340

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
341
  	btrfs_end_transaction(trans, root);
f062abf08   Li Zefan   Btrfs: remove BUG...
342
343
344
345
346
   out_drop:
  	if (ret) {
  		ip->flags = ip_oldflags;
  		inode->i_flags = i_oldflags;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
347

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
348
   out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
349
  	inode_unlock(inode);
e7848683a   Jan Kara   btrfs: Push mnt_w...
350
  	mnt_drop_write_file(file);
2d4e6f6ad   liubo   Btrfs: fix return...
351
  	return ret;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
352
353
354
355
  }
  
  static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
356
  	struct inode *inode = file_inode(file);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
357
358
359
  
  	return put_user(inode->i_generation, arg);
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
360

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
361
362
  static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
  {
54563d41a   Al Viro   btrfs: get rid of...
363
  	struct btrfs_fs_info *fs_info = btrfs_sb(file_inode(file)->i_sb);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
364
365
366
367
368
  	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...
369
  	u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
370
371
372
373
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
1f78160ce   Xiao Guangrong   Btrfs: using rcu ...
374
375
376
  	rcu_read_lock();
  	list_for_each_entry_rcu(device, &fs_info->fs_devices->devices,
  				dev_list) {
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
377
378
379
380
381
382
383
384
385
  		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 ...
386
  	rcu_read_unlock();
f4c697e64   Lukas Czerner   btrfs: return EIN...
387

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
388
389
  	if (!num_devices)
  		return -EOPNOTSUPP;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
390
391
  	if (copy_from_user(&range, arg, sizeof(range)))
  		return -EFAULT;
e515c18bf   Lukas Czerner   btrfs: Return EIN...
392
393
  	if (range.start > total_bytes ||
  	    range.len < fs_info->sb->s_blocksize)
f4c697e64   Lukas Czerner   btrfs: return EIN...
394
  		return -EINVAL;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
395

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

49a3c4d9b   David Sterba   btrfs: use dynami...
441
442
443
  	root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
  	if (!root_item)
  		return -ENOMEM;
581bb0509   Li Zefan   Btrfs: Cache free...
444
  	ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
2fbe8c8ad   Al Viro   get rid of useles...
445
  	if (ret)
49a3c4d9b   David Sterba   btrfs: use dynami...
446
  		goto fail_free;
6a9122130   Josef Bacik   Btrfs: use dget_p...
447

e09fe2d21   Qu Wenruo   btrfs: Don't allo...
448
449
  	/*
  	 * Don't create subvolume whose level is not zero. Or qgroup will be
013276101   Nicholas D Steeves   btrfs: fix string...
450
  	 * screwed up since it assumes subvolume qgroup's level to be 0.
e09fe2d21   Qu Wenruo   btrfs: Don't allo...
451
  	 */
49a3c4d9b   David Sterba   btrfs: use dynami...
452
453
454
455
  	if (btrfs_qgroup_level(objectid)) {
  		ret = -ENOSPC;
  		goto fail_free;
  	}
e09fe2d21   Qu Wenruo   btrfs: Don't allo...
456

d5c120701   Miao Xie   Btrfs: fix wrong ...
457
  	btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
9ed74f2db   Josef Bacik   Btrfs: proper -EN...
458
  	/*
d5c120701   Miao Xie   Btrfs: fix wrong ...
459
460
  	 * The same as the snapshot creation, please see the comment
  	 * of create_snapshot().
9ed74f2db   Josef Bacik   Btrfs: proper -EN...
461
  	 */
d5c120701   Miao Xie   Btrfs: fix wrong ...
462
  	ret = btrfs_subvolume_reserve_metadata(root, &block_rsv,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
463
  					       8, &qgroup_reserved, false);
d5c120701   Miao Xie   Btrfs: fix wrong ...
464
  	if (ret)
49a3c4d9b   David Sterba   btrfs: use dynami...
465
  		goto fail_free;
d5c120701   Miao Xie   Btrfs: fix wrong ...
466
467
468
469
  
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
de6e82006   Liu Bo   Btrfs: release su...
470
471
  		btrfs_subvolume_release_metadata(root, &block_rsv,
  						 qgroup_reserved);
49a3c4d9b   David Sterba   btrfs: use dynami...
472
  		goto fail_free;
d5c120701   Miao Xie   Btrfs: fix wrong ...
473
474
475
  	}
  	trans->block_rsv = &block_rsv;
  	trans->bytes_reserved = block_rsv.size;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
476

8696c5330   Miao Xie   Btrfs: fix memory...
477
  	ret = btrfs_qgroup_inherit(trans, root->fs_info, 0, objectid, inherit);
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
478
479
  	if (ret)
  		goto fail;
4d75f8a9c   David Sterba   btrfs: remove blo...
480
  	leaf = btrfs_alloc_tree_block(trans, root, 0, objectid, NULL, 0, 0, 0);
8e8a1e31f   Josef Bacik   Btrfs: Fix a few ...
481
482
483
484
  	if (IS_ERR(leaf)) {
  		ret = PTR_ERR(leaf);
  		goto fail;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
485

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
486
  	memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header));
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
487
488
  	btrfs_set_header_bytenr(leaf, leaf->start);
  	btrfs_set_header_generation(leaf, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
489
  	btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
490
  	btrfs_set_header_owner(leaf, objectid);
0a4e55860   Ross Kirk   btrfs: remove unu...
491
  	write_extent_buffer(leaf, root->fs_info->fsid, btrfs_header_fsid(),
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
492
  			    BTRFS_FSID_SIZE);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
493
  	write_extent_buffer(leaf, root->fs_info->chunk_tree_uuid,
b308bc2f0   Geert Uytterhoeven   Btrfs: Make btrfs...
494
  			    btrfs_header_chunk_tree_uuid(leaf),
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
495
  			    BTRFS_UUID_SIZE);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
496
  	btrfs_mark_buffer_dirty(leaf);
49a3c4d9b   David Sterba   btrfs: use dynami...
497
  	inode_item = &root_item->inode;
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
498
499
500
  	btrfs_set_stack_inode_generation(inode_item, 1);
  	btrfs_set_stack_inode_size(inode_item, 3);
  	btrfs_set_stack_inode_nlink(inode_item, 1);
707e8a071   David Sterba   btrfs: use nodesi...
501
  	btrfs_set_stack_inode_nbytes(inode_item, root->nodesize);
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
502
  	btrfs_set_stack_inode_mode(inode_item, S_IFDIR | 0755);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
503

49a3c4d9b   David Sterba   btrfs: use dynami...
504
505
  	btrfs_set_root_flags(root_item, 0);
  	btrfs_set_root_limit(root_item, 0);
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
506
  	btrfs_set_stack_inode_flags(inode_item, BTRFS_INODE_ROOT_ITEM_INIT);
08fe4db17   Li Zefan   Btrfs: Fix uninit...
507

49a3c4d9b   David Sterba   btrfs: use dynami...
508
509
510
511
512
513
  	btrfs_set_root_bytenr(root_item, leaf->start);
  	btrfs_set_root_generation(root_item, trans->transid);
  	btrfs_set_root_level(root_item, 0);
  	btrfs_set_root_refs(root_item, 1);
  	btrfs_set_root_used(root_item, leaf->len);
  	btrfs_set_root_last_snapshot(root_item, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
514

49a3c4d9b   David Sterba   btrfs: use dynami...
515
516
  	btrfs_set_root_generation_v2(root_item,
  			btrfs_root_generation(root_item));
8ea05e3a4   Alexander Block   Btrfs: introduce ...
517
  	uuid_le_gen(&new_uuid);
49a3c4d9b   David Sterba   btrfs: use dynami...
518
519
520
521
522
523
  	memcpy(root_item->uuid, new_uuid.b, BTRFS_UUID_SIZE);
  	btrfs_set_stack_timespec_sec(&root_item->otime, cur_time.tv_sec);
  	btrfs_set_stack_timespec_nsec(&root_item->otime, cur_time.tv_nsec);
  	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 ...
524

925baeddc   Chris Mason   Btrfs: Start btre...
525
  	btrfs_tree_unlock(leaf);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
526
527
  	free_extent_buffer(leaf);
  	leaf = NULL;
49a3c4d9b   David Sterba   btrfs: use dynami...
528
  	btrfs_set_root_dirid(root_item, new_dirid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
529
530
  
  	key.objectid = objectid;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
531
  	key.offset = 0;
962a298f3   David Sterba   btrfs: kill the k...
532
  	key.type = BTRFS_ROOT_ITEM_KEY;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
533
  	ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
49a3c4d9b   David Sterba   btrfs: use dynami...
534
  				root_item);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
535
536
  	if (ret)
  		goto fail;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
537
538
  	key.offset = (u64)-1;
  	new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
79787eaab   Jeff Mahoney   btrfs: replace ma...
539
  	if (IS_ERR(new_root)) {
79787eaab   Jeff Mahoney   btrfs: replace ma...
540
  		ret = PTR_ERR(new_root);
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
541
  		btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
542
543
  		goto fail;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
544
545
  
  	btrfs_record_root_in_trans(trans, new_root);
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
546
  	ret = btrfs_create_subvol_root(trans, new_root, root, new_dirid);
ce598979b   Mark Fasheh   btrfs: Don't BUG_...
547
548
  	if (ret) {
  		/* We potentially lose an unused inode item here */
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
549
  		btrfs_abort_transaction(trans, ret);
ce598979b   Mark Fasheh   btrfs: Don't BUG_...
550
551
  		goto fail;
  	}
f32e48e92   Chandan Rajendra   Btrfs: Initialize...
552
553
554
  	mutex_lock(&new_root->objectid_mutex);
  	new_root->highest_objectid = new_dirid;
  	mutex_unlock(&new_root->objectid_mutex);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
555
556
557
  	/*
  	 * insert the directory item
  	 */
3de4586c5   Chris Mason   Btrfs: Allow subv...
558
  	ret = btrfs_set_inode_index(dir, &index);
79787eaab   Jeff Mahoney   btrfs: replace ma...
559
  	if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
560
  		btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
561
562
  		goto fail;
  	}
3de4586c5   Chris Mason   Btrfs: Allow subv...
563
564
  
  	ret = btrfs_insert_dir_item(trans, root,
16cdcec73   Miao Xie   btrfs: implement ...
565
  				    name, namelen, dir, &key,
3de4586c5   Chris Mason   Btrfs: Allow subv...
566
  				    BTRFS_FT_DIR, index);
79787eaab   Jeff Mahoney   btrfs: replace ma...
567
  	if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
568
  		btrfs_abort_transaction(trans, ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
569
  		goto fail;
79787eaab   Jeff Mahoney   btrfs: replace ma...
570
  	}
0660b5af3   Chris Mason   Btrfs: Add backre...
571

52c261799   Yan Zheng   Btrfs: update dir...
572
573
574
  	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...
575
  	ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
4df27c4d5   Yan, Zheng   Btrfs: change how...
576
  				 objectid, root->root_key.objectid,
33345d015   Li Zefan   Btrfs: Always use...
577
  				 btrfs_ino(dir), index, name, namelen);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
578
  	BUG_ON(ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
579

dd5f9615f   Stefan Behrens   Btrfs: maintain s...
580
  	ret = btrfs_uuid_tree_add(trans, root->fs_info->uuid_root,
49a3c4d9b   David Sterba   btrfs: use dynami...
581
  				  root_item->uuid, BTRFS_UUID_KEY_SUBVOL,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
582
583
  				  objectid);
  	if (ret)
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
584
  		btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
585

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
586
  fail:
49a3c4d9b   David Sterba   btrfs: use dynami...
587
  	kfree(root_item);
d5c120701   Miao Xie   Btrfs: fix wrong ...
588
589
  	trans->block_rsv = NULL;
  	trans->bytes_reserved = 0;
de6e82006   Liu Bo   Btrfs: release su...
590
  	btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
591
592
593
  	if (async_transid) {
  		*async_transid = trans->transid;
  		err = btrfs_commit_transaction_async(trans, root, 1);
00d71c9c1   Miao Xie   Btrfs: fix unclos...
594
595
  		if (err)
  			err = btrfs_commit_transaction(trans, root);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
596
597
598
  	} else {
  		err = btrfs_commit_transaction(trans, root);
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
599
600
  	if (err && !ret)
  		ret = err;
1a65e24b0   Chris Mason   Btrfs: move d_ins...
601

5662344b3   Tsutomu Itoh   Btrfs: fix error ...
602
603
  	if (!ret) {
  		inode = btrfs_lookup_dentry(dir, dentry);
de6e82006   Liu Bo   Btrfs: release su...
604
605
  		if (IS_ERR(inode))
  			return PTR_ERR(inode);
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
606
607
  		d_instantiate(dentry, inode);
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
608
  	return ret;
49a3c4d9b   David Sterba   btrfs: use dynami...
609
610
611
612
  
  fail_free:
  	kfree(root_item);
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
613
  }
9ea24bbe1   Filipe Manana   Btrfs: fix snapsh...
614
  static void btrfs_wait_for_no_snapshoting_writes(struct btrfs_root *root)
8257b2dc3   Miao Xie   Btrfs: introduce ...
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
  {
  	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...
630
631
632
633
  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 ...
634
  {
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
635
  	struct inode *inode;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
636
637
  	struct btrfs_pending_snapshot *pending_snapshot;
  	struct btrfs_trans_handle *trans;
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
638
  	int ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
639

27cdeb709   Miao Xie   Btrfs: use bitfie...
640
  	if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state))
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
641
  		return -EINVAL;
a1ee73626   David Sterba   btrfs: do an allo...
642
643
644
  	pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
  	if (!pending_snapshot)
  		return -ENOMEM;
b0c0ea633   David Sterba   btrfs: allocate r...
645
646
  	pending_snapshot->root_item = kzalloc(sizeof(struct btrfs_root_item),
  			GFP_NOFS);
8546b5705   David Sterba   btrfs: preallocat...
647
648
  	pending_snapshot->path = btrfs_alloc_path();
  	if (!pending_snapshot->root_item || !pending_snapshot->path) {
b0c0ea633   David Sterba   btrfs: allocate r...
649
650
651
  		ret = -ENOMEM;
  		goto free_pending;
  	}
8257b2dc3   Miao Xie   Btrfs: introduce ...
652
  	atomic_inc(&root->will_be_snapshoted);
4e857c58e   Peter Zijlstra   arch: Mass conver...
653
  	smp_mb__after_atomic();
9ea24bbe1   Filipe Manana   Btrfs: fix snapsh...
654
  	btrfs_wait_for_no_snapshoting_writes(root);
8257b2dc3   Miao Xie   Btrfs: introduce ...
655

6a03843df   Miao Xie   Btrfs: just flush...
656
657
  	ret = btrfs_start_delalloc_inodes(root, 0);
  	if (ret)
a1ee73626   David Sterba   btrfs: do an allo...
658
  		goto dec_and_free;
6a03843df   Miao Xie   Btrfs: just flush...
659

578def7c5   Filipe Manana   Btrfs: don't wait...
660
  	btrfs_wait_ordered_extents(root, -1, 0, (u64)-1);
6a03843df   Miao Xie   Btrfs: just flush...
661

66d8f3dd1   Miao Xie   Btrfs: add a new ...
662
663
  	btrfs_init_block_rsv(&pending_snapshot->block_rsv,
  			     BTRFS_BLOCK_RSV_TEMP);
d5c120701   Miao Xie   Btrfs: fix wrong ...
664
665
666
667
668
669
  	/*
  	 * 1 - parent dir inode
  	 * 2 - dir entries
  	 * 1 - root item
  	 * 2 - root ref/backref
  	 * 1 - root of snapshot
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
670
  	 * 1 - UUID item
d5c120701   Miao Xie   Btrfs: fix wrong ...
671
672
  	 */
  	ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
673
  					&pending_snapshot->block_rsv, 8,
ee3441b49   Jeff Mahoney   btrfs: fall back ...
674
675
  					&pending_snapshot->qgroup_reserved,
  					false);
d5c120701   Miao Xie   Btrfs: fix wrong ...
676
  	if (ret)
a1ee73626   David Sterba   btrfs: do an allo...
677
  		goto dec_and_free;
d5c120701   Miao Xie   Btrfs: fix wrong ...
678

3de4586c5   Chris Mason   Btrfs: Allow subv...
679
  	pending_snapshot->dentry = dentry;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
680
  	pending_snapshot->root = root;
b83cc9693   Li Zefan   Btrfs: Add readon...
681
  	pending_snapshot->readonly = readonly;
e9662f701   Miao Xie   Btrfs: remove unn...
682
  	pending_snapshot->dir = dir;
8696c5330   Miao Xie   Btrfs: fix memory...
683
  	pending_snapshot->inherit = inherit;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
684

d5c120701   Miao Xie   Btrfs: fix wrong ...
685
  	trans = btrfs_start_transaction(root, 0);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
686
687
688
689
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto fail;
  	}
8351583e3   Josef Bacik   Btrfs: protect th...
690
  	spin_lock(&root->fs_info->trans_lock);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
691
692
  	list_add(&pending_snapshot->list,
  		 &trans->transaction->pending_snapshots);
8351583e3   Josef Bacik   Btrfs: protect th...
693
  	spin_unlock(&root->fs_info->trans_lock);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
694
695
696
697
  	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...
698
699
  		if (ret)
  			ret = btrfs_commit_transaction(trans, root);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
700
701
702
703
  	} else {
  		ret = btrfs_commit_transaction(trans,
  					       root->fs_info->extent_root);
  	}
aec8030a8   Miao Xie   Btrfs: fix wrong ...
704
  	if (ret)
c37b2b626   Josef Bacik   Btrfs: do not bug...
705
  		goto fail;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
706
707
708
709
  
  	ret = pending_snapshot->error;
  	if (ret)
  		goto fail;
d37973082   Chris Mason   Revert "Btrfs: ra...
710
711
712
  	ret = btrfs_orphan_cleanup(pending_snapshot->snap);
  	if (ret)
  		goto fail;
2b0143b5c   David Howells   VFS: normal files...
713
  	inode = btrfs_lookup_dentry(d_inode(dentry->d_parent), dentry);
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
714
715
716
717
  	if (IS_ERR(inode)) {
  		ret = PTR_ERR(inode);
  		goto fail;
  	}
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
718

2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
719
720
721
  	d_instantiate(dentry, inode);
  	ret = 0;
  fail:
d5c120701   Miao Xie   Btrfs: fix wrong ...
722
723
724
  	btrfs_subvolume_release_metadata(BTRFS_I(dir)->root,
  					 &pending_snapshot->block_rsv,
  					 pending_snapshot->qgroup_reserved);
a1ee73626   David Sterba   btrfs: do an allo...
725
  dec_and_free:
9ea24bbe1   Filipe Manana   Btrfs: fix snapsh...
726
727
  	if (atomic_dec_and_test(&root->will_be_snapshoted))
  		wake_up_atomic_t(&root->will_be_snapshoted);
b0c0ea633   David Sterba   btrfs: allocate r...
728
729
  free_pending:
  	kfree(pending_snapshot->root_item);
8546b5705   David Sterba   btrfs: preallocat...
730
  	btrfs_free_path(pending_snapshot->path);
a1ee73626   David Sterba   btrfs: do an allo...
731
  	kfree(pending_snapshot);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
732
733
  	return ret;
  }
4260f7c75   Sage Weil   Btrfs: allow subv...
734
735
736
737
738
739
740
741
742
743
744
  /*  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
013276101   Nicholas D Steeves   btrfs: fix string...
745
   *  6. If the victim is append-only or immutable we can't do anything with
4260f7c75   Sage Weil   Btrfs: allow subv...
746
747
748
749
750
751
752
   *     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...
753
  static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
4260f7c75   Sage Weil   Btrfs: allow subv...
754
755
  {
  	int error;
2b0143b5c   David Howells   VFS: normal files...
756
  	if (d_really_is_negative(victim))
4260f7c75   Sage Weil   Btrfs: allow subv...
757
  		return -ENOENT;
2b0143b5c   David Howells   VFS: normal files...
758
  	BUG_ON(d_inode(victim->d_parent) != dir);
4fa6b5ecb   Jeff Layton   audit: overhaul _...
759
  	audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
4260f7c75   Sage Weil   Btrfs: allow subv...
760
761
762
763
764
765
  
  	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
  	if (error)
  		return error;
  	if (IS_APPEND(dir))
  		return -EPERM;
2b0143b5c   David Howells   VFS: normal files...
766
767
  	if (check_sticky(dir, d_inode(victim)) || IS_APPEND(d_inode(victim)) ||
  	    IS_IMMUTABLE(d_inode(victim)) || IS_SWAPFILE(d_inode(victim)))
4260f7c75   Sage Weil   Btrfs: allow subv...
768
769
  		return -EPERM;
  	if (isdir) {
e36cb0b89   David Howells   VFS: (Scripted) C...
770
  		if (!d_is_dir(victim))
4260f7c75   Sage Weil   Btrfs: allow subv...
771
772
773
  			return -ENOTDIR;
  		if (IS_ROOT(victim))
  			return -EBUSY;
e36cb0b89   David Howells   VFS: (Scripted) C...
774
  	} else if (d_is_dir(victim))
4260f7c75   Sage Weil   Btrfs: allow subv...
775
776
777
778
779
780
781
  		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...
782
783
784
  /* copy of may_create in fs/namei.c() */
  static inline int btrfs_may_create(struct inode *dir, struct dentry *child)
  {
2b0143b5c   David Howells   VFS: normal files...
785
  	if (d_really_is_positive(child))
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
786
787
788
789
790
791
792
793
794
795
796
  		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...
797
798
  static noinline int btrfs_mksubvol(struct path *parent,
  				   char *name, int namelen,
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
799
  				   struct btrfs_root *snap_src,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
800
  				   u64 *async_transid, bool readonly,
8696c5330   Miao Xie   Btrfs: fix memory...
801
  				   struct btrfs_qgroup_inherit *inherit)
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
802
  {
2b0143b5c   David Howells   VFS: normal files...
803
  	struct inode *dir  = d_inode(parent->dentry);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
804
805
  	struct dentry *dentry;
  	int error;
002354112   Al Viro   restore killabili...
806
807
808
  	error = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
  	if (error == -EINTR)
  		return error;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
809
810
811
812
813
  
  	dentry = lookup_one_len(name, parent->dentry, namelen);
  	error = PTR_ERR(dentry);
  	if (IS_ERR(dentry))
  		goto out_unlock;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
814
  	error = btrfs_may_create(dir, dentry);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
815
  	if (error)
a874a63e1   Liu Bo   Btrfs: check writ...
816
  		goto out_dput;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
817

9c52057c6   Chris Mason   Btrfs: fix hash o...
818
819
820
821
822
823
824
825
826
  	/*
  	 * 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...
827
828
829
830
  	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...
831
  	if (snap_src) {
e9662f701   Miao Xie   Btrfs: remove unn...
832
  		error = create_snapshot(snap_src, dir, dentry, name, namelen,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
833
  					async_transid, readonly, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
834
  	} else {
d5c120701   Miao Xie   Btrfs: fix wrong ...
835
836
  		error = create_subvol(dir, dentry, name, namelen,
  				      async_transid, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
837
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
838
839
840
841
  	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...
842
843
844
  out_dput:
  	dput(dentry);
  out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
845
  	inode_unlock(dir);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
846
847
  	return error;
  }
4cb5300bc   Chris Mason   Btrfs: add mount ...
848
849
850
851
852
853
854
  /*
   * 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
   */
aab110abc   David Sterba   btrfs: defrag, us...
855
  static int check_defrag_in_cache(struct inode *inode, u64 offset, u32 thresh)
4cb5300bc   Chris Mason   Btrfs: add mount ...
856
857
858
859
860
861
862
  {
  	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);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
863
  	em = lookup_extent_mapping(em_tree, offset, PAGE_SIZE);
4cb5300bc   Chris Mason   Btrfs: add mount ...
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
  	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,
aab110abc   David Sterba   btrfs: defrag, us...
890
  			    u64 *off, u32 thresh)
4cb5300bc   Chris Mason   Btrfs: add mount ...
891
892
893
  {
  	struct btrfs_path *path;
  	struct btrfs_key min_key;
4cb5300bc   Chris Mason   Btrfs: add mount ...
894
895
896
897
  	struct extent_buffer *leaf;
  	struct btrfs_file_extent_item *extent;
  	int type;
  	int ret;
a4689d2bd   David Sterba   btrfs: use btrfs_...
898
  	u64 ino = btrfs_ino(inode);
4cb5300bc   Chris Mason   Btrfs: add mount ...
899
900
901
902
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
a4689d2bd   David Sterba   btrfs: use btrfs_...
903
  	min_key.objectid = ino;
4cb5300bc   Chris Mason   Btrfs: add mount ...
904
905
  	min_key.type = BTRFS_EXTENT_DATA_KEY;
  	min_key.offset = *off;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
906
  	while (1) {
6174d3cb4   Filipe David Borba Manana   Btrfs: remove unu...
907
  		ret = btrfs_search_forward(root, &min_key, path, newer_than);
4cb5300bc   Chris Mason   Btrfs: add mount ...
908
909
  		if (ret != 0)
  			goto none;
f094c9bd3   Filipe Manana   Btrfs: less fs tr...
910
  process_slot:
a4689d2bd   David Sterba   btrfs: use btrfs_...
911
  		if (min_key.objectid != ino)
4cb5300bc   Chris Mason   Btrfs: add mount ...
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
  			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...
928
929
930
931
932
  		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 ...
933
934
935
936
937
938
939
940
941
942
  		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...
943
  static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start)
17ce6ef8d   Liu Bo   Btrfs: add a chec...
944
945
  {
  	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
6c282eb40   Li Zefan   Btrfs: fix defrag...
946
947
  	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
  	struct extent_map *em;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
948
  	u64 len = PAGE_SIZE;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
949

6c282eb40   Li Zefan   Btrfs: fix defrag...
950
951
952
953
  	/*
  	 * hopefully we have this extent in the tree already, try without
  	 * the full extent lock
  	 */
17ce6ef8d   Liu Bo   Btrfs: add a chec...
954
  	read_lock(&em_tree->lock);
6c282eb40   Li Zefan   Btrfs: fix defrag...
955
  	em = lookup_extent_mapping(em_tree, start, len);
17ce6ef8d   Liu Bo   Btrfs: add a chec...
956
  	read_unlock(&em_tree->lock);
6c282eb40   Li Zefan   Btrfs: fix defrag...
957
  	if (!em) {
308d9800b   Filipe Manana   Btrfs: cache exte...
958
959
  		struct extent_state *cached = NULL;
  		u64 end = start + len - 1;
6c282eb40   Li Zefan   Btrfs: fix defrag...
960
  		/* get the big lock and read metadata off disk */
ff13db41f   David Sterba   btrfs: drop unuse...
961
  		lock_extent_bits(io_tree, start, end, &cached);
6c282eb40   Li Zefan   Btrfs: fix defrag...
962
  		em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
308d9800b   Filipe Manana   Btrfs: cache exte...
963
  		unlock_extent_cached(io_tree, start, end, &cached, GFP_NOFS);
6c282eb40   Li Zefan   Btrfs: fix defrag...
964
965
966
967
968
969
970
  
  		if (IS_ERR(em))
  			return NULL;
  	}
  
  	return em;
  }
17ce6ef8d   Liu Bo   Btrfs: add a chec...
971

6c282eb40   Li Zefan   Btrfs: fix defrag...
972
973
974
975
976
977
978
979
980
981
  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);
e9512d72e   Chris Mason   Btrfs: fix autode...
982
983
984
  	if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE)
  		ret = false;
  	else if ((em->block_start + em->block_len == next->block_start) &&
ee22184b5   Byongho Lee   Btrfs: use linux/...
985
  		 (em->block_len > SZ_128K && next->block_len > SZ_128K))
6c282eb40   Li Zefan   Btrfs: fix defrag...
986
987
988
  		ret = false;
  
  	free_extent_map(next);
17ce6ef8d   Liu Bo   Btrfs: add a chec...
989
990
  	return ret;
  }
aab110abc   David Sterba   btrfs: defrag, us...
991
  static int should_defrag_range(struct inode *inode, u64 start, u32 thresh,
a43a21113   Andrew Mahone   btrfs: ignore unf...
992
993
  			       u64 *last_len, u64 *skip, u64 *defrag_end,
  			       int compress)
940100a4a   Chris Mason   Btrfs: be more se...
994
  {
6c282eb40   Li Zefan   Btrfs: fix defrag...
995
  	struct extent_map *em;
940100a4a   Chris Mason   Btrfs: be more se...
996
  	int ret = 1;
6c282eb40   Li Zefan   Btrfs: fix defrag...
997
  	bool next_mergeable = true;
4a3560c4f   Liu Bo   Btrfs: fix defrag...
998
  	bool prev_mergeable = true;
940100a4a   Chris Mason   Btrfs: be more se...
999
1000
  
  	/*
008873eaf   Li Zefan   Btrfs: honor exte...
1001
  	 * make sure that once we start defragging an extent, we keep on
940100a4a   Chris Mason   Btrfs: be more se...
1002
1003
1004
1005
1006
1007
  	 * defragging it
  	 */
  	if (start < *defrag_end)
  		return 1;
  
  	*skip = 0;
6c282eb40   Li Zefan   Btrfs: fix defrag...
1008
1009
1010
  	em = defrag_lookup_extent(inode, start);
  	if (!em)
  		return 0;
940100a4a   Chris Mason   Btrfs: be more se...
1011
1012
  
  	/* this will cover holes, and inline extents */
17ce6ef8d   Liu Bo   Btrfs: add a chec...
1013
  	if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
940100a4a   Chris Mason   Btrfs: be more se...
1014
  		ret = 0;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
1015
1016
  		goto out;
  	}
4a3560c4f   Liu Bo   Btrfs: fix defrag...
1017
1018
  	if (!*defrag_end)
  		prev_mergeable = false;
6c282eb40   Li Zefan   Btrfs: fix defrag...
1019
  	next_mergeable = defrag_check_next_extent(inode, em);
940100a4a   Chris Mason   Btrfs: be more se...
1020
  	/*
6c282eb40   Li Zefan   Btrfs: fix defrag...
1021
1022
  	 * 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...
1023
  	 */
a43a21113   Andrew Mahone   btrfs: ignore unf...
1024
  	if (!compress && (*last_len == 0 || *last_len >= thresh) &&
4a3560c4f   Liu Bo   Btrfs: fix defrag...
1025
  	    (em->len >= thresh || (!next_mergeable && !prev_mergeable)))
940100a4a   Chris Mason   Btrfs: be more se...
1026
  		ret = 0;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
1027
  out:
940100a4a   Chris Mason   Btrfs: be more se...
1028
1029
1030
1031
1032
1033
1034
1035
1036
  	/*
  	 * 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...
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
  		*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 ...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
  /*
   * 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...
1062
  				    unsigned long num_pages)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1063
  {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1064
1065
1066
1067
  	unsigned long file_end;
  	u64 isize = i_size_read(inode);
  	u64 page_start;
  	u64 page_end;
1f12bd063   Liu Bo   Btrfs: fix the mi...
1068
  	u64 page_cnt;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1069
1070
1071
  	int ret;
  	int i;
  	int i_done;
3eaa28852   Chris Mason   Btrfs: Fix the de...
1072
  	struct btrfs_ordered_extent *ordered;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1073
  	struct extent_state *cached_state = NULL;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1074
  	struct extent_io_tree *tree;
3b16a4e3c   Josef Bacik   Btrfs: use the in...
1075
  	gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1076

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1077
  	file_end = (isize - 1) >> PAGE_SHIFT;
1f12bd063   Liu Bo   Btrfs: fix the mi...
1078
1079
1080
1081
  	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 ...
1082
1083
  
  	ret = btrfs_delalloc_reserve_space(inode,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1084
1085
  			start_index << PAGE_SHIFT,
  			page_cnt << PAGE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1086
1087
  	if (ret)
  		return ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1088
  	i_done = 0;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1089
  	tree = &BTRFS_I(inode)->io_tree;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1090
1091
  
  	/* step one, lock all the pages */
1f12bd063   Liu Bo   Btrfs: fix the mi...
1092
  	for (i = 0; i < page_cnt; i++) {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1093
  		struct page *page;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1094
  again:
a94733d0b   Josef Bacik   Btrfs: use find_o...
1095
  		page = find_or_create_page(inode->i_mapping,
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1096
  					   start_index + i, mask);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1097
1098
  		if (!page)
  			break;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1099
  		page_start = page_offset(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1100
  		page_end = page_start + PAGE_SIZE - 1;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1101
  		while (1) {
308d9800b   Filipe Manana   Btrfs: cache exte...
1102
  			lock_extent_bits(tree, page_start, page_end,
ff13db41f   David Sterba   btrfs: drop unuse...
1103
  					 &cached_state);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1104
1105
  			ordered = btrfs_lookup_ordered_extent(inode,
  							      page_start);
308d9800b   Filipe Manana   Btrfs: cache exte...
1106
1107
  			unlock_extent_cached(tree, page_start, page_end,
  					     &cached_state, GFP_NOFS);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1108
1109
1110
1111
1112
1113
1114
  			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...
1115
1116
1117
1118
1119
1120
  			/*
  			 * we unlocked the page above, so we need check if
  			 * it was released or not.
  			 */
  			if (page->mapping != inode->i_mapping) {
  				unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1121
  				put_page(page);
1f12bd063   Liu Bo   Btrfs: fix the mi...
1122
1123
  				goto again;
  			}
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1124
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1125
1126
1127
1128
1129
  		if (!PageUptodate(page)) {
  			btrfs_readpage(NULL, page);
  			lock_page(page);
  			if (!PageUptodate(page)) {
  				unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1130
  				put_page(page);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1131
1132
1133
1134
  				ret = -EIO;
  				break;
  			}
  		}
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1135

600a45e1d   Miao Xie   Btrfs: fix deadlo...
1136
1137
  		if (page->mapping != inode->i_mapping) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1138
  			put_page(page);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1139
1140
  			goto again;
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
  		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]);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1158
  	page_end = page_offset(pages[i_done - 1]) + PAGE_SIZE;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1159
1160
  
  	lock_extent_bits(&BTRFS_I(inode)->io_tree,
ff13db41f   David Sterba   btrfs: drop unuse...
1161
  			 page_start, page_end - 1, &cached_state);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1162
1163
  	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
  			  page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
9e8a4a8b0   Liu Bo   Btrfs: use flag E...
1164
1165
  			  EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0,
  			  &cached_state, GFP_NOFS);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1166

1f12bd063   Liu Bo   Btrfs: fix the mi...
1167
  	if (i_done != page_cnt) {
9e0baf60d   Josef Bacik   Btrfs: fix enospc...
1168
1169
1170
  		spin_lock(&BTRFS_I(inode)->lock);
  		BTRFS_I(inode)->outstanding_extents++;
  		spin_unlock(&BTRFS_I(inode)->lock);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1171
  		btrfs_delalloc_release_space(inode,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1172
1173
  				start_index << PAGE_SHIFT,
  				(page_cnt - i_done) << PAGE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1174
  	}
9e8a4a8b0   Liu Bo   Btrfs: use flag E...
1175
  	set_extent_defrag(&BTRFS_I(inode)->io_tree, page_start, page_end - 1,
018ed4f78   David Sterba   btrfs: sink gfp p...
1176
  			  &cached_state);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
  
  	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]);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1188
  		put_page(pages[i]);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1189
1190
1191
1192
1193
  	}
  	return i_done;
  out:
  	for (i = 0; i < i_done; i++) {
  		unlock_page(pages[i]);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1194
  		put_page(pages[i]);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1195
  	}
7cf5b9765   Qu Wenruo   btrfs: qgroup: Cl...
1196
  	btrfs_delalloc_release_space(inode,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1197
1198
  			start_index << PAGE_SHIFT,
  			page_cnt << PAGE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1199
1200
1201
1202
1203
1204
1205
1206
1207
  	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 ...
1208
  	struct file_ra_state *ra = NULL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1209
  	unsigned long last_index;
151a31b25   Li Zefan   Btrfs: use i_size...
1210
  	u64 isize = i_size_read(inode);
940100a4a   Chris Mason   Btrfs: be more se...
1211
1212
1213
  	u64 last_len = 0;
  	u64 skip = 0;
  	u64 defrag_end = 0;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1214
  	u64 newer_off = range->start;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1215
  	unsigned long i;
008873eaf   Li Zefan   Btrfs: honor exte...
1216
  	unsigned long ra_index = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1217
  	int ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1218
  	int defrag_count = 0;
1a419d85a   Li Zefan   btrfs: Allow to s...
1219
  	int compress_type = BTRFS_COMPRESS_ZLIB;
aab110abc   David Sterba   btrfs: defrag, us...
1220
  	u32 extent_thresh = range->extent_thresh;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1221
  	unsigned long max_cluster = SZ_256K >> PAGE_SHIFT;
c41570c9d   Justin Maggard   btrfs: fix defrag...
1222
  	unsigned long cluster = max_cluster;
ee22184b5   Byongho Lee   Btrfs: use linux/...
1223
  	u64 new_align = ~((u64)SZ_128K - 1);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1224
  	struct page **pages = NULL;
0abd5b172   Liu Bo   Btrfs: return err...
1225
1226
1227
1228
1229
  	if (isize == 0)
  		return 0;
  
  	if (range->start >= isize)
  		return -EINVAL;
1a419d85a   Li Zefan   btrfs: Allow to s...
1230
1231
1232
1233
1234
1235
1236
  
  	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 ...
1237

0abd5b172   Liu Bo   Btrfs: return err...
1238
  	if (extent_thresh == 0)
ee22184b5   Byongho Lee   Btrfs: use linux/...
1239
  		extent_thresh = SZ_256K;
940100a4a   Chris Mason   Btrfs: be more se...
1240

4cb5300bc   Chris Mason   Btrfs: add mount ...
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
  	/*
  	 * 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...
1253
  	pages = kmalloc_array(max_cluster, sizeof(struct page *),
4cb5300bc   Chris Mason   Btrfs: add mount ...
1254
1255
1256
1257
1258
1259
1260
  			GFP_NOFS);
  	if (!pages) {
  		ret = -ENOMEM;
  		goto out_ra;
  	}
  
  	/* find the last page to defrag */
1e701a329   Chris Mason   Btrfs: add new de...
1261
  	if (range->start + range->len > range->start) {
151a31b25   Li Zefan   Btrfs: use i_size...
1262
  		last_index = min_t(u64, isize - 1,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1263
  			 range->start + range->len - 1) >> PAGE_SHIFT;
1e701a329   Chris Mason   Btrfs: add new de...
1264
  	} else {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1265
  		last_index = (isize - 1) >> PAGE_SHIFT;
1e701a329   Chris Mason   Btrfs: add new de...
1266
  	}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1267
1268
  	if (newer_than) {
  		ret = find_new_extents(root, inode, newer_than,
ee22184b5   Byongho Lee   Btrfs: use linux/...
1269
  				       &newer_off, SZ_64K);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1270
1271
1272
1273
1274
1275
  		if (!ret) {
  			range->start = newer_off;
  			/*
  			 * we always align our defrag to help keep
  			 * the extents in the file evenly spaced
  			 */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1276
  			i = (newer_off & new_align) >> PAGE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1277
1278
1279
  		} else
  			goto out_ra;
  	} else {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1280
  		i = range->start >> PAGE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1281
1282
  	}
  	if (!max_to_defrag)
070034bdf   chandan   Btrfs: btrfs_defr...
1283
  		max_to_defrag = last_index - i + 1;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1284

2a0f7f576   Li Zefan   Btrfs: fix recurs...
1285
1286
1287
1288
1289
1290
  	/*
  	 * 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 ...
1291
  	while (i <= last_index && defrag_count < max_to_defrag &&
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1292
  	       (i < DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE))) {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1293
1294
1295
1296
1297
1298
  		/*
  		 * 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...
1299
  		if (btrfs_defrag_cancelled(root->fs_info)) {
f14d104db   David Sterba   btrfs: switch mor...
1300
  			btrfs_debug(root->fs_info, "defrag_file cancelled");
210549ebe   David Sterba   btrfs: add cancel...
1301
1302
1303
  			ret = -EAGAIN;
  			break;
  		}
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1304
  		if (!should_defrag_range(inode, (u64)i << PAGE_SHIFT,
6c282eb40   Li Zefan   Btrfs: fix defrag...
1305
  					 extent_thresh, &last_len, &skip,
a43a21113   Andrew Mahone   btrfs: ignore unf...
1306
1307
  					 &defrag_end, range->flags &
  					 BTRFS_DEFRAG_RANGE_COMPRESS)) {
940100a4a   Chris Mason   Btrfs: be more se...
1308
1309
1310
1311
1312
  			unsigned long next;
  			/*
  			 * the should_defrag function tells us how much to skip
  			 * bump our counter by the suggested amount
  			 */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1313
  			next = DIV_ROUND_UP(skip, PAGE_SIZE);
940100a4a   Chris Mason   Btrfs: be more se...
1314
1315
1316
  			i = max(i + 1, next);
  			continue;
  		}
008873eaf   Li Zefan   Btrfs: honor exte...
1317
1318
  
  		if (!newer_than) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1319
1320
  			cluster = (PAGE_ALIGN(defrag_end) >>
  				   PAGE_SHIFT) - i;
008873eaf   Li Zefan   Btrfs: honor exte...
1321
1322
1323
1324
  			cluster = min(cluster, max_cluster);
  		} else {
  			cluster = max_cluster;
  		}
008873eaf   Li Zefan   Btrfs: honor exte...
1325
1326
1327
1328
  		if (i + cluster > ra_index) {
  			ra_index = max(i, ra_index);
  			btrfs_force_ra(inode->i_mapping, ra, file, ra_index,
  				       cluster);
e4826a5b2   chandan   Btrfs: btrfs_defr...
1329
  			ra_index += cluster;
008873eaf   Li Zefan   Btrfs: honor exte...
1330
  		}
940100a4a   Chris Mason   Btrfs: be more se...
1331

5955102c9   Al Viro   wrappers for ->i_...
1332
  		inode_lock(inode);
633085c79   Filipe David Borba Manana   Btrfs: reset forc...
1333
1334
  		if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
  			BTRFS_I(inode)->force_compress = compress_type;
008873eaf   Li Zefan   Btrfs: honor exte...
1335
  		ret = cluster_pages_for_defrag(inode, pages, i, cluster);
ecb8bea87   Liu Bo   Btrfs: fix race b...
1336
  		if (ret < 0) {
5955102c9   Al Viro   wrappers for ->i_...
1337
  			inode_unlock(inode);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1338
  			goto out_ra;
ecb8bea87   Liu Bo   Btrfs: fix race b...
1339
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1340
1341
  
  		defrag_count += ret;
d0e1d66b5   Namjae Jeon   writeback: remove...
1342
  		balance_dirty_pages_ratelimited(inode->i_mapping);
5955102c9   Al Viro   wrappers for ->i_...
1343
  		inode_unlock(inode);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1344
1345
1346
1347
  
  		if (newer_than) {
  			if (newer_off == (u64)-1)
  				break;
e1f041e14   Liu Bo   Btrfs: update to ...
1348
1349
  			if (ret > 0)
  				i += ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1350
  			newer_off = max(newer_off + 1,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1351
  					(u64)i << PAGE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1352

ee22184b5   Byongho Lee   Btrfs: use linux/...
1353
1354
  			ret = find_new_extents(root, inode, newer_than,
  					       &newer_off, SZ_64K);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1355
1356
  			if (!ret) {
  				range->start = newer_off;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1357
  				i = (newer_off & new_align) >> PAGE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1358
1359
  			} else {
  				break;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1360
  			}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1361
  		} else {
008873eaf   Li Zefan   Btrfs: honor exte...
1362
  			if (ret > 0) {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1363
  				i += ret;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1364
  				last_len += ret << PAGE_SHIFT;
008873eaf   Li Zefan   Btrfs: honor exte...
1365
  			} else {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1366
  				i++;
008873eaf   Li Zefan   Btrfs: honor exte...
1367
1368
  				last_len = 0;
  			}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1369
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1370
  	}
dec8ef905   Filipe Manana   Btrfs: correctly ...
1371
  	if ((range->flags & BTRFS_DEFRAG_RANGE_START_IO)) {
1e701a329   Chris Mason   Btrfs: add new de...
1372
  		filemap_flush(inode->i_mapping);
dec8ef905   Filipe Manana   Btrfs: correctly ...
1373
1374
1375
1376
  		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...
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
  
  	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...
1391
  	}
1a419d85a   Li Zefan   btrfs: Allow to s...
1392
  	if (range->compress_type == BTRFS_COMPRESS_LZO) {
2b0ce2c29   Mitch Harder   Btrfs: Check INCO...
1393
  		btrfs_set_fs_incompat(root->fs_info, COMPRESS_LZO);
1a419d85a   Li Zefan   btrfs: Allow to s...
1394
  	}
60ccf82f5   Diego Calleja   btrfs: fix memory...
1395
  	ret = defrag_count;
940100a4a   Chris Mason   Btrfs: be more se...
1396

4cb5300bc   Chris Mason   Btrfs: add mount ...
1397
  out_ra:
633085c79   Filipe David Borba Manana   Btrfs: reset forc...
1398
  	if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
5955102c9   Al Viro   wrappers for ->i_...
1399
  		inode_lock(inode);
633085c79   Filipe David Borba Manana   Btrfs: reset forc...
1400
  		BTRFS_I(inode)->force_compress = BTRFS_COMPRESS_NONE;
5955102c9   Al Viro   wrappers for ->i_...
1401
  		inode_unlock(inode);
633085c79   Filipe David Borba Manana   Btrfs: reset forc...
1402
  	}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1403
1404
1405
  	if (!file)
  		kfree(ra);
  	kfree(pages);
940100a4a   Chris Mason   Btrfs: be more se...
1406
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1407
  }
198605a8e   Miao Xie   Btrfs: get write ...
1408
  static noinline int btrfs_ioctl_resize(struct file *file,
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1409
  					void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1410
1411
1412
1413
  {
  	u64 new_size;
  	u64 old_size;
  	u64 devid = 1;
496ad9aa8   Al Viro   new helper: file_...
1414
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1415
1416
1417
1418
  	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...
1419
  	char *retptr;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1420
1421
  	char *devstr = NULL;
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1422
  	int mod = 0;
e441d54de   Chris Mason   Btrfs: add permis...
1423
1424
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
198605a8e   Miao Xie   Btrfs: get write ...
1425
1426
1427
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5ac00addc   Stefan Behrens   Btrfs: disallow m...
1428
1429
  	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
975476765   Miao Xie   Btrfs: fix missin...
1430
  		mnt_drop_write_file(file);
e57138b3e   Anand Jain   btrfs: return btr...
1431
  		return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1432
  	}
5ac00addc   Stefan Behrens   Btrfs: disallow m...
1433
  	mutex_lock(&root->fs_info->volume_mutex);
dae7b665c   Li Zefan   btrfs: use memdup...
1434
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1435
1436
1437
1438
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
  		goto out;
  	}
5516e5957   Mark Fasheh   Btrfs: Null termi...
1439
1440
  
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1441

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1442
1443
1444
  	sizestr = vol_args->name;
  	devstr = strchr(sizestr, ':');
  	if (devstr) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1445
1446
1447
  		sizestr = devstr + 1;
  		*devstr = '\0';
  		devstr = vol_args->name;
58dfae636   ZhangZhen   btrfs: replace si...
1448
1449
1450
  		ret = kstrtoull(devstr, 10, &devid);
  		if (ret)
  			goto out_free;
dfd79829b   Miao Xie   Btrfs: fix trivia...
1451
1452
1453
1454
  		if (!devid) {
  			ret = -EINVAL;
  			goto out_free;
  		}
efe120a06   Frank Holton   Btrfs: convert pr...
1455
  		btrfs_info(root->fs_info, "resizing devid %llu", devid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1456
  	}
dba60f3f5   Miao Xie   Btrfs: fix resize...
1457

aa1b8cd40   Stefan Behrens   Btrfs: pass fs_in...
1458
  	device = btrfs_find_device(root->fs_info, devid, NULL, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1459
  	if (!device) {
efe120a06   Frank Holton   Btrfs: convert pr...
1460
  		btrfs_info(root->fs_info, "resizer unable to find device %llu",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
1461
  		       devid);
dfd79829b   Miao Xie   Btrfs: fix trivia...
1462
  		ret = -ENODEV;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1463
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1464
  	}
dba60f3f5   Miao Xie   Btrfs: fix resize...
1465
1466
  
  	if (!device->writeable) {
efe120a06   Frank Holton   Btrfs: convert pr...
1467
1468
  		btrfs_info(root->fs_info,
  			   "resizer unable to apply on readonly device %llu",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
1469
  		       devid);
dfd79829b   Miao Xie   Btrfs: fix trivia...
1470
  		ret = -EPERM;
4e42ae1bd   Liu Bo   Btrfs: do not res...
1471
1472
  		goto out_free;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
  	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...
1483
1484
  		new_size = memparse(sizestr, &retptr);
  		if (*retptr != '\0' || new_size == 0) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1485
  			ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1486
  			goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1487
1488
  		}
  	}
63a212abc   Stefan Behrens   Btrfs: disallow s...
1489
  	if (device->is_tgtdev_for_dev_replace) {
dfd79829b   Miao Xie   Btrfs: fix trivia...
1490
  		ret = -EPERM;
63a212abc   Stefan Behrens   Btrfs: disallow s...
1491
1492
  		goto out_free;
  	}
7cc8e58d5   Miao Xie   Btrfs: fix unprot...
1493
  	old_size = btrfs_device_get_total_bytes(device);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1494
1495
1496
1497
  
  	if (mod < 0) {
  		if (new_size > old_size) {
  			ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1498
  			goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1499
1500
1501
  		}
  		new_size = old_size - new_size;
  	} else if (mod > 0) {
eb8052e01   Wenliang Fan   fs/btrfs: Integer...
1502
  		if (new_size > ULLONG_MAX - old_size) {
902c68a4d   Gui Hecheng   btrfs: replace EI...
1503
  			ret = -ERANGE;
eb8052e01   Wenliang Fan   fs/btrfs: Integer...
1504
1505
  			goto out_free;
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1506
1507
  		new_size = old_size + new_size;
  	}
ee22184b5   Byongho Lee   Btrfs: use linux/...
1508
  	if (new_size < SZ_256M) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1509
  		ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1510
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1511
1512
1513
  	}
  	if (new_size > device->bdev->bd_inode->i_size) {
  		ret = -EFBIG;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1514
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1515
  	}
b8b93addd   David Sterba   btrfs: cleanup 64...
1516
  	new_size = div_u64(new_size, root->sectorsize);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1517
  	new_size *= root->sectorsize;
ecaeb14b9   David Sterba   btrfs: switch mes...
1518
  	btrfs_info_in_rcu(root->fs_info, "new size for %s is %llu",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
1519
  		      rcu_str_deref(device->name), new_size);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1520
1521
  
  	if (new_size > old_size) {
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
1522
  		trans = btrfs_start_transaction(root, 0);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
1523
1524
  		if (IS_ERR(trans)) {
  			ret = PTR_ERR(trans);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1525
  			goto out_free;
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
1526
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1527
1528
  		ret = btrfs_grow_device(trans, device, new_size);
  		btrfs_commit_transaction(trans, root);
ece7d20e8   Mike Fleetwood   Btrfs: Don't erro...
1529
  	} else if (new_size < old_size) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1530
  		ret = btrfs_shrink_device(device, new_size);
0253f40ef   jeff.liu   Btrfs: Remove the...
1531
  	} /* equal, nothing need to do */
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1532

c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1533
  out_free:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1534
  	kfree(vol_args);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1535
1536
  out:
  	mutex_unlock(&root->fs_info->volume_mutex);
5ac00addc   Stefan Behrens   Btrfs: disallow m...
1537
  	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
18f39c416   Ilya Dryomov   Btrfs: fix unlock...
1538
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1539
1540
  	return ret;
  }
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1541
  static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1542
1543
  				char *name, unsigned long fd, int subvol,
  				u64 *transid, bool readonly,
8696c5330   Miao Xie   Btrfs: fix memory...
1544
  				struct btrfs_qgroup_inherit *inherit)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1545
  {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1546
  	int namelen;
3de4586c5   Chris Mason   Btrfs: Allow subv...
1547
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1548

325c50e3c   Jeff Mahoney   btrfs: ensure tha...
1549
1550
  	if (!S_ISDIR(file_inode(file)->i_mode))
  		return -ENOTDIR;
a874a63e1   Liu Bo   Btrfs: check writ...
1551
1552
1553
  	ret = mnt_want_write_file(file);
  	if (ret)
  		goto out;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1554
1555
  	namelen = strlen(name);
  	if (strchr(name, '/')) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1556
  		ret = -EINVAL;
a874a63e1   Liu Bo   Btrfs: check writ...
1557
  		goto out_drop_write;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1558
  	}
16780cabb   Chris Mason   Btrfs: add extra ...
1559
1560
1561
  	if (name[0] == '.' &&
  	   (namelen == 1 || (name[1] == '.' && namelen == 2))) {
  		ret = -EEXIST;
a874a63e1   Liu Bo   Btrfs: check writ...
1562
  		goto out_drop_write;
16780cabb   Chris Mason   Btrfs: add extra ...
1563
  	}
3de4586c5   Chris Mason   Btrfs: Allow subv...
1564
  	if (subvol) {
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1565
  		ret = btrfs_mksubvol(&file->f_path, name, namelen,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1566
  				     NULL, transid, readonly, inherit);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
1567
  	} else {
2903ff019   Al Viro   switch simple cas...
1568
  		struct fd src = fdget(fd);
3de4586c5   Chris Mason   Btrfs: Allow subv...
1569
  		struct inode *src_inode;
2903ff019   Al Viro   switch simple cas...
1570
  		if (!src.file) {
3de4586c5   Chris Mason   Btrfs: Allow subv...
1571
  			ret = -EINVAL;
a874a63e1   Liu Bo   Btrfs: check writ...
1572
  			goto out_drop_write;
3de4586c5   Chris Mason   Btrfs: Allow subv...
1573
  		}
496ad9aa8   Al Viro   new helper: file_...
1574
1575
  		src_inode = file_inode(src.file);
  		if (src_inode->i_sb != file_inode(file)->i_sb) {
c79b47133   Josef Bacik   Btrfs: don't use ...
1576
  			btrfs_info(BTRFS_I(file_inode(file))->root->fs_info,
efe120a06   Frank Holton   Btrfs: convert pr...
1577
  				   "Snapshot src from another FS");
23ad5b17d   Kusanagi Kouichi   btrfs: Return EXD...
1578
  			ret = -EXDEV;
d02420613   David Sterba   btrfs: restrict s...
1579
1580
1581
1582
1583
1584
  		} 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...
1585
1586
1587
1588
  		} else {
  			ret = btrfs_mksubvol(&file->f_path, name, namelen,
  					     BTRFS_I(src_inode)->root,
  					     transid, readonly, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
1589
  		}
2903ff019   Al Viro   switch simple cas...
1590
  		fdput(src);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
1591
  	}
a874a63e1   Liu Bo   Btrfs: check writ...
1592
1593
  out_drop_write:
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1594
  out:
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1595
1596
1597
1598
  	return ret;
  }
  
  static noinline int btrfs_ioctl_snap_create(struct file *file,
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1599
  					    void __user *arg, int subvol)
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1600
  {
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1601
  	struct btrfs_ioctl_vol_args *vol_args;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1602
  	int ret;
325c50e3c   Jeff Mahoney   btrfs: ensure tha...
1603
1604
  	if (!S_ISDIR(file_inode(file)->i_mode))
  		return -ENOTDIR;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1605
1606
1607
1608
  	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...
1609

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

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1614
1615
1616
  	kfree(vol_args);
  	return ret;
  }
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1617

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1618
1619
1620
1621
1622
1623
1624
  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...
1625
  	bool readonly = false;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1626
  	struct btrfs_qgroup_inherit *inherit = NULL;
75eaa0e22   Sage Weil   Btrfs: fix sync s...
1627

325c50e3c   Jeff Mahoney   btrfs: ensure tha...
1628
1629
  	if (!S_ISDIR(file_inode(file)->i_mode))
  		return -ENOTDIR;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1630
1631
1632
1633
  	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...
1634

b83cc9693   Li Zefan   Btrfs: Add readon...
1635
  	if (vol_args->flags &
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1636
1637
  	    ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY |
  	      BTRFS_SUBVOL_QGROUP_INHERIT)) {
b83cc9693   Li Zefan   Btrfs: Add readon...
1638
  		ret = -EOPNOTSUPP;
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1639
  		goto free_args;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1640
  	}
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1641
1642
1643
  
  	if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
  		ptr = &transid;
b83cc9693   Li Zefan   Btrfs: Add readon...
1644
1645
  	if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
  		readonly = true;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1646
  	if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1647
  		if (vol_args->size > PAGE_SIZE) {
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1648
  			ret = -EINVAL;
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1649
  			goto free_args;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1650
1651
1652
1653
  		}
  		inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size);
  		if (IS_ERR(inherit)) {
  			ret = PTR_ERR(inherit);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1654
  			goto free_args;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1655
1656
  		}
  	}
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1657
1658
  
  	ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1659
  					      vol_args->fd, subvol, ptr,
8696c5330   Miao Xie   Btrfs: fix memory...
1660
  					      readonly, inherit);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1661
1662
  	if (ret)
  		goto free_inherit;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1663

c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1664
1665
1666
1667
  	if (ptr && copy_to_user(arg +
  				offsetof(struct btrfs_ioctl_vol_args_v2,
  					transid),
  				ptr, sizeof(*ptr)))
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1668
  		ret = -EFAULT;
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1669
1670
  
  free_inherit:
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1671
  	kfree(inherit);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1672
1673
  free_args:
  	kfree(vol_args);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1674
1675
  	return ret;
  }
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1676
1677
1678
  static noinline int btrfs_ioctl_subvol_getflags(struct file *file,
  						void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
1679
  	struct inode *inode = file_inode(file);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1680
1681
1682
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret = 0;
  	u64 flags = 0;
33345d015   Li Zefan   Btrfs: Always use...
1683
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID)
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
  		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_...
1700
  	struct inode *inode = file_inode(file);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1701
1702
1703
1704
1705
  	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...
1706
1707
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
b9ca0664d   Liu Bo   Btrfs: do not set...
1708
1709
1710
  	ret = mnt_want_write_file(file);
  	if (ret)
  		goto out;
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1711

b9ca0664d   Liu Bo   Btrfs: do not set...
1712
1713
1714
1715
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
  		ret = -EINVAL;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1716

b9ca0664d   Liu Bo   Btrfs: do not set...
1717
1718
1719
1720
  	if (copy_from_user(&flags, arg, sizeof(flags))) {
  		ret = -EFAULT;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1721

b9ca0664d   Liu Bo   Btrfs: do not set...
1722
1723
1724
1725
  	if (flags & BTRFS_SUBVOL_CREATE_ASYNC) {
  		ret = -EINVAL;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1726

b9ca0664d   Liu Bo   Btrfs: do not set...
1727
1728
1729
1730
  	if (flags & ~BTRFS_SUBVOL_RDONLY) {
  		ret = -EOPNOTSUPP;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1731
1732
1733
1734
1735
  
  	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...
1736
  		goto out_drop_sem;
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1737
1738
  
  	root_flags = btrfs_root_flags(&root->root_item);
2c6865378   David Sterba   btrfs: Check read...
1739
  	if (flags & BTRFS_SUBVOL_RDONLY) {
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1740
1741
  		btrfs_set_root_flags(&root->root_item,
  				     root_flags | BTRFS_ROOT_SUBVOL_RDONLY);
2c6865378   David Sterba   btrfs: Check read...
1742
1743
1744
1745
1746
1747
1748
1749
  	} 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_...
1750
  				     root_flags & ~BTRFS_ROOT_SUBVOL_RDONLY);
2c6865378   David Sterba   btrfs: Check read...
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
  			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_...
1761
1762
1763
1764
1765
1766
  
  	trans = btrfs_start_transaction(root, 1);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_reset;
  	}
b4dc2b8c6   Li Zefan   Btrfs: Fix BTRFS_...
1767
  	ret = btrfs_update_root(trans, root->fs_info->tree_root,
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1768
1769
1770
1771
1772
1773
  				&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...
1774
  out_drop_sem:
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1775
  	up_write(&root->fs_info->subvol_sem);
b9ca0664d   Liu Bo   Btrfs: do not set...
1776
1777
1778
  out_drop_write:
  	mnt_drop_write_file(file);
  out:
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1779
1780
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1781
1782
1783
1784
1785
1786
  /*
   * 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...
1787
  	struct btrfs_dir_item *di;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1788
  	struct btrfs_key key;
175a2b871   Josef Bacik   Btrfs: don't allo...
1789
  	u64 dir_id;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1790
1791
1792
1793
1794
  	int ret;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
175a2b871   Josef Bacik   Btrfs: don't allo...
1795
1796
1797
1798
1799
1800
1801
  	/* 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...
1802
  			ret = -EPERM;
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
1803
1804
1805
  			btrfs_err(root->fs_info,
  				  "deleting default subvolume %llu is not allowed",
  				  key.objectid);
175a2b871   Josef Bacik   Btrfs: don't allo...
1806
1807
1808
1809
  			goto out;
  		}
  		btrfs_release_path(path);
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
  	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...
1832
1833
1834
  static noinline int key_in_sk(struct btrfs_key *key,
  			      struct btrfs_ioctl_search_key *sk)
  {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1835
1836
1837
1838
1839
1840
1841
1842
1843
  	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...
1844
  		return 0;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1845
1846
1847
1848
1849
1850
1851
  
  	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...
1852
1853
1854
  		return 0;
  	return 1;
  }
df3975652   Jeff Mahoney   btrfs: copy_to_sk...
1855
  static noinline int copy_to_sk(struct btrfs_path *path,
ac8e9819d   Chris Mason   Btrfs: add search...
1856
1857
  			       struct btrfs_key *key,
  			       struct btrfs_ioctl_search_key *sk,
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1858
  			       size_t *buf_size,
ba346b357   Gerhard Heift   btrfs: tree_searc...
1859
  			       char __user *ubuf,
ac8e9819d   Chris Mason   Btrfs: add search...
1860
1861
1862
1863
1864
1865
  			       unsigned long *sk_offset,
  			       int *num_found)
  {
  	u64 found_transid;
  	struct extent_buffer *leaf;
  	struct btrfs_ioctl_search_header sh;
dd81d459a   Naohiro Aota   btrfs: fix search...
1866
  	struct btrfs_key test;
ac8e9819d   Chris Mason   Btrfs: add search...
1867
1868
1869
1870
1871
  	unsigned long item_off;
  	unsigned long item_len;
  	int nritems;
  	int i;
  	int slot;
ac8e9819d   Chris Mason   Btrfs: add search...
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
  	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...
1887
1888
1889
  		btrfs_item_key_to_cpu(leaf, key, i);
  		if (!key_in_sk(key, sk))
  			continue;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1890
  		if (sizeof(sh) + item_len > *buf_size) {
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
1891
1892
1893
1894
1895
1896
1897
1898
1899
  			if (*num_found) {
  				ret = 1;
  				goto out;
  			}
  
  			/*
  			 * return one empty item back for v1, which does not
  			 * handle -EOVERFLOW
  			 */
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1900
  			*buf_size = sizeof(sh) + item_len;
ac8e9819d   Chris Mason   Btrfs: add search...
1901
  			item_len = 0;
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
1902
1903
  			ret = -EOVERFLOW;
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1904

9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1905
  		if (sizeof(sh) + item_len + *sk_offset > *buf_size) {
ac8e9819d   Chris Mason   Btrfs: add search...
1906
  			ret = 1;
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
1907
  			goto out;
ac8e9819d   Chris Mason   Btrfs: add search...
1908
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1909
1910
1911
1912
1913
1914
1915
  		sh.objectid = key->objectid;
  		sh.offset = key->offset;
  		sh.type = key->type;
  		sh.len = item_len;
  		sh.transid = found_transid;
  
  		/* copy search result header */
ba346b357   Gerhard Heift   btrfs: tree_searc...
1916
1917
1918
1919
  		if (copy_to_user(ubuf + *sk_offset, &sh, sizeof(sh))) {
  			ret = -EFAULT;
  			goto out;
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1920
1921
1922
  		*sk_offset += sizeof(sh);
  
  		if (item_len) {
ba346b357   Gerhard Heift   btrfs: tree_searc...
1923
  			char __user *up = ubuf + *sk_offset;
ac8e9819d   Chris Mason   Btrfs: add search...
1924
  			/* copy the item */
ba346b357   Gerhard Heift   btrfs: tree_searc...
1925
1926
1927
1928
1929
  			if (read_extent_buffer_to_user(leaf, up,
  						       item_off, item_len)) {
  				ret = -EFAULT;
  				goto out;
  			}
ac8e9819d   Chris Mason   Btrfs: add search...
1930
  			*sk_offset += item_len;
ac8e9819d   Chris Mason   Btrfs: add search...
1931
  		}
e21568671   Hugo Mills   btrfs: Ensure the...
1932
  		(*num_found)++;
ac8e9819d   Chris Mason   Btrfs: add search...
1933

8f5f6178f   Gerhard Heift   btrfs: tree_searc...
1934
1935
  		if (ret) /* -EOVERFLOW from above */
  			goto out;
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
1936
1937
1938
1939
  		if (*num_found >= sk->nr_items) {
  			ret = 1;
  			goto out;
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1940
1941
  	}
  advance_key:
abc6e1341   Chris Mason   Btrfs: fix key ch...
1942
  	ret = 0;
dd81d459a   Naohiro Aota   btrfs: fix search...
1943
1944
1945
1946
1947
1948
  	test.objectid = sk->max_objectid;
  	test.type = sk->max_type;
  	test.offset = sk->max_offset;
  	if (btrfs_comp_cpu_keys(key, &test) >= 0)
  		ret = 1;
  	else if (key->offset < (u64)-1)
ac8e9819d   Chris Mason   Btrfs: add search...
1949
  		key->offset++;
dd81d459a   Naohiro Aota   btrfs: fix search...
1950
  	else if (key->type < (u8)-1) {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1951
  		key->offset = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1952
  		key->type++;
dd81d459a   Naohiro Aota   btrfs: fix search...
1953
  	} else if (key->objectid < (u64)-1) {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1954
1955
  		key->offset = 0;
  		key->type = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1956
  		key->objectid++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1957
1958
  	} else
  		ret = 1;
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
1959
  out:
ba346b357   Gerhard Heift   btrfs: tree_searc...
1960
1961
1962
1963
1964
1965
1966
1967
1968
  	/*
  	 *  0: all items from this leaf copied, continue with next
  	 *  1: * more items can be copied, but unused buffer is too small
  	 *     * all items were found
  	 *     Either way, it will stops the loop which iterates to the next
  	 *     leaf
  	 *  -EOVERFLOW: item was to large for buffer
  	 *  -EFAULT: could not copy extent buffer back to userspace
  	 */
ac8e9819d   Chris Mason   Btrfs: add search...
1969
1970
1971
1972
  	return ret;
  }
  
  static noinline int search_ioctl(struct inode *inode,
125444428   Gerhard Heift   btrfs: tree_searc...
1973
  				 struct btrfs_ioctl_search_key *sk,
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1974
  				 size_t *buf_size,
ba346b357   Gerhard Heift   btrfs: tree_searc...
1975
  				 char __user *ubuf)
ac8e9819d   Chris Mason   Btrfs: add search...
1976
1977
1978
  {
  	struct btrfs_root *root;
  	struct btrfs_key key;
ac8e9819d   Chris Mason   Btrfs: add search...
1979
  	struct btrfs_path *path;
ac8e9819d   Chris Mason   Btrfs: add search...
1980
1981
1982
1983
  	struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info;
  	int ret;
  	int num_found = 0;
  	unsigned long sk_offset = 0;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1984
1985
  	if (*buf_size < sizeof(struct btrfs_ioctl_search_header)) {
  		*buf_size = sizeof(struct btrfs_ioctl_search_header);
125444428   Gerhard Heift   btrfs: tree_searc...
1986
  		return -EOVERFLOW;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1987
  	}
125444428   Gerhard Heift   btrfs: tree_searc...
1988

ac8e9819d   Chris Mason   Btrfs: add search...
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
  	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)) {
ac8e9819d   Chris Mason   Btrfs: add search...
2002
2003
2004
2005
2006
2007
2008
2009
  			btrfs_free_path(path);
  			return -ENOENT;
  		}
  	}
  
  	key.objectid = sk->min_objectid;
  	key.type = sk->min_type;
  	key.offset = sk->min_offset;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2010
  	while (1) {
6174d3cb4   Filipe David Borba Manana   Btrfs: remove unu...
2011
  		ret = btrfs_search_forward(root, &key, path, sk->min_transid);
ac8e9819d   Chris Mason   Btrfs: add search...
2012
2013
2014
2015
2016
  		if (ret != 0) {
  			if (ret > 0)
  				ret = 0;
  			goto err;
  		}
df3975652   Jeff Mahoney   btrfs: copy_to_sk...
2017
  		ret = copy_to_sk(path, &key, sk, buf_size, ubuf,
ac8e9819d   Chris Mason   Btrfs: add search...
2018
  				 &sk_offset, &num_found);
b3b4aa74b   David Sterba   btrfs: drop unuse...
2019
  		btrfs_release_path(path);
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
2020
  		if (ret)
ac8e9819d   Chris Mason   Btrfs: add search...
2021
2022
2023
  			break;
  
  	}
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
2024
2025
  	if (ret > 0)
  		ret = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
2026
2027
2028
2029
2030
2031
2032
2033
2034
  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)
  {
ba346b357   Gerhard Heift   btrfs: tree_searc...
2035
2036
  	struct btrfs_ioctl_search_args __user *uargs;
  	struct btrfs_ioctl_search_key sk;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
2037
2038
2039
  	struct inode *inode;
  	int ret;
  	size_t buf_size;
ac8e9819d   Chris Mason   Btrfs: add search...
2040
2041
2042
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
ba346b357   Gerhard Heift   btrfs: tree_searc...
2043
2044
2045
2046
  	uargs = (struct btrfs_ioctl_search_args __user *)argp;
  
  	if (copy_from_user(&sk, &uargs->key, sizeof(sk)))
  		return -EFAULT;
ac8e9819d   Chris Mason   Btrfs: add search...
2047

ba346b357   Gerhard Heift   btrfs: tree_searc...
2048
  	buf_size = sizeof(uargs->buf);
ac8e9819d   Chris Mason   Btrfs: add search...
2049

496ad9aa8   Al Viro   new helper: file_...
2050
  	inode = file_inode(file);
ba346b357   Gerhard Heift   btrfs: tree_searc...
2051
  	ret = search_ioctl(inode, &sk, &buf_size, uargs->buf);
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
2052
2053
2054
2055
2056
2057
2058
  
  	/*
  	 * In the origin implementation an overflow is handled by returning a
  	 * search header with a len of zero, so reset ret.
  	 */
  	if (ret == -EOVERFLOW)
  		ret = 0;
ba346b357   Gerhard Heift   btrfs: tree_searc...
2059
  	if (ret == 0 && copy_to_user(&uargs->key, &sk, sizeof(sk)))
ac8e9819d   Chris Mason   Btrfs: add search...
2060
  		ret = -EFAULT;
ac8e9819d   Chris Mason   Btrfs: add search...
2061
2062
  	return ret;
  }
cc68a8a5a   Gerhard Heift   btrfs: new ioctl ...
2063
2064
2065
2066
2067
2068
2069
2070
  static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
  					       void __user *argp)
  {
  	struct btrfs_ioctl_search_args_v2 __user *uarg;
  	struct btrfs_ioctl_search_args_v2 args;
  	struct inode *inode;
  	int ret;
  	size_t buf_size;
ee22184b5   Byongho Lee   Btrfs: use linux/...
2071
  	const size_t buf_limit = SZ_16M;
cc68a8a5a   Gerhard Heift   btrfs: new ioctl ...
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	/* copy search header and buffer size */
  	uarg = (struct btrfs_ioctl_search_args_v2 __user *)argp;
  	if (copy_from_user(&args, uarg, sizeof(args)))
  		return -EFAULT;
  
  	buf_size = args.buf_size;
  
  	if (buf_size < sizeof(struct btrfs_ioctl_search_header))
  		return -EOVERFLOW;
  
  	/* limit result size to 16MB */
  	if (buf_size > buf_limit)
  		buf_size = buf_limit;
  
  	inode = file_inode(file);
  	ret = search_ioctl(inode, &args.key, &buf_size,
  			   (char *)(&uarg->buf[0]));
  	if (ret == 0 && copy_to_user(&uarg->key, &args.key, sizeof(args.key)))
  		ret = -EFAULT;
  	else if (ret == -EOVERFLOW &&
  		copy_to_user(&uarg->buf_size, &buf_size, sizeof(buf_size)))
  		ret = -EFAULT;
ac8e9819d   Chris Mason   Btrfs: add search...
2098
2099
  	return ret;
  }
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2100
  /*
ac8e9819d   Chris Mason   Btrfs: add search...
2101
2102
2103
   * 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...
2104
2105
2106
2107
2108
  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...
2109
  	char *ptr;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
  	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...
2126
  	ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX];
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2127
2128
2129
2130
2131
2132
  
  	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)) {
f14d104db   David Sterba   btrfs: switch mor...
2133
  		btrfs_err(info, "could not find root %llu", tree_id);
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2134
2135
  		ret = -ENOENT;
  		goto out;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2136
2137
2138
2139
  	}
  
  	key.objectid = dirid;
  	key.type = BTRFS_INODE_REF_KEY;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2140
  	key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2141

678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2142
  	while (1) {
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2143
2144
2145
  		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  		if (ret < 0)
  			goto out;
18674c6cc   Filipe David Borba Manana   Btrfs: don't miss...
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
  		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...
2156
2157
2158
2159
  
  		l = path->nodes[0];
  		slot = path->slots[0];
  		btrfs_item_key_to_cpu(l, &key, slot);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2160
2161
2162
2163
  		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...
2164
2165
  		if (ptr < name) {
  			ret = -ENAMETOOLONG;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2166
  			goto out;
a696cf352   Filipe David Borba Manana   Btrfs: add missin...
2167
  		}
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2168
2169
  
  		*(ptr + len) = '/';
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2170
  		read_extent_buffer(l, ptr, (unsigned long)(iref + 1), len);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2171
2172
2173
  
  		if (key.offset == BTRFS_FIRST_FREE_OBJECTID)
  			break;
b3b4aa74b   David Sterba   btrfs: drop unuse...
2174
  		btrfs_release_path(path);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2175
  		key.objectid = key.offset;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2176
  		key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2177
  		dirid = key.objectid;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2178
  	}
77906a507   Li Zefan   Btrfs: copy strin...
2179
  	memmove(name, ptr, total_len);
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2180
  	name[total_len] = '\0';
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2181
2182
2183
  	ret = 0;
  out:
  	btrfs_free_path(path);
ac8e9819d   Chris Mason   Btrfs: add search...
2184
2185
2186
2187
2188
2189
2190
2191
  	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;
01b810b88   David Sterba   btrfs: make root ...
2192
  	int ret = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
2193

2354d08fe   Julia Lawall   Btrfs: use memdup...
2194
2195
2196
  	args = memdup_user(argp, sizeof(*args));
  	if (IS_ERR(args))
  		return PTR_ERR(args);
c2b96929e   Dan Carpenter   Btrfs: handle kma...
2197

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

01b810b88   David Sterba   btrfs: make root ...
2200
2201
2202
2203
  	/*
  	 * Unprivileged query to obtain the containing subvolume root id. The
  	 * path is reset so it's consistent with btrfs_search_path_in_tree.
  	 */
1b53ac4d1   Chris Mason   Btrfs: allow tree...
2204
2205
  	if (args->treeid == 0)
  		args->treeid = BTRFS_I(inode)->root->root_key.objectid;
01b810b88   David Sterba   btrfs: make root ...
2206
2207
2208
2209
2210
2211
2212
2213
2214
  	if (args->objectid == BTRFS_FIRST_FREE_OBJECTID) {
  		args->name[0] = 0;
  		goto out;
  	}
  
  	if (!capable(CAP_SYS_ADMIN)) {
  		ret = -EPERM;
  		goto out;
  	}
ac8e9819d   Chris Mason   Btrfs: add search...
2215
2216
2217
  	ret = btrfs_search_path_in_tree(BTRFS_I(inode)->root->fs_info,
  					args->treeid, args->objectid,
  					args->name);
01b810b88   David Sterba   btrfs: make root ...
2218
  out:
ac8e9819d   Chris Mason   Btrfs: add search...
2219
2220
2221
2222
  	if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
  		ret = -EFAULT;
  
  	kfree(args);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2223
2224
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2225
2226
2227
  static noinline int btrfs_ioctl_snap_destroy(struct file *file,
  					     void __user *arg)
  {
54563d41a   Al Viro   btrfs: get rid of...
2228
  	struct dentry *parent = file->f_path.dentry;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2229
  	struct dentry *dentry;
2b0143b5c   David Howells   VFS: normal files...
2230
  	struct inode *dir = d_inode(parent);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2231
2232
2233
2234
2235
  	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 ...
2236
  	struct btrfs_block_rsv block_rsv;
521e0546c   David Sterba   btrfs: protect sn...
2237
  	u64 root_flags;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2238
  	u64 qgroup_reserved;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2239
2240
2241
  	int namelen;
  	int ret;
  	int err = 0;
325c50e3c   Jeff Mahoney   btrfs: ensure tha...
2242
2243
  	if (!S_ISDIR(dir->i_mode))
  		return -ENOTDIR;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
  	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...
2255
  	err = mnt_want_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2256
2257
  	if (err)
  		goto out;
521e0546c   David Sterba   btrfs: protect sn...
2258

002354112   Al Viro   restore killabili...
2259
2260
2261
  	err = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
  	if (err == -EINTR)
  		goto out_drop_write;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2262
2263
2264
2265
2266
  	dentry = lookup_one_len(vol_args->name, parent, namelen);
  	if (IS_ERR(dentry)) {
  		err = PTR_ERR(dentry);
  		goto out_unlock_dir;
  	}
2b0143b5c   David Howells   VFS: normal files...
2267
  	if (d_really_is_negative(dentry)) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2268
2269
2270
  		err = -ENOENT;
  		goto out_dput;
  	}
2b0143b5c   David Howells   VFS: normal files...
2271
  	inode = d_inode(dentry);
4260f7c75   Sage Weil   Btrfs: allow subv...
2272
  	dest = BTRFS_I(inode)->root;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2273
  	if (!capable(CAP_SYS_ADMIN)) {
4260f7c75   Sage Weil   Btrfs: allow subv...
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
  		/*
  		 * 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;
3cdde2240   Jeff Mahoney   btrfs: btrfs_test...
2288
  		if (!btrfs_test_opt(root->fs_info, USER_SUBVOL_RM_ALLOWED))
4260f7c75   Sage Weil   Btrfs: allow subv...
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
  			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...
2305
  	}
5c39da5b6   Miao Xie   Btrfs: do not del...
2306
2307
2308
2309
  	/* 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...
2310
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2311
2312
2313
  		err = -EINVAL;
  		goto out_dput;
  	}
5955102c9   Al Viro   wrappers for ->i_...
2314
  	inode_lock(inode);
521e0546c   David Sterba   btrfs: protect sn...
2315
2316
2317
2318
2319
2320
2321
  
  	/*
  	 * Don't allow to delete a subvolume with send in progress. This is
  	 * inside the i_mutex so the error handling that has to drop the bit
  	 * again is not run concurrently.
  	 */
  	spin_lock(&dest->root_item_lock);
c55bfa67e   Filipe Manana   Btrfs: set dead f...
2322
2323
2324
  	root_flags = btrfs_root_flags(&dest->root_item);
  	if (dest->send_in_progress == 0) {
  		btrfs_set_root_flags(&dest->root_item,
521e0546c   David Sterba   btrfs: protect sn...
2325
2326
2327
2328
2329
2330
  				root_flags | BTRFS_ROOT_SUBVOL_DEAD);
  		spin_unlock(&dest->root_item_lock);
  	} else {
  		spin_unlock(&dest->root_item_lock);
  		btrfs_warn(root->fs_info,
  			"Attempt to delete subvolume %llu during send",
c55bfa67e   Filipe Manana   Btrfs: set dead f...
2331
  			dest->root_key.objectid);
521e0546c   David Sterba   btrfs: protect sn...
2332
  		err = -EPERM;
909e26dce   Omar Sandoval   btrfs: unlock i_m...
2333
  		goto out_unlock_inode;
521e0546c   David Sterba   btrfs: protect sn...
2334
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2335
2336
2337
2338
2339
  	down_write(&root->fs_info->subvol_sem);
  
  	err = may_destroy_subvol(dest);
  	if (err)
  		goto out_up_write;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2340
2341
2342
2343
2344
2345
  	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 ...
2346
  					       5, &qgroup_reserved, true);
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2347
2348
  	if (err)
  		goto out_up_write;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2349
2350
2351
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		err = PTR_ERR(trans);
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2352
  		goto out_release;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2353
  	}
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2354
2355
  	trans->block_rsv = &block_rsv;
  	trans->bytes_reserved = block_rsv.size;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2356

2be63d5ce   Filipe Manana   Btrfs: fix file l...
2357
  	btrfs_record_snapshot_destroy(trans, dir);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2358
2359
2360
2361
  	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...
2362
2363
  	if (ret) {
  		err = ret;
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2364
  		btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2365
2366
  		goto out_end_trans;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2367
2368
2369
2370
2371
2372
2373
  
  	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);
27cdeb709   Miao Xie   Btrfs: use bitfie...
2374
  	if (!test_and_set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &dest->state)) {
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
2375
2376
2377
  		ret = btrfs_insert_orphan_item(trans,
  					root->fs_info->tree_root,
  					dest->root_key.objectid);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2378
  		if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2379
  			btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2380
2381
2382
  			err = ret;
  			goto out_end_trans;
  		}
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
2383
  	}
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2384
2385
2386
2387
2388
  
  	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) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2389
  		btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2390
2391
2392
2393
2394
2395
2396
2397
2398
  		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) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2399
  			btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2400
2401
2402
2403
  			err = ret;
  			goto out_end_trans;
  		}
  	}
79787eaab   Jeff Mahoney   btrfs: replace ma...
2404
  out_end_trans:
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2405
2406
  	trans->block_rsv = NULL;
  	trans->bytes_reserved = 0;
531cb13f1   Sage Weil   Btrfs: make SNAP_...
2407
  	ret = btrfs_end_transaction(trans, root);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2408
2409
  	if (ret && !err)
  		err = ret;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2410
  	inode->i_flags |= S_DEAD;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2411
2412
  out_release:
  	btrfs_subvolume_release_metadata(root, &block_rsv, qgroup_reserved);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2413
2414
  out_up_write:
  	up_write(&root->fs_info->subvol_sem);
521e0546c   David Sterba   btrfs: protect sn...
2415
2416
  	if (err) {
  		spin_lock(&dest->root_item_lock);
c55bfa67e   Filipe Manana   Btrfs: set dead f...
2417
2418
  		root_flags = btrfs_root_flags(&dest->root_item);
  		btrfs_set_root_flags(&dest->root_item,
521e0546c   David Sterba   btrfs: protect sn...
2419
2420
2421
  				root_flags & ~BTRFS_ROOT_SUBVOL_DEAD);
  		spin_unlock(&dest->root_item_lock);
  	}
909e26dce   Omar Sandoval   btrfs: unlock i_m...
2422
  out_unlock_inode:
5955102c9   Al Viro   wrappers for ->i_...
2423
  	inode_unlock(inode);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2424
  	if (!err) {
64ad6c488   Omar Sandoval   Btrfs: don't inva...
2425
  		d_invalidate(dentry);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2426
2427
  		btrfs_invalidate_inodes(dest);
  		d_delete(dentry);
61155aa04   David Sterba   btrfs: assert tha...
2428
  		ASSERT(dest->send_in_progress == 0);
fa6ac8765   Liu Bo   Btrfs: fix cleane...
2429
2430
  
  		/* the last ref */
57cdc8db2   David Sterba   btrfs: cleanup in...
2431
2432
2433
  		if (dest->ino_cache_inode) {
  			iput(dest->ino_cache_inode);
  			dest->ino_cache_inode = NULL;
fa6ac8765   Liu Bo   Btrfs: fix cleane...
2434
  		}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2435
2436
2437
2438
  	}
  out_dput:
  	dput(dentry);
  out_unlock_dir:
5955102c9   Al Viro   wrappers for ->i_...
2439
  	inode_unlock(dir);
002354112   Al Viro   restore killabili...
2440
  out_drop_write:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
2441
  	mnt_drop_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2442
2443
2444
2445
  out:
  	kfree(vol_args);
  	return err;
  }
1e701a329   Chris Mason   Btrfs: add new de...
2446
  static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2447
  {
496ad9aa8   Al Viro   new helper: file_...
2448
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2449
  	struct btrfs_root *root = BTRFS_I(inode)->root;
1e701a329   Chris Mason   Btrfs: add new de...
2450
  	struct btrfs_ioctl_defrag_range_args *range;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2451
  	int ret;
25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2452
2453
2454
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
b83cc9693   Li Zefan   Btrfs: Add readon...
2455

25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2456
2457
2458
  	if (btrfs_root_readonly(root)) {
  		ret = -EROFS;
  		goto out;
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2459
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2460
2461
2462
  
  	switch (inode->i_mode & S_IFMT) {
  	case S_IFDIR:
e441d54de   Chris Mason   Btrfs: add permis...
2463
2464
2465
2466
  		if (!capable(CAP_SYS_ADMIN)) {
  			ret = -EPERM;
  			goto out;
  		}
de78b51a2   Eric Sandeen   btrfs: remove cac...
2467
  		ret = btrfs_defrag_root(root);
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
2468
2469
  		if (ret)
  			goto out;
de78b51a2   Eric Sandeen   btrfs: remove cac...
2470
  		ret = btrfs_defrag_root(root->fs_info->extent_root);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2471
2472
  		break;
  	case S_IFREG:
e441d54de   Chris Mason   Btrfs: add permis...
2473
2474
2475
2476
  		if (!(file->f_mode & FMODE_WRITE)) {
  			ret = -EINVAL;
  			goto out;
  		}
1e701a329   Chris Mason   Btrfs: add new de...
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
  
  		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...
2489
  				goto out;
1e701a329   Chris Mason   Btrfs: add new de...
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
  			}
  			/* 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_...
2500
  		ret = btrfs_defrag_file(file_inode(file), file,
4cb5300bc   Chris Mason   Btrfs: add mount ...
2501
2502
2503
  					range, 0, 0);
  		if (ret > 0)
  			ret = 0;
1e701a329   Chris Mason   Btrfs: add new de...
2504
  		kfree(range);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2505
  		break;
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
2506
2507
  	default:
  		ret = -EINVAL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2508
  	}
e441d54de   Chris Mason   Btrfs: add permis...
2509
  out:
25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2510
  	mnt_drop_write_file(file);
e441d54de   Chris Mason   Btrfs: add permis...
2511
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2512
  }
b2950863c   Christoph Hellwig   Btrfs: make thing...
2513
  static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2514
2515
2516
  {
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2517
2518
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2519
2520
  	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
e57138b3e   Anand Jain   btrfs: return btr...
2521
  		return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2522
  	}
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2523
  	mutex_lock(&root->fs_info->volume_mutex);
dae7b665c   Li Zefan   btrfs: use memdup...
2524
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2525
2526
2527
2528
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
  		goto out;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2529

5516e5957   Mark Fasheh   Btrfs: Null termi...
2530
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2531
  	ret = btrfs_init_new_device(root, vol_args->name);
43d207616   Anand Jain   btrfs: device add...
2532
2533
  	if (!ret)
  		btrfs_info(root->fs_info, "disk added %s",vol_args->name);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2534
  	kfree(vol_args);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2535
2536
  out:
  	mutex_unlock(&root->fs_info->volume_mutex);
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2537
  	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2538
2539
  	return ret;
  }
6b526ed70   Anand Jain   btrfs: introduce ...
2540
  static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2541
  {
496ad9aa8   Al Viro   new helper: file_...
2542
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
6b526ed70   Anand Jain   btrfs: introduce ...
2543
  	struct btrfs_ioctl_vol_args_v2 *vol_args;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2544
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2545
2546
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
da24927b1   Miao Xie   Btrfs: get write ...
2547
2548
2549
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2550

dae7b665c   Li Zefan   btrfs: use memdup...
2551
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2552
2553
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
2554
  		goto err_drop;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2555
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2556

6b526ed70   Anand Jain   btrfs: introduce ...
2557
  	/* Check for compatibility reject unknown flags */
735654ea9   David Sterba   btrfs: rename fla...
2558
2559
  	if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED)
  		return -EOPNOTSUPP;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2560

183860f6a   Anand Jain   btrfs: device del...
2561
2562
2563
2564
2565
2566
2567
  	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);
735654ea9   David Sterba   btrfs: rename fla...
2568
  	if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) {
6b526ed70   Anand Jain   btrfs: introduce ...
2569
2570
2571
2572
2573
  		ret = btrfs_rm_device(root, NULL, vol_args->devid);
  	} else {
  		vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
  		ret = btrfs_rm_device(root, vol_args->name, 0);
  	}
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2574
  	mutex_unlock(&root->fs_info->volume_mutex);
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2575
  	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
183860f6a   Anand Jain   btrfs: device del...
2576

6b526ed70   Anand Jain   btrfs: introduce ...
2577
  	if (!ret) {
735654ea9   David Sterba   btrfs: rename fla...
2578
  		if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID)
6b526ed70   Anand Jain   btrfs: introduce ...
2579
2580
2581
2582
2583
2584
  			btrfs_info(root->fs_info, "device deleted: id %llu",
  					vol_args->devid);
  		else
  			btrfs_info(root->fs_info, "device deleted: %s",
  					vol_args->name);
  	}
183860f6a   Anand Jain   btrfs: device del...
2585
2586
  out:
  	kfree(vol_args);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
2587
  err_drop:
4ac20c70b   Ilya Dryomov   Btrfs: fix unlock...
2588
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2589
2590
  	return ret;
  }
da24927b1   Miao Xie   Btrfs: get write ...
2591
  static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2592
  {
496ad9aa8   Al Viro   new helper: file_...
2593
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2594
2595
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2596
2597
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
da24927b1   Miao Xie   Btrfs: get write ...
2598
2599
2600
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2601

183860f6a   Anand Jain   btrfs: device del...
2602
2603
2604
  	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
  		ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2605
2606
2607
2608
2609
2610
  		goto out_drop_write;
  	}
  
  	vol_args = memdup_user(arg, sizeof(*vol_args));
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
183860f6a   Anand Jain   btrfs: device del...
2611
2612
  		goto out;
  	}
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2613
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
183860f6a   Anand Jain   btrfs: device del...
2614
  	mutex_lock(&root->fs_info->volume_mutex);
6b526ed70   Anand Jain   btrfs: introduce ...
2615
  	ret = btrfs_rm_device(root, vol_args->name, 0);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2616
  	mutex_unlock(&root->fs_info->volume_mutex);
183860f6a   Anand Jain   btrfs: device del...
2617

ec95d4917   Anand Jain   btrfs: device del...
2618
2619
  	if (!ret)
  		btrfs_info(root->fs_info, "disk deleted %s",vol_args->name);
183860f6a   Anand Jain   btrfs: device del...
2620
  	kfree(vol_args);
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2621
2622
2623
  out:
  	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
  out_drop_write:
4ac20c70b   Ilya Dryomov   Btrfs: fix unlock...
2624
  	mnt_drop_write_file(file);
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2625

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2626
2627
  	return ret;
  }
475f63874   Jan Schmidt   btrfs: new ioctls...
2628
2629
  static long btrfs_ioctl_fs_info(struct btrfs_root *root, void __user *arg)
  {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2630
  	struct btrfs_ioctl_fs_info_args *fi_args;
475f63874   Jan Schmidt   btrfs: new ioctls...
2631
  	struct btrfs_device *device;
475f63874   Jan Schmidt   btrfs: new ioctls...
2632
  	struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
027ed2f00   Li Zefan   Btrfs: avoid stac...
2633
  	int ret = 0;
475f63874   Jan Schmidt   btrfs: new ioctls...
2634

027ed2f00   Li Zefan   Btrfs: avoid stac...
2635
2636
2637
  	fi_args = kzalloc(sizeof(*fi_args), GFP_KERNEL);
  	if (!fi_args)
  		return -ENOMEM;
f71717502   Filipe David Borba Manana   Btrfs: fix race c...
2638
  	mutex_lock(&fs_devices->device_list_mutex);
027ed2f00   Li Zefan   Btrfs: avoid stac...
2639
2640
  	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...
2641

d7641a49a   Byongho Lee   btrfs: replace un...
2642
  	list_for_each_entry(device, &fs_devices->devices, dev_list) {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2643
2644
  		if (device->devid > fi_args->max_id)
  			fi_args->max_id = device->devid;
475f63874   Jan Schmidt   btrfs: new ioctls...
2645
2646
  	}
  	mutex_unlock(&fs_devices->device_list_mutex);
80a773fbf   David Sterba   btrfs: retrieve m...
2647
2648
2649
  	fi_args->nodesize = root->fs_info->super_copy->nodesize;
  	fi_args->sectorsize = root->fs_info->super_copy->sectorsize;
  	fi_args->clone_alignment = root->fs_info->super_copy->sectorsize;
027ed2f00   Li Zefan   Btrfs: avoid stac...
2650
2651
  	if (copy_to_user(arg, fi_args, sizeof(*fi_args)))
  		ret = -EFAULT;
475f63874   Jan Schmidt   btrfs: new ioctls...
2652

027ed2f00   Li Zefan   Btrfs: avoid stac...
2653
2654
  	kfree(fi_args);
  	return ret;
475f63874   Jan Schmidt   btrfs: new ioctls...
2655
2656
2657
2658
2659
2660
2661
2662
2663
  }
  
  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...
2664

475f63874   Jan Schmidt   btrfs: new ioctls...
2665
2666
2667
  	di_args = memdup_user(arg, sizeof(*di_args));
  	if (IS_ERR(di_args))
  		return PTR_ERR(di_args);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2668
  	if (!btrfs_is_empty_uuid(di_args->uuid))
475f63874   Jan Schmidt   btrfs: new ioctls...
2669
2670
2671
  		s_uuid = di_args->uuid;
  
  	mutex_lock(&fs_devices->device_list_mutex);
aa1b8cd40   Stefan Behrens   Btrfs: pass fs_in...
2672
  	dev = btrfs_find_device(root->fs_info, di_args->devid, s_uuid, NULL);
475f63874   Jan Schmidt   btrfs: new ioctls...
2673
2674
2675
2676
2677
2678
2679
  
  	if (!dev) {
  		ret = -ENODEV;
  		goto out;
  	}
  
  	di_args->devid = dev->devid;
7cc8e58d5   Miao Xie   Btrfs: fix unprot...
2680
2681
  	di_args->bytes_used = btrfs_device_get_bytes_used(dev);
  	di_args->total_bytes = btrfs_device_get_total_bytes(dev);
475f63874   Jan Schmidt   btrfs: new ioctls...
2682
  	memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
a27202fbe   Jim Meyering   Btrfs: NUL-termin...
2683
  	if (dev->name) {
606686eea   Josef Bacik   Btrfs: use rcu to...
2684
2685
2686
2687
2688
2689
  		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...
2690
2691
  		di_args->path[sizeof(di_args->path) - 1] = 0;
  	} else {
99ba55ad6   Stefan Behrens   Btrfs: fix btrfs_...
2692
  		di_args->path[0] = '\0';
a27202fbe   Jim Meyering   Btrfs: NUL-termin...
2693
  	}
475f63874   Jan Schmidt   btrfs: new ioctls...
2694
2695
  
  out:
55793c0d0   David Sterba   btrfs: read entir...
2696
  	mutex_unlock(&fs_devices->device_list_mutex);
475f63874   Jan Schmidt   btrfs: new ioctls...
2697
2698
2699
2700
2701
2702
  	if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args)))
  		ret = -EFAULT;
  
  	kfree(di_args);
  	return ret;
  }
f44146020   Mark Fasheh   btrfs: fix deadlo...
2703
  static struct page *extent_same_get_page(struct inode *inode, pgoff_t index)
416161db9   Mark Fasheh   btrfs: offline de...
2704
2705
  {
  	struct page *page;
416161db9   Mark Fasheh   btrfs: offline de...
2706

416161db9   Mark Fasheh   btrfs: offline de...
2707
2708
  	page = grab_cache_page(inode->i_mapping, index);
  	if (!page)
313140023   Filipe Manana   Btrfs: fix page r...
2709
  		return ERR_PTR(-ENOMEM);
416161db9   Mark Fasheh   btrfs: offline de...
2710
2711
  
  	if (!PageUptodate(page)) {
313140023   Filipe Manana   Btrfs: fix page r...
2712
2713
2714
2715
2716
  		int ret;
  
  		ret = btrfs_readpage(NULL, page);
  		if (ret)
  			return ERR_PTR(ret);
416161db9   Mark Fasheh   btrfs: offline de...
2717
2718
2719
  		lock_page(page);
  		if (!PageUptodate(page)) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2720
  			put_page(page);
313140023   Filipe Manana   Btrfs: fix page r...
2721
2722
2723
2724
  			return ERR_PTR(-EIO);
  		}
  		if (page->mapping != inode->i_mapping) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2725
  			put_page(page);
313140023   Filipe Manana   Btrfs: fix page r...
2726
  			return ERR_PTR(-EAGAIN);
416161db9   Mark Fasheh   btrfs: offline de...
2727
2728
  		}
  	}
416161db9   Mark Fasheh   btrfs: offline de...
2729
2730
2731
  
  	return page;
  }
f44146020   Mark Fasheh   btrfs: fix deadlo...
2732
2733
2734
2735
  static int gather_extent_pages(struct inode *inode, struct page **pages,
  			       int num_pages, u64 off)
  {
  	int i;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2736
  	pgoff_t index = off >> PAGE_SHIFT;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2737
2738
  
  	for (i = 0; i < num_pages; i++) {
313140023   Filipe Manana   Btrfs: fix page r...
2739
  again:
f44146020   Mark Fasheh   btrfs: fix deadlo...
2740
  		pages[i] = extent_same_get_page(inode, index + i);
313140023   Filipe Manana   Btrfs: fix page r...
2741
2742
2743
2744
2745
2746
2747
2748
  		if (IS_ERR(pages[i])) {
  			int err = PTR_ERR(pages[i]);
  
  			if (err == -EAGAIN)
  				goto again;
  			pages[i] = NULL;
  			return err;
  		}
f44146020   Mark Fasheh   btrfs: fix deadlo...
2749
2750
2751
  	}
  	return 0;
  }
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2752
2753
  static int lock_extent_range(struct inode *inode, u64 off, u64 len,
  			     bool retry_range_locking)
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2754
  {
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2755
2756
2757
2758
2759
2760
2761
2762
  	/*
  	 * Do any pending delalloc/csum calculations on inode, one way or
  	 * another, and lock file content.
  	 * The locking order is:
  	 *
  	 *   1) pages
  	 *   2) range in the inode's io tree
  	 */
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2763
2764
2765
2766
2767
  	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);
ff5df9b88   Filipe Manana   Btrfs: ioctl, don...
2768
2769
2770
  		if ((!ordered ||
  		     ordered->file_offset + ordered->len <= off ||
  		     ordered->file_offset >= off + len) &&
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2771
  		    !test_range_bit(&BTRFS_I(inode)->io_tree, off,
ff5df9b88   Filipe Manana   Btrfs: ioctl, don...
2772
2773
2774
  				    off + len - 1, EXTENT_DELALLOC, 0, NULL)) {
  			if (ordered)
  				btrfs_put_ordered_extent(ordered);
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2775
  			break;
ff5df9b88   Filipe Manana   Btrfs: ioctl, don...
2776
  		}
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2777
2778
2779
  		unlock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
  		if (ordered)
  			btrfs_put_ordered_extent(ordered);
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2780
2781
  		if (!retry_range_locking)
  			return -EAGAIN;
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2782
2783
  		btrfs_wait_ordered_range(inode, off, len);
  	}
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2784
  	return 0;
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2785
  }
f44146020   Mark Fasheh   btrfs: fix deadlo...
2786
  static void btrfs_double_inode_unlock(struct inode *inode1, struct inode *inode2)
416161db9   Mark Fasheh   btrfs: offline de...
2787
  {
5955102c9   Al Viro   wrappers for ->i_...
2788
2789
  	inode_unlock(inode1);
  	inode_unlock(inode2);
416161db9   Mark Fasheh   btrfs: offline de...
2790
  }
f44146020   Mark Fasheh   btrfs: fix deadlo...
2791
2792
2793
2794
  static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2)
  {
  	if (inode1 < inode2)
  		swap(inode1, inode2);
5955102c9   Al Viro   wrappers for ->i_...
2795
2796
  	inode_lock_nested(inode1, I_MUTEX_PARENT);
  	inode_lock_nested(inode2, I_MUTEX_CHILD);
f44146020   Mark Fasheh   btrfs: fix deadlo...
2797
2798
2799
2800
2801
2802
2803
2804
  }
  
  static void btrfs_double_extent_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);
  }
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2805
2806
2807
  static int btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
  				    struct inode *inode2, u64 loff2, u64 len,
  				    bool retry_range_locking)
416161db9   Mark Fasheh   btrfs: offline de...
2808
  {
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2809
  	int ret;
416161db9   Mark Fasheh   btrfs: offline de...
2810
2811
2812
2813
  	if (inode1 < inode2) {
  		swap(inode1, inode2);
  		swap(loff1, loff2);
  	}
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2814
2815
2816
2817
2818
2819
2820
2821
  	ret = lock_extent_range(inode1, loff1, len, retry_range_locking);
  	if (ret)
  		return ret;
  	ret = lock_extent_range(inode2, loff2, len, retry_range_locking);
  	if (ret)
  		unlock_extent(&BTRFS_I(inode1)->io_tree, loff1,
  			      loff1 + len - 1);
  	return ret;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
  }
  
  struct cmp_pages {
  	int		num_pages;
  	struct page	**src_pages;
  	struct page	**dst_pages;
  };
  
  static void btrfs_cmp_data_free(struct cmp_pages *cmp)
  {
  	int i;
  	struct page *pg;
  
  	for (i = 0; i < cmp->num_pages; i++) {
  		pg = cmp->src_pages[i];
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2837
2838
  		if (pg) {
  			unlock_page(pg);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2839
  			put_page(pg);
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2840
  		}
f44146020   Mark Fasheh   btrfs: fix deadlo...
2841
  		pg = cmp->dst_pages[i];
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2842
2843
  		if (pg) {
  			unlock_page(pg);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2844
  			put_page(pg);
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2845
  		}
f44146020   Mark Fasheh   btrfs: fix deadlo...
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
  	}
  	kfree(cmp->src_pages);
  	kfree(cmp->dst_pages);
  }
  
  static int btrfs_cmp_data_prepare(struct inode *src, u64 loff,
  				  struct inode *dst, u64 dst_loff,
  				  u64 len, struct cmp_pages *cmp)
  {
  	int ret;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2856
  	int num_pages = PAGE_ALIGN(len) >> PAGE_SHIFT;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2857
2858
2859
2860
2861
2862
2863
2864
  	struct page **src_pgarr, **dst_pgarr;
  
  	/*
  	 * We must gather up all the pages before we initiate our
  	 * extent locking. We use an array for the page pointers. Size
  	 * of the array is bounded by len, which is in turn bounded by
  	 * BTRFS_MAX_DEDUPE_LEN.
  	 */
66722f7c0   David Sterba   btrfs: switch to ...
2865
2866
  	src_pgarr = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
  	dst_pgarr = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
f44146020   Mark Fasheh   btrfs: fix deadlo...
2867
2868
2869
2870
  	if (!src_pgarr || !dst_pgarr) {
  		kfree(src_pgarr);
  		kfree(dst_pgarr);
  		return -ENOMEM;
416161db9   Mark Fasheh   btrfs: offline de...
2871
  	}
f44146020   Mark Fasheh   btrfs: fix deadlo...
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
  	cmp->num_pages = num_pages;
  	cmp->src_pages = src_pgarr;
  	cmp->dst_pages = dst_pgarr;
  
  	ret = gather_extent_pages(src, cmp->src_pages, cmp->num_pages, loff);
  	if (ret)
  		goto out;
  
  	ret = gather_extent_pages(dst, cmp->dst_pages, cmp->num_pages, dst_loff);
  
  out:
  	if (ret)
  		btrfs_cmp_data_free(cmp);
  	return 0;
416161db9   Mark Fasheh   btrfs: offline de...
2886
2887
2888
  }
  
  static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst,
f44146020   Mark Fasheh   btrfs: fix deadlo...
2889
  			  u64 dst_loff, u64 len, struct cmp_pages *cmp)
416161db9   Mark Fasheh   btrfs: offline de...
2890
2891
  {
  	int ret = 0;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2892
  	int i;
416161db9   Mark Fasheh   btrfs: offline de...
2893
  	struct page *src_page, *dst_page;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2894
  	unsigned int cmp_len = PAGE_SIZE;
416161db9   Mark Fasheh   btrfs: offline de...
2895
  	void *addr, *dst_addr;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2896
  	i = 0;
416161db9   Mark Fasheh   btrfs: offline de...
2897
  	while (len) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2898
  		if (len < PAGE_SIZE)
416161db9   Mark Fasheh   btrfs: offline de...
2899
  			cmp_len = len;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2900
2901
2902
2903
  		BUG_ON(i >= cmp->num_pages);
  
  		src_page = cmp->src_pages[i];
  		dst_page = cmp->dst_pages[i];
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2904
2905
  		ASSERT(PageLocked(src_page));
  		ASSERT(PageLocked(dst_page));
f44146020   Mark Fasheh   btrfs: fix deadlo...
2906

416161db9   Mark Fasheh   btrfs: offline de...
2907
2908
2909
2910
2911
2912
2913
  		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))
2b3909f8a   Darrick J. Wong   btrfs: use new de...
2914
  			ret = -EBADE;
416161db9   Mark Fasheh   btrfs: offline de...
2915
2916
2917
  
  		kunmap_atomic(addr);
  		kunmap_atomic(dst_addr);
416161db9   Mark Fasheh   btrfs: offline de...
2918
2919
2920
  
  		if (ret)
  			break;
416161db9   Mark Fasheh   btrfs: offline de...
2921
  		len -= cmp_len;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2922
  		i++;
416161db9   Mark Fasheh   btrfs: offline de...
2923
2924
2925
2926
  	}
  
  	return ret;
  }
e1d227a42   Mark Fasheh   btrfs: Handle una...
2927
2928
  static int extent_same_check_offsets(struct inode *inode, u64 off, u64 *plen,
  				     u64 olen)
416161db9   Mark Fasheh   btrfs: offline de...
2929
  {
e1d227a42   Mark Fasheh   btrfs: Handle una...
2930
  	u64 len = *plen;
416161db9   Mark Fasheh   btrfs: offline de...
2931
  	u64 bs = BTRFS_I(inode)->root->fs_info->sb->s_blocksize;
e1d227a42   Mark Fasheh   btrfs: Handle una...
2932
  	if (off + olen > inode->i_size || off + olen < off)
416161db9   Mark Fasheh   btrfs: offline de...
2933
  		return -EINVAL;
e1d227a42   Mark Fasheh   btrfs: Handle una...
2934
2935
2936
2937
  
  	/* if we extend to eof, continue to block boundary */
  	if (off + len == inode->i_size)
  		*plen = len = ALIGN(inode->i_size, bs) - off;
416161db9   Mark Fasheh   btrfs: offline de...
2938
2939
2940
2941
2942
2943
  	/* Check that we are block aligned - btrfs_clone() requires this */
  	if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs))
  		return -EINVAL;
  
  	return 0;
  }
e1d227a42   Mark Fasheh   btrfs: Handle una...
2944
  static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
416161db9   Mark Fasheh   btrfs: offline de...
2945
2946
2947
  			     struct inode *dst, u64 dst_loff)
  {
  	int ret;
e1d227a42   Mark Fasheh   btrfs: Handle una...
2948
  	u64 len = olen;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2949
  	struct cmp_pages cmp;
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
2950
2951
2952
  	int same_inode = 0;
  	u64 same_lock_start = 0;
  	u64 same_lock_len = 0;
416161db9   Mark Fasheh   btrfs: offline de...
2953

416161db9   Mark Fasheh   btrfs: offline de...
2954
  	if (src == dst)
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
2955
  		same_inode = 1;
416161db9   Mark Fasheh   btrfs: offline de...
2956

113e82838   Filipe Manana   Btrfs: fix inode ...
2957
2958
  	if (len == 0)
  		return 0;
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
2959
  	if (same_inode) {
5955102c9   Al Viro   wrappers for ->i_...
2960
  		inode_lock(src);
416161db9   Mark Fasheh   btrfs: offline de...
2961

0efa9f48c   Mark Fasheh   btrfs: allow dedu...
2962
2963
2964
  		ret = extent_same_check_offsets(src, loff, &len, olen);
  		if (ret)
  			goto out_unlock;
f4dfe6871   Filipe Manana   Btrfs: fix extent...
2965
2966
2967
  		ret = extent_same_check_offsets(src, dst_loff, &len, olen);
  		if (ret)
  			goto out_unlock;
416161db9   Mark Fasheh   btrfs: offline de...
2968

0efa9f48c   Mark Fasheh   btrfs: allow dedu...
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
  		/*
  		 * Single inode case wants the same checks, except we
  		 * don't want our length pushed out past i_size as
  		 * comparing that data range makes no sense.
  		 *
  		 * extent_same_check_offsets() will do this for an
  		 * unaligned length at i_size, so catch it here and
  		 * reject the request.
  		 *
  		 * This effectively means we require aligned extents
  		 * for the single-inode case, whereas the other cases
  		 * allow an unaligned length so long as it ends at
  		 * i_size.
  		 */
  		if (len != olen) {
  			ret = -EINVAL;
  			goto out_unlock;
  		}
  
  		/* Check for overlapping ranges */
  		if (dst_loff + len > loff && dst_loff < loff + len) {
  			ret = -EINVAL;
  			goto out_unlock;
  		}
  
  		same_lock_start = min_t(u64, loff, dst_loff);
  		same_lock_len = max_t(u64, loff, dst_loff) + len - same_lock_start;
  	} else {
  		btrfs_double_inode_lock(src, dst);
  
  		ret = extent_same_check_offsets(src, loff, &len, olen);
  		if (ret)
  			goto out_unlock;
  
  		ret = extent_same_check_offsets(dst, dst_loff, &len, olen);
  		if (ret)
  			goto out_unlock;
  	}
416161db9   Mark Fasheh   btrfs: offline de...
3007
3008
3009
3010
3011
3012
3013
  
  	/* 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;
  	}
e0bd70c67   Filipe Manana   Btrfs: fix invali...
3014
  again:
f44146020   Mark Fasheh   btrfs: fix deadlo...
3015
3016
3017
  	ret = btrfs_cmp_data_prepare(src, loff, dst, dst_loff, olen, &cmp);
  	if (ret)
  		goto out_unlock;
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3018
  	if (same_inode)
e0bd70c67   Filipe Manana   Btrfs: fix invali...
3019
3020
  		ret = lock_extent_range(src, same_lock_start, same_lock_len,
  					false);
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3021
  	else
e0bd70c67   Filipe Manana   Btrfs: fix invali...
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
  		ret = btrfs_double_extent_lock(src, loff, dst, dst_loff, len,
  					       false);
  	/*
  	 * If one of the inodes has dirty pages in the respective range or
  	 * ordered extents, we need to flush dellaloc and wait for all ordered
  	 * extents in the range. We must unlock the pages and the ranges in the
  	 * io trees to avoid deadlocks when flushing delalloc (requires locking
  	 * pages) and when waiting for ordered extents to complete (they require
  	 * range locking).
  	 */
  	if (ret == -EAGAIN) {
  		/*
  		 * Ranges in the io trees already unlocked. Now unlock all
  		 * pages before waiting for all IO to complete.
  		 */
  		btrfs_cmp_data_free(&cmp);
  		if (same_inode) {
  			btrfs_wait_ordered_range(src, same_lock_start,
  						 same_lock_len);
  		} else {
  			btrfs_wait_ordered_range(src, loff, len);
  			btrfs_wait_ordered_range(dst, dst_loff, len);
  		}
  		goto again;
  	}
  	ASSERT(ret == 0);
  	if (WARN_ON(ret)) {
  		/* ranges in the io trees already unlocked */
  		btrfs_cmp_data_free(&cmp);
  		return ret;
  	}
f44146020   Mark Fasheh   btrfs: fix deadlo...
3053

207910dde   Mark Fasheh   btrfs: pass unali...
3054
  	/* pass original length for comparison so we stay within i_size */
f44146020   Mark Fasheh   btrfs: fix deadlo...
3055
  	ret = btrfs_cmp_data(src, loff, dst, dst_loff, olen, &cmp);
416161db9   Mark Fasheh   btrfs: offline de...
3056
  	if (ret == 0)
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3057
  		ret = btrfs_clone(src, dst, loff, olen, len, dst_loff, 1);
416161db9   Mark Fasheh   btrfs: offline de...
3058

0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3059
3060
3061
3062
3063
  	if (same_inode)
  		unlock_extent(&BTRFS_I(src)->io_tree, same_lock_start,
  			      same_lock_start + same_lock_len - 1);
  	else
  		btrfs_double_extent_unlock(src, loff, dst, dst_loff, len);
f44146020   Mark Fasheh   btrfs: fix deadlo...
3064
3065
  
  	btrfs_cmp_data_free(&cmp);
416161db9   Mark Fasheh   btrfs: offline de...
3066
  out_unlock:
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3067
  	if (same_inode)
5955102c9   Al Viro   wrappers for ->i_...
3068
  		inode_unlock(src);
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3069
3070
  	else
  		btrfs_double_inode_unlock(src, dst);
416161db9   Mark Fasheh   btrfs: offline de...
3071
3072
3073
  
  	return ret;
  }
ee22184b5   Byongho Lee   Btrfs: use linux/...
3074
  #define BTRFS_MAX_DEDUPE_LEN	SZ_16M
416161db9   Mark Fasheh   btrfs: offline de...
3075

2b3909f8a   Darrick J. Wong   btrfs: use new de...
3076
3077
  ssize_t btrfs_dedupe_file_range(struct file *src_file, u64 loff, u64 olen,
  				struct file *dst_file, u64 dst_loff)
416161db9   Mark Fasheh   btrfs: offline de...
3078
  {
2b3909f8a   Darrick J. Wong   btrfs: use new de...
3079
3080
  	struct inode *src = file_inode(src_file);
  	struct inode *dst = file_inode(dst_file);
416161db9   Mark Fasheh   btrfs: offline de...
3081
  	u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
2b3909f8a   Darrick J. Wong   btrfs: use new de...
3082
  	ssize_t res;
416161db9   Mark Fasheh   btrfs: offline de...
3083

2b3909f8a   Darrick J. Wong   btrfs: use new de...
3084
3085
  	if (olen > BTRFS_MAX_DEDUPE_LEN)
  		olen = BTRFS_MAX_DEDUPE_LEN;
416161db9   Mark Fasheh   btrfs: offline de...
3086

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
3087
  	if (WARN_ON_ONCE(bs < PAGE_SIZE)) {
416161db9   Mark Fasheh   btrfs: offline de...
3088
3089
3090
3091
3092
  		/*
  		 * Btrfs does not support blocksize < page_size. As a
  		 * result, btrfs_cmp_data() won't correctly handle
  		 * this situation without an update.
  		 */
2b3909f8a   Darrick J. Wong   btrfs: use new de...
3093
  		return -EINVAL;
416161db9   Mark Fasheh   btrfs: offline de...
3094
  	}
2b3909f8a   Darrick J. Wong   btrfs: use new de...
3095
3096
3097
3098
  	res = btrfs_extent_same(src, loff, olen, dst, dst_loff);
  	if (res)
  		return res;
  	return olen;
416161db9   Mark Fasheh   btrfs: offline de...
3099
  }
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3100
3101
3102
3103
  static int clone_finish_inode_update(struct btrfs_trans_handle *trans,
  				     struct inode *inode,
  				     u64 endoff,
  				     const u64 destoff,
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3104
3105
  				     const u64 olen,
  				     int no_time_update)
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3106
3107
3108
3109
3110
  {
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret;
  
  	inode_inc_iversion(inode);
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3111
  	if (!no_time_update)
c2050a454   Deepa Dinamani   fs: Replace curre...
3112
  		inode->i_mtime = inode->i_ctime = current_time(inode);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
  	/*
  	 * We round up to the block size at eof when determining which
  	 * extents to clone above, but shouldn't round up the file size.
  	 */
  	if (endoff > destoff + olen)
  		endoff = destoff + olen;
  	if (endoff > inode->i_size)
  		btrfs_i_size_write(inode, endoff);
  
  	ret = btrfs_update_inode(trans, root, inode);
  	if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
3124
  		btrfs_abort_transaction(trans, ret);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3125
3126
3127
3128
3129
3130
3131
  		btrfs_end_transaction(trans, root);
  		goto out;
  	}
  	ret = btrfs_end_transaction(trans, root);
  out:
  	return ret;
  }
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3132
3133
3134
  static void clone_update_extent_map(struct inode *inode,
  				    const struct btrfs_trans_handle *trans,
  				    const struct btrfs_path *path,
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
  				    const u64 hole_offset,
  				    const u64 hole_len)
  {
  	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
  	struct extent_map *em;
  	int ret;
  
  	em = alloc_extent_map();
  	if (!em) {
  		set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
  			&BTRFS_I(inode)->runtime_flags);
  		return;
  	}
14f597963   Filipe Manana   Btrfs: fix use-af...
3148
3149
3150
3151
3152
  	if (path) {
  		struct btrfs_file_extent_item *fi;
  
  		fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
  				    struct btrfs_file_extent_item);
7ffbb598a   Filipe Manana   Btrfs: make fsync...
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
  		btrfs_extent_item_to_extent_map(inode, path, fi, false, em);
  		em->generation = -1;
  		if (btrfs_file_extent_type(path->nodes[0], fi) ==
  		    BTRFS_FILE_EXTENT_INLINE)
  			set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
  				&BTRFS_I(inode)->runtime_flags);
  	} else {
  		em->start = hole_offset;
  		em->len = hole_len;
  		em->ram_bytes = em->len;
  		em->orig_start = hole_offset;
  		em->block_start = EXTENT_MAP_HOLE;
  		em->block_len = 0;
  		em->orig_block_len = 0;
  		em->compress_type = BTRFS_COMPRESS_NONE;
  		em->generation = trans->transid;
  	}
  
  	while (1) {
  		write_lock(&em_tree->lock);
  		ret = add_extent_mapping(em_tree, em, 1);
  		write_unlock(&em_tree->lock);
  		if (ret != -EEXIST) {
  			free_extent_map(em);
  			break;
  		}
  		btrfs_drop_extent_cache(inode, em->start,
  					em->start + em->len - 1, 0);
  	}
ee39b432b   David Sterba   btrfs: remove unl...
3182
  	if (ret)
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3183
3184
3185
  		set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
  			&BTRFS_I(inode)->runtime_flags);
  }
8039d87d9   Filipe Manana   Btrfs: fix file c...
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
  /*
   * Make sure we do not end up inserting an inline extent into a file that has
   * already other (non-inline) extents. If a file has an inline extent it can
   * not have any other extents and the (single) inline extent must start at the
   * file offset 0. Failing to respect these rules will lead to file corruption,
   * resulting in EIO errors on read/write operations, hitting BUG_ON's in mm, etc
   *
   * We can have extents that have been already written to disk or we can have
   * dirty ranges still in delalloc, in which case the extent maps and items are
   * created only when we run delalloc, and the delalloc ranges might fall outside
   * the range we are currently locking in the inode's io tree. So we check the
   * inode's i_size because of that (i_size updates are done while holding the
   * i_mutex, which we are holding here).
   * We also check to see if the inode has a size not greater than "datal" but has
   * extents beyond it, due to an fallocate with FALLOC_FL_KEEP_SIZE (and we are
   * protected against such concurrent fallocate calls by the i_mutex).
   *
   * If the file has no extents but a size greater than datal, do not allow the
   * copy because we would need turn the inline extent into a non-inline one (even
   * with NO_HOLES enabled). If we find our destination inode only has one inline
   * extent, just overwrite it with the source inline extent if its size is less
   * than the source extent's size, or we could copy the source inline extent's
   * data into the destination inode's inline extent if the later is greater then
   * the former.
   */
  static int clone_copy_inline_extent(struct inode *src,
  				    struct inode *dst,
  				    struct btrfs_trans_handle *trans,
  				    struct btrfs_path *path,
  				    struct btrfs_key *new_key,
  				    const u64 drop_start,
  				    const u64 datal,
  				    const u64 skip,
  				    const u64 size,
  				    char *inline_data)
  {
  	struct btrfs_root *root = BTRFS_I(dst)->root;
  	const u64 aligned_end = ALIGN(new_key->offset + datal,
  				      root->sectorsize);
  	int ret;
  	struct btrfs_key key;
  
  	if (new_key->offset > 0)
  		return -EOPNOTSUPP;
  
  	key.objectid = btrfs_ino(dst);
  	key.type = BTRFS_EXTENT_DATA_KEY;
  	key.offset = 0;
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  	if (ret < 0) {
  		return ret;
  	} else if (ret > 0) {
  		if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
  			ret = btrfs_next_leaf(root, path);
  			if (ret < 0)
  				return ret;
  			else if (ret > 0)
  				goto copy_inline_extent;
  		}
  		btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
  		if (key.objectid == btrfs_ino(dst) &&
  		    key.type == BTRFS_EXTENT_DATA_KEY) {
  			ASSERT(key.offset > 0);
  			return -EOPNOTSUPP;
  		}
  	} else if (i_size_read(dst) <= datal) {
  		struct btrfs_file_extent_item *ei;
  		u64 ext_len;
  
  		/*
  		 * If the file size is <= datal, make sure there are no other
  		 * extents following (can happen do to an fallocate call with
  		 * the flag FALLOC_FL_KEEP_SIZE).
  		 */
  		ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
  				    struct btrfs_file_extent_item);
  		/*
  		 * If it's an inline extent, it can not have other extents
  		 * following it.
  		 */
  		if (btrfs_file_extent_type(path->nodes[0], ei) ==
  		    BTRFS_FILE_EXTENT_INLINE)
  			goto copy_inline_extent;
  
  		ext_len = btrfs_file_extent_num_bytes(path->nodes[0], ei);
  		if (ext_len > aligned_end)
  			return -EOPNOTSUPP;
  
  		ret = btrfs_next_item(root, path);
  		if (ret < 0) {
  			return ret;
  		} else if (ret == 0) {
  			btrfs_item_key_to_cpu(path->nodes[0], &key,
  					      path->slots[0]);
  			if (key.objectid == btrfs_ino(dst) &&
  			    key.type == BTRFS_EXTENT_DATA_KEY)
  				return -EOPNOTSUPP;
  		}
  	}
  
  copy_inline_extent:
  	/*
  	 * We have no extent items, or we have an extent at offset 0 which may
  	 * or may not be inlined. All these cases are dealt the same way.
  	 */
  	if (i_size_read(dst) > datal) {
  		/*
  		 * If the destination inode has an inline extent...
  		 * This would require copying the data from the source inline
  		 * extent into the beginning of the destination's inline extent.
  		 * But this is really complex, both extents can be compressed
  		 * or just one of them, which would require decompressing and
  		 * re-compressing data (which could increase the new compressed
  		 * size, not allowing the compressed data to fit anymore in an
  		 * inline extent).
  		 * So just don't support this case for now (it should be rare,
  		 * we are not really saving space when cloning inline extents).
  		 */
  		return -EOPNOTSUPP;
  	}
  
  	btrfs_release_path(path);
  	ret = btrfs_drop_extents(trans, root, dst, drop_start, aligned_end, 1);
  	if (ret)
  		return ret;
  	ret = btrfs_insert_empty_item(trans, root, path, new_key, size);
  	if (ret)
  		return ret;
  
  	if (skip) {
  		const u32 start = btrfs_file_extent_calc_inline_size(0);
  
  		memmove(inline_data + start, inline_data + start + skip, datal);
  	}
  
  	write_extent_buffer(path->nodes[0], inline_data,
  			    btrfs_item_ptr_offset(path->nodes[0],
  						  path->slots[0]),
  			    size);
  	inode_add_bytes(dst, datal);
  
  	return 0;
  }
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3329
3330
3331
3332
3333
3334
3335
  /**
   * 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
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3336
   * @olen_aligned: Block-aligned value of olen
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3337
   * @destoff: Offset within @inode to start clone
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3338
   * @no_time_update: Whether to update mtime/ctime on the target inode
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3339
3340
   */
  static int btrfs_clone(struct inode *src, struct inode *inode,
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3341
  		       const u64 off, const u64 olen, const u64 olen_aligned,
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3342
  		       const u64 destoff, int no_time_update)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3343
  {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3344
  	struct btrfs_root *root = BTRFS_I(inode)->root;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3345
  	struct btrfs_path *path = NULL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3346
  	struct extent_buffer *leaf;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3347
3348
  	struct btrfs_trans_handle *trans;
  	char *buf = NULL;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3349
  	struct btrfs_key key;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3350
3351
  	u32 nritems;
  	int slot;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3352
  	int ret;
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3353
  	const u64 len = olen_aligned;
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3354
  	u64 last_dest_end = destoff;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3355
3356
  
  	ret = -ENOMEM;
153519559   David Sterba   btrfs: clone: use...
3357
3358
3359
3360
3361
3362
  	buf = kmalloc(root->nodesize, GFP_KERNEL | __GFP_NOWARN);
  	if (!buf) {
  		buf = vmalloc(root->nodesize);
  		if (!buf)
  			return ret;
  	}
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3363
3364
3365
  
  	path = btrfs_alloc_path();
  	if (!path) {
153519559   David Sterba   btrfs: clone: use...
3366
  		kvfree(buf);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3367
  		return ret;
d525e8ab0   Li Zefan   Btrfs: add dummy ...
3368
  	}
e4058b54d   David Sterba   btrfs: cleanup, u...
3369
  	path->reada = READA_FORWARD;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3370
  	/* clone data */
33345d015   Li Zefan   Btrfs: Always use...
3371
  	key.objectid = btrfs_ino(src);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3372
  	key.type = BTRFS_EXTENT_DATA_KEY;
2c463823c   Filipe Manana   Btrfs: avoid visi...
3373
  	key.offset = off;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3374
3375
  
  	while (1) {
de249e66a   Chris Mason   Btrfs: fix uninit...
3376
  		u64 next_key_min_offset = key.offset + 1;
df858e767   Filipe Manana   Btrfs: fix range ...
3377

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3378
3379
3380
3381
  		/*
  		 * note the key will change type as we walk through the
  		 * tree.
  		 */
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3382
  		path->leave_spinning = 1;
362a20c5e   David Sterba   btrfs: allow cros...
3383
3384
  		ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path,
  				0, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3385
3386
  		if (ret < 0)
  			goto out;
2c463823c   Filipe Manana   Btrfs: avoid visi...
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
  		/*
  		 * First search, if no extent item that starts at offset off was
  		 * found but the previous item is an extent item, it's possible
  		 * it might overlap our target range, therefore process it.
  		 */
  		if (key.offset == off && ret > 0 && path->slots[0] > 0) {
  			btrfs_item_key_to_cpu(path->nodes[0], &key,
  					      path->slots[0] - 1);
  			if (key.type == BTRFS_EXTENT_DATA_KEY)
  				path->slots[0]--;
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3398

ae01a0abf   Yan Zheng   Btrfs: Update clo...
3399
  		nritems = btrfs_header_nritems(path->nodes[0]);
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3400
  process_slot:
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3401
  		if (path->slots[0] >= nritems) {
362a20c5e   David Sterba   btrfs: allow cros...
3402
  			ret = btrfs_next_leaf(BTRFS_I(src)->root, path);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3403
3404
3405
3406
  			if (ret < 0)
  				goto out;
  			if (ret > 0)
  				break;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3407
  			nritems = btrfs_header_nritems(path->nodes[0]);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3408
3409
3410
  		}
  		leaf = path->nodes[0];
  		slot = path->slots[0];
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3411

ae01a0abf   Yan Zheng   Btrfs: Update clo...
3412
  		btrfs_item_key_to_cpu(leaf, &key, slot);
962a298f3   David Sterba   btrfs: kill the k...
3413
  		if (key.type > BTRFS_EXTENT_DATA_KEY ||
33345d015   Li Zefan   Btrfs: Always use...
3414
  		    key.objectid != btrfs_ino(src))
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3415
  			break;
962a298f3   David Sterba   btrfs: kill the k...
3416
  		if (key.type == BTRFS_EXTENT_DATA_KEY) {
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3417
3418
  			struct btrfs_file_extent_item *extent;
  			int type;
31840ae1a   Zheng Yan   Btrfs: Full back ...
3419
3420
  			u32 size;
  			struct btrfs_key new_key;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3421
3422
3423
  			u64 disko = 0, diskl = 0;
  			u64 datao = 0, datal = 0;
  			u8 comp;
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3424
  			u64 drop_start;
31840ae1a   Zheng Yan   Btrfs: Full back ...
3425

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3426
3427
3428
3429
  			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...
3430
3431
  			if (type == BTRFS_FILE_EXTENT_REG ||
  			    type == BTRFS_FILE_EXTENT_PREALLOC) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
3432
3433
3434
3435
  				disko = btrfs_file_extent_disk_bytenr(leaf,
  								      extent);
  				diskl = btrfs_file_extent_disk_num_bytes(leaf,
  								 extent);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3436
  				datao = btrfs_file_extent_offset(leaf, extent);
d397712bc   Chris Mason   Btrfs: Fix checkp...
3437
3438
  				datal = btrfs_file_extent_num_bytes(leaf,
  								    extent);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3439
3440
3441
3442
3443
  			} 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 ...
3444

2c463823c   Filipe Manana   Btrfs: avoid visi...
3445
3446
3447
3448
3449
3450
  			/*
  			 * The first search might have left us at an extent
  			 * item that ends before our target range's start, can
  			 * happen if we have holes and NO_HOLES feature enabled.
  			 */
  			if (key.offset + datal <= off) {
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3451
3452
  				path->slots[0]++;
  				goto process_slot;
2c463823c   Filipe Manana   Btrfs: avoid visi...
3453
3454
  			} else if (key.offset >= off + len) {
  				break;
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3455
  			}
df858e767   Filipe Manana   Btrfs: fix range ...
3456
  			next_key_min_offset = key.offset + datal;
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3457
3458
3459
3460
3461
3462
3463
  			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...
3464

31840ae1a   Zheng Yan   Btrfs: Full back ...
3465
  			memcpy(&new_key, &key, sizeof(new_key));
33345d015   Li Zefan   Btrfs: Always use...
3466
  			new_key.objectid = btrfs_ino(inode);
4d728ec7a   Li Zefan   Btrfs: Fix file c...
3467
3468
3469
3470
  			if (off <= key.offset)
  				new_key.offset = key.offset + destoff - off;
  			else
  				new_key.offset = destoff;
31840ae1a   Zheng Yan   Btrfs: Full back ...
3471

b6f3409b2   Sage Weil   Btrfs: reserve su...
3472
  			/*
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
  			 * Deal with a hole that doesn't have an extent item
  			 * that represents it (NO_HOLES feature enabled).
  			 * This hole is either in the middle of the cloning
  			 * range or at the beginning (fully overlaps it or
  			 * partially overlaps it).
  			 */
  			if (new_key.offset != last_dest_end)
  				drop_start = last_dest_end;
  			else
  				drop_start = new_key.offset;
  
  			/*
b6f3409b2   Sage Weil   Btrfs: reserve su...
3485
3486
3487
3488
3489
  			 * 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 ...
3490
3491
3492
3493
  			if (IS_ERR(trans)) {
  				ret = PTR_ERR(trans);
  				goto out;
  			}
c8a894d77   Chris Mason   Btrfs: fix the fi...
3494
3495
  			if (type == BTRFS_FILE_EXTENT_REG ||
  			    type == BTRFS_FILE_EXTENT_PREALLOC) {
d72c0842f   Li Zefan   Btrfs: calc file ...
3496
3497
3498
3499
  				/*
  				 *    a  | --- range to clone ---|  b
  				 * | ------------- extent ------------- |
  				 */
939155841   Antonio Ospite   trivial: fs/btrfs...
3500
  				/* subtract range b */
d72c0842f   Li Zefan   Btrfs: calc file ...
3501
3502
  				if (key.offset + datal > off + len)
  					datal = off + len - key.offset;
939155841   Antonio Ospite   trivial: fs/btrfs...
3503
  				/* subtract range a */
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3504
3505
3506
3507
  				if (off > key.offset) {
  					datao += off - key.offset;
  					datal -= off - key.offset;
  				}
5dc562c54   Josef Bacik   Btrfs: turbo char...
3508
  				ret = btrfs_drop_extents(trans, root, inode,
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3509
  							 drop_start,
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3510
  							 new_key.offset + datal,
2671485d3   Josef Bacik   Btrfs: remove unu...
3511
  							 1);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3512
  				if (ret) {
3f9e3df8d   David Sterba   btrfs: replace er...
3513
  					if (ret != -EOPNOTSUPP)
00fdf13a2   Liu Bo   Btrfs: fix a cras...
3514
  						btrfs_abort_transaction(trans,
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
3515
  									ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3516
3517
3518
  					btrfs_end_transaction(trans, root);
  					goto out;
  				}
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3519

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3520
3521
  				ret = btrfs_insert_empty_item(trans, root, path,
  							      &new_key, size);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3522
  				if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
3523
  					btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3524
3525
3526
  					btrfs_end_transaction(trans, root);
  					goto out;
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3527
3528
3529
3530
  
  				leaf = path->nodes[0];
  				slot = path->slots[0];
  				write_extent_buffer(leaf, buf,
31840ae1a   Zheng Yan   Btrfs: Full back ...
3531
3532
  					    btrfs_item_ptr_offset(leaf, slot),
  					    size);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3533

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

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3537
3538
3539
  				/* disko == 0 means it's a hole */
  				if (!disko)
  					datao = 0;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3540
3541
3542
3543
3544
  
  				btrfs_set_file_extent_offset(leaf, extent,
  							     datao);
  				btrfs_set_file_extent_num_bytes(leaf, extent,
  								datal);
fcebe4562   Josef Bacik   Btrfs: rework qgr...
3545

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3546
3547
  				if (disko) {
  					inode_add_bytes(inode, datal);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3548
  					ret = btrfs_inc_extent_ref(trans, root,
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3549
3550
  							disko, diskl, 0,
  							root->root_key.objectid,
33345d015   Li Zefan   Btrfs: Always use...
3551
  							btrfs_ino(inode),
b06c4bf5c   Filipe Manana   Btrfs: fix regres...
3552
  							new_key.offset - datao);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3553
3554
  					if (ret) {
  						btrfs_abort_transaction(trans,
79787eaab   Jeff Mahoney   btrfs: replace ma...
3555
3556
3557
3558
3559
3560
  									ret);
  						btrfs_end_transaction(trans,
  								      root);
  						goto out;
  
  					}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3561
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3562
3563
3564
  			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
  				u64 skip = 0;
  				u64 trim = 0;
ed9587626   Filipe Manana   Btrfs: fix file c...
3565

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3566
3567
3568
3569
  				if (off > key.offset) {
  					skip = off - key.offset;
  					new_key.offset += skip;
  				}
d397712bc   Chris Mason   Btrfs: Fix checkp...
3570

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

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3574
  				if (comp && (skip || trim)) {
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3575
  					ret = -EINVAL;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3576
  					btrfs_end_transaction(trans, root);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3577
3578
3579
3580
  					goto out;
  				}
  				size -= skip + trim;
  				datal -= skip + trim;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3581

8039d87d9   Filipe Manana   Btrfs: fix file c...
3582
3583
3584
3585
3586
3587
  				ret = clone_copy_inline_extent(src, inode,
  							       trans, path,
  							       &new_key,
  							       drop_start,
  							       datal,
  							       skip, size, buf);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3588
  				if (ret) {
3f9e3df8d   David Sterba   btrfs: replace er...
3589
  					if (ret != -EOPNOTSUPP)
3a29bc092   Chris Mason   Btrfs: fix EINVAL...
3590
  						btrfs_abort_transaction(trans,
8039d87d9   Filipe Manana   Btrfs: fix file c...
3591
  									ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3592
3593
3594
  					btrfs_end_transaction(trans, root);
  					goto out;
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3595
3596
  				leaf = path->nodes[0];
  				slot = path->slots[0];
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3597
  			}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3598

7ffbb598a   Filipe Manana   Btrfs: make fsync...
3599
3600
3601
  			/* If we have an implicit hole (NO_HOLES feature). */
  			if (drop_start < new_key.offset)
  				clone_update_extent_map(inode, trans,
14f597963   Filipe Manana   Btrfs: fix use-af...
3602
  						NULL, drop_start,
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3603
  						new_key.offset - drop_start);
14f597963   Filipe Manana   Btrfs: fix use-af...
3604
  			clone_update_extent_map(inode, trans, path, 0, 0);
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3605

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3606
  			btrfs_mark_buffer_dirty(leaf);
b3b4aa74b   David Sterba   btrfs: drop unuse...
3607
  			btrfs_release_path(path);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3608

62e2390e1   Filipe Manana   Btrfs: clone, don...
3609
3610
  			last_dest_end = ALIGN(new_key.offset + datal,
  					      root->sectorsize);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3611
3612
  			ret = clone_finish_inode_update(trans, inode,
  							last_dest_end,
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3613
3614
  							destoff, olen,
  							no_time_update);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3615
  			if (ret)
79787eaab   Jeff Mahoney   btrfs: replace ma...
3616
  				goto out;
2c463823c   Filipe Manana   Btrfs: avoid visi...
3617
3618
  			if (new_key.offset + datal >= destoff + len)
  				break;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3619
  		}
b3b4aa74b   David Sterba   btrfs: drop unuse...
3620
  		btrfs_release_path(path);
df858e767   Filipe Manana   Btrfs: fix range ...
3621
  		key.offset = next_key_min_offset;
69ae5e445   Wang Xiaoguang   btrfs: make file ...
3622
3623
3624
3625
3626
  
  		if (fatal_signal_pending(current)) {
  			ret = -EINTR;
  			goto out;
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3627
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3628
  	ret = 0;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3629

f82a9901b   Filipe Manana   Btrfs: fix clone ...
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
  	if (last_dest_end < destoff + len) {
  		/*
  		 * We have an implicit hole (NO_HOLES feature is enabled) that
  		 * fully or partially overlaps our cloning range at its end.
  		 */
  		btrfs_release_path(path);
  
  		/*
  		 * 1 - remove extent(s)
  		 * 1 - inode update
  		 */
  		trans = btrfs_start_transaction(root, 2);
  		if (IS_ERR(trans)) {
  			ret = PTR_ERR(trans);
  			goto out;
  		}
  		ret = btrfs_drop_extents(trans, root, inode,
  					 last_dest_end, destoff + len, 1);
  		if (ret) {
  			if (ret != -EOPNOTSUPP)
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
3650
  				btrfs_abort_transaction(trans, ret);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3651
3652
3653
  			btrfs_end_transaction(trans, root);
  			goto out;
  		}
14f597963   Filipe Manana   Btrfs: fix use-af...
3654
3655
  		clone_update_extent_map(inode, trans, NULL, last_dest_end,
  					destoff + len - last_dest_end);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3656
  		ret = clone_finish_inode_update(trans, inode, destoff + len,
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3657
  						destoff, olen, no_time_update);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3658
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3659
  out:
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3660
  	btrfs_free_path(path);
153519559   David Sterba   btrfs: clone: use...
3661
  	kvfree(buf);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3662
3663
  	return ret;
  }
3db11b2ee   Zach Brown   btrfs: add .copy_...
3664
3665
  static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
  					u64 off, u64 olen, u64 destoff)
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3666
  {
54563d41a   Al Viro   btrfs: get rid of...
3667
  	struct inode *inode = file_inode(file);
3db11b2ee   Zach Brown   btrfs: add .copy_...
3668
  	struct inode *src = file_inode(file_src);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3669
  	struct btrfs_root *root = BTRFS_I(inode)->root;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3670
3671
3672
  	int ret;
  	u64 len = olen;
  	u64 bs = root->fs_info->sb->s_blocksize;
3db11b2ee   Zach Brown   btrfs: add .copy_...
3673
  	int same_inode = src == inode;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3674
3675
3676
3677
3678
3679
3680
  
  	/*
  	 * 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...
3681
3682
3683
  	 *
  	 * - split destination inode's inline extents.  The inline extents can
  	 *   be either compressed or non-compressed.
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3684
  	 */
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3685
3686
  	if (btrfs_root_readonly(root))
  		return -EROFS;
3db11b2ee   Zach Brown   btrfs: add .copy_...
3687
3688
3689
  	if (file_src->f_path.mnt != file->f_path.mnt ||
  	    src->i_sb != inode->i_sb)
  		return -EXDEV;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3690
3691
3692
3693
  
  	/* don't make the dst file partly checksummed */
  	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
  	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
3db11b2ee   Zach Brown   btrfs: add .copy_...
3694
  		return -EINVAL;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3695

32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3696
  	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
3db11b2ee   Zach Brown   btrfs: add .copy_...
3697
  		return -EISDIR;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3698
3699
  
  	if (!same_inode) {
293a8489f   Mark Fasheh   btrfs: fix clone ...
3700
  		btrfs_double_inode_lock(src, inode);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3701
  	} else {
5955102c9   Al Viro   wrappers for ->i_...
3702
  		inode_lock(src);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
  	}
  
  	/* 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;
ccccf3d67   Filipe Manana   Btrfs: fix inode ...
3714
3715
3716
3717
  	if (len == 0) {
  		ret = 0;
  		goto out_unlock;
  	}
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
  	/* 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;
  	}
c125b8bff   Filipe Manana   Btrfs: ensure rea...
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
  	/*
  	 * Lock the target range too. Right after we replace the file extent
  	 * items in the fs tree (which now point to the cloned data), we might
  	 * have a worker replace them with extent items relative to a write
  	 * operation that was issued before this clone operation (i.e. confront
  	 * with inode.c:btrfs_finish_ordered_io).
  	 */
  	if (same_inode) {
  		u64 lock_start = min_t(u64, off, destoff);
  		u64 lock_len = max_t(u64, off, destoff) + len - lock_start;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3744

e0bd70c67   Filipe Manana   Btrfs: fix invali...
3745
  		ret = lock_extent_range(src, lock_start, lock_len, true);
c125b8bff   Filipe Manana   Btrfs: ensure rea...
3746
  	} else {
e0bd70c67   Filipe Manana   Btrfs: fix invali...
3747
3748
3749
3750
3751
3752
3753
  		ret = btrfs_double_extent_lock(src, off, inode, destoff, len,
  					       true);
  	}
  	ASSERT(ret == 0);
  	if (WARN_ON(ret)) {
  		/* ranges in the io trees already unlocked */
  		goto out_unlock;
c125b8bff   Filipe Manana   Btrfs: ensure rea...
3754
  	}
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3755

1c919a5e1   Mark Fasheh   btrfs: don't upda...
3756
  	ret = btrfs_clone(src, inode, off, olen, len, destoff, 0);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3757

c125b8bff   Filipe Manana   Btrfs: ensure rea...
3758
3759
3760
3761
3762
3763
  	if (same_inode) {
  		u64 lock_start = min_t(u64, off, destoff);
  		u64 lock_end = max_t(u64, off, destoff) + len - 1;
  
  		unlock_extent(&BTRFS_I(src)->io_tree, lock_start, lock_end);
  	} else {
293a8489f   Mark Fasheh   btrfs: fix clone ...
3764
  		btrfs_double_extent_unlock(src, off, inode, destoff, len);
c125b8bff   Filipe Manana   Btrfs: ensure rea...
3765
3766
3767
3768
3769
  	}
  	/*
  	 * Truncate page cache pages so that future reads will see the cloned
  	 * data immediately and not the previous data.
  	 */
65bfa6580   Chandan Rajendra   Btrfs: btrfs_ioct...
3770
  	truncate_inode_pages_range(&inode->i_data,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
3771
3772
  				round_down(destoff, PAGE_SIZE),
  				round_up(destoff + len, PAGE_SIZE) - 1);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3773
  out_unlock:
293a8489f   Mark Fasheh   btrfs: fix clone ...
3774
3775
3776
  	if (!same_inode)
  		btrfs_double_inode_unlock(src, inode);
  	else
5955102c9   Al Viro   wrappers for ->i_...
3777
  		inode_unlock(src);
3db11b2ee   Zach Brown   btrfs: add .copy_...
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
  	return ret;
  }
  
  ssize_t btrfs_copy_file_range(struct file *file_in, loff_t pos_in,
  			      struct file *file_out, loff_t pos_out,
  			      size_t len, unsigned int flags)
  {
  	ssize_t ret;
  
  	ret = btrfs_clone_files(file_out, file_in, pos_in, len, pos_out);
  	if (ret == 0)
  		ret = len;
  	return ret;
  }
04b38d601   Christoph Hellwig   vfs: pull btrfs c...
3792
3793
  int btrfs_clone_file_range(struct file *src_file, loff_t off,
  		struct file *dst_file, loff_t destoff, u64 len)
3db11b2ee   Zach Brown   btrfs: add .copy_...
3794
  {
04b38d601   Christoph Hellwig   vfs: pull btrfs c...
3795
  	return btrfs_clone_files(dst_file, src_file, off, len, destoff);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3796
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3797
3798
3799
3800
3801
3802
  /*
   * 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...
3803
  static long btrfs_ioctl_trans_start(struct file *file)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3804
  {
496ad9aa8   Al Viro   new helper: file_...
3805
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3806
3807
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
1ab86aedb   Sage Weil   Btrfs: fix error ...
3808
  	int ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3809

1ab86aedb   Sage Weil   Btrfs: fix error ...
3810
  	ret = -EPERM;
df5b5520b   Christoph Hellwig   BTRFS_IOC_TRANS_S...
3811
  	if (!capable(CAP_SYS_ADMIN))
1ab86aedb   Sage Weil   Btrfs: fix error ...
3812
  		goto out;
df5b5520b   Christoph Hellwig   BTRFS_IOC_TRANS_S...
3813

1ab86aedb   Sage Weil   Btrfs: fix error ...
3814
3815
  	ret = -EINPROGRESS;
  	if (file->private_data)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3816
  		goto out;
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3817

b83cc9693   Li Zefan   Btrfs: Add readon...
3818
3819
3820
  	ret = -EROFS;
  	if (btrfs_root_readonly(root))
  		goto out;
a561be710   Al Viro   switch a bunch of...
3821
  	ret = mnt_want_write_file(file);
c146afad2   Yan Zheng   Btrfs: mount ro a...
3822
3823
  	if (ret)
  		goto out;
a4abeea41   Josef Bacik   Btrfs: kill trans...
3824
  	atomic_inc(&root->fs_info->open_ioctl_trans);
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3825

1ab86aedb   Sage Weil   Btrfs: fix error ...
3826
  	ret = -ENOMEM;
7a7eaa40a   Josef Bacik   Btrfs: take away ...
3827
  	trans = btrfs_start_ioctl_transaction(root);
abd30bb0a   Tsutomu Itoh   btrfs: check retu...
3828
  	if (IS_ERR(trans))
1ab86aedb   Sage Weil   Btrfs: fix error ...
3829
3830
3831
3832
3833
3834
  		goto out_drop;
  
  	file->private_data = trans;
  	return 0;
  
  out_drop:
a4abeea41   Josef Bacik   Btrfs: kill trans...
3835
  	atomic_dec(&root->fs_info->open_ioctl_trans);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
3836
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3837
  out:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3838
3839
  	return ret;
  }
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3840
3841
  static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
  {
496ad9aa8   Al Viro   new helper: file_...
3842
  	struct inode *inode = file_inode(file);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3843
3844
3845
3846
3847
3848
3849
  	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 ...
3850
3851
  	u64 objectid = 0;
  	u64 dir_id;
3c04ce010   Miao Xie   Btrfs: get write ...
3852
  	int ret;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3853
3854
3855
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
3c04ce010   Miao Xie   Btrfs: get write ...
3856
3857
3858
3859
3860
3861
3862
3863
  	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 ...
3864
3865
  
  	if (!objectid)
1cecf579d   chandan   Btrfs: btrfs_ioct...
3866
  		objectid = BTRFS_FS_TREE_OBJECTID;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3867
3868
3869
3870
3871
3872
  
  	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 ...
3873
3874
3875
3876
  	if (IS_ERR(new_root)) {
  		ret = PTR_ERR(new_root);
  		goto out;
  	}
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3877

6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3878
  	path = btrfs_alloc_path();
3c04ce010   Miao Xie   Btrfs: get write ...
3879
3880
3881
3882
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3883
3884
3885
  	path->leave_spinning = 1;
  
  	trans = btrfs_start_transaction(root, 1);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
3886
  	if (IS_ERR(trans)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3887
  		btrfs_free_path(path);
3c04ce010   Miao Xie   Btrfs: get write ...
3888
3889
  		ret = PTR_ERR(trans);
  		goto out;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3890
  	}
6c41761fc   David Sterba   btrfs: separate s...
3891
  	dir_id = btrfs_super_root_dir(root->fs_info->super_copy);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3892
3893
  	di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path,
  				   dir_id, "default", 7, 1);
cf1e99a4e   Dan Carpenter   Btrfs: btrfs_look...
3894
  	if (IS_ERR_OR_NULL(di)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3895
3896
  		btrfs_free_path(path);
  		btrfs_end_transaction(trans, root);
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
3897
3898
  		btrfs_err(new_root->fs_info,
  			  "Umm, you don't have the default diritem, this isn't going to work");
3c04ce010   Miao Xie   Btrfs: get write ...
3899
3900
  		ret = -ENOENT;
  		goto out;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3901
3902
3903
3904
3905
3906
  	}
  
  	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...
3907
  	btrfs_set_fs_incompat(root->fs_info, DEFAULT_SUBVOL);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3908
  	btrfs_end_transaction(trans, root);
3c04ce010   Miao Xie   Btrfs: get write ...
3909
3910
3911
  out:
  	mnt_drop_write_file(file);
  	return ret;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3912
  }
5af3e8cce   Stefan Behrens   Btrfs: make files...
3913
3914
  void btrfs_get_block_group_info(struct list_head *groups_list,
  				struct btrfs_ioctl_space_info *space)
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
  {
  	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...
3928
  static long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
1406e4327   Josef Bacik   Btrfs: add a "df"...
3929
3930
3931
3932
  {
  	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...
3933
  	struct btrfs_ioctl_space_info *dest_orig;
13f2696f1   Daniel J Blueman   fix user annotati...
3934
  	struct btrfs_ioctl_space_info __user *user_dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3935
  	struct btrfs_space_info *info;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3936
3937
3938
3939
3940
  	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...
3941
  	int alloc_size;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3942
  	int ret = 0;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
3943
  	u64 slot_count = 0;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3944
  	int i, c;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3945
3946
3947
3948
3949
  
  	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...
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
  	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...
3974

36523e951   David Sterba   btrfs: export glo...
3975
3976
3977
3978
  	/*
  	 * Global block reserve, exported as a space_info
  	 */
  	slot_count++;
7fde62bff   Chris Mason   Btrfs: buffer res...
3979
3980
3981
3982
3983
  	/* 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...
3984

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

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

7fde62bff   Chris Mason   Btrfs: buffer res...
3989
3990
3991
  	/* 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
  	 */
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
3992
  	if (alloc_size > PAGE_SIZE)
7fde62bff   Chris Mason   Btrfs: buffer res...
3993
  		return -ENOMEM;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3994
  	space_args.total_spaces = 0;
8d2db7855   David Sterba   btrfs: use GFP_KE...
3995
  	dest = kmalloc(alloc_size, GFP_KERNEL);
7fde62bff   Chris Mason   Btrfs: buffer res...
3996
3997
3998
  	if (!dest)
  		return -ENOMEM;
  	dest_orig = dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3999

7fde62bff   Chris Mason   Btrfs: buffer res...
4000
  	/* now we have a buffer to copy into */
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4001
4002
  	for (i = 0; i < num_types; i++) {
  		struct btrfs_space_info *tmp;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
4003
4004
  		if (!slot_count)
  			break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
  		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...
4015

bf5fc093c   Josef Bacik   Btrfs: fix the df...
4016
4017
4018
4019
4020
  		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...
4021
4022
  				btrfs_get_block_group_info(
  					&info->block_groups[c], &space);
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4023
4024
4025
  				memcpy(dest, &space, sizeof(space));
  				dest++;
  				space_args.total_spaces++;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
4026
  				slot_count--;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4027
  			}
51788b1bd   Dan Rosenberg   btrfs: prevent he...
4028
4029
  			if (!slot_count)
  				break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4030
4031
  		}
  		up_read(&info->groups_sem);
1406e4327   Josef Bacik   Btrfs: add a "df"...
4032
  	}
1406e4327   Josef Bacik   Btrfs: add a "df"...
4033

36523e951   David Sterba   btrfs: export glo...
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
  	/*
  	 * 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...
4048
  	user_dest = (struct btrfs_ioctl_space_info __user *)
7fde62bff   Chris Mason   Btrfs: buffer res...
4049
4050
4051
4052
4053
4054
4055
4056
  		(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"...
4057
4058
4059
4060
  		ret = -EFAULT;
  
  	return ret;
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4061
4062
4063
4064
4065
4066
4067
4068
  /*
   * 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_...
4069
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4070
4071
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4072

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4073
  	trans = file->private_data;
1ab86aedb   Sage Weil   Btrfs: fix error ...
4074
4075
  	if (!trans)
  		return -EINVAL;
b214107ed   Christoph Hellwig   Btrfs: trivial sp...
4076
  	file->private_data = NULL;
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
4077

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

2a79f17e4   Al Viro   vfs: mnt_drop_wri...
4081
  	mnt_drop_write_file(file);
1ab86aedb   Sage Weil   Btrfs: fix error ...
4082
  	return 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4083
  }
9a8c28bec   Miao Xie   Btrfs: pass root ...
4084
4085
  static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
  					    void __user *argp)
462045928   Sage Weil   Btrfs: add START_...
4086
  {
462045928   Sage Weil   Btrfs: add START_...
4087
4088
  	struct btrfs_trans_handle *trans;
  	u64 transid;
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
4089
  	int ret;
462045928   Sage Weil   Btrfs: add START_...
4090

d4edf39bd   Miao Xie   Btrfs: fix uncomp...
4091
  	trans = btrfs_attach_transaction_barrier(root);
ff7c1d335   Miao Xie   Btrfs: don't star...
4092
4093
4094
4095
4096
4097
4098
4099
  	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_...
4100
  	transid = trans->transid;
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
4101
  	ret = btrfs_commit_transaction_async(trans, root, 0);
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
4102
4103
  	if (ret) {
  		btrfs_end_transaction(trans, root);
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
4104
  		return ret;
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
4105
  	}
ff7c1d335   Miao Xie   Btrfs: don't star...
4106
  out:
462045928   Sage Weil   Btrfs: add START_...
4107
4108
4109
4110
4111
  	if (argp)
  		if (copy_to_user(argp, &transid, sizeof(transid)))
  			return -EFAULT;
  	return 0;
  }
9a8c28bec   Miao Xie   Btrfs: pass root ...
4112
4113
  static noinline long btrfs_ioctl_wait_sync(struct btrfs_root *root,
  					   void __user *argp)
462045928   Sage Weil   Btrfs: add START_...
4114
  {
462045928   Sage Weil   Btrfs: add START_...
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
  	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 ...
4125
  static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
475f63874   Jan Schmidt   btrfs: new ioctls...
4126
  {
496ad9aa8   Al Viro   new helper: file_...
4127
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
475f63874   Jan Schmidt   btrfs: new ioctls...
4128
  	struct btrfs_ioctl_scrub_args *sa;
b8e95489b   Miao Xie   Btrfs: get write ...
4129
  	int ret;
475f63874   Jan Schmidt   btrfs: new ioctls...
4130
4131
4132
4133
4134
4135
4136
  
  	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 ...
4137
4138
4139
4140
4141
  	if (!(sa->flags & BTRFS_SCRUB_READONLY)) {
  		ret = mnt_want_write_file(file);
  		if (ret)
  			goto out;
  	}
aa1b8cd40   Stefan Behrens   Btrfs: pass fs_in...
4142
  	ret = btrfs_scrub_dev(root->fs_info, sa->devid, sa->start, sa->end,
63a212abc   Stefan Behrens   Btrfs: disallow s...
4143
4144
  			      &sa->progress, sa->flags & BTRFS_SCRUB_READONLY,
  			      0);
475f63874   Jan Schmidt   btrfs: new ioctls...
4145
4146
4147
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
b8e95489b   Miao Xie   Btrfs: get write ...
4148
4149
4150
  	if (!(sa->flags & BTRFS_SCRUB_READONLY))
  		mnt_drop_write_file(file);
  out:
475f63874   Jan Schmidt   btrfs: new ioctls...
4151
4152
4153
4154
4155
4156
4157
4158
  	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...
4159
  	return btrfs_scrub_cancel(root->fs_info);
475f63874   Jan Schmidt   btrfs: new ioctls...
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
  }
  
  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 ...
4183
  static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root,
b27f7c0c1   David Sterba   btrfs: join DEV_S...
4184
  				      void __user *arg)
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
4185
4186
4187
  {
  	struct btrfs_ioctl_get_dev_stats *sa;
  	int ret;
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
4188
4189
4190
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
b27f7c0c1   David Sterba   btrfs: join DEV_S...
4191
4192
4193
4194
4195
4196
  	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 ...
4197
4198
4199
4200
4201
4202
4203
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
  
  	kfree(sa);
  	return ret;
  }
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
  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...
4218
4219
4220
4221
  		if (root->fs_info->sb->s_flags & MS_RDONLY) {
  			ret = -EROFS;
  			goto out;
  		}
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4222
4223
4224
  		if (atomic_xchg(
  			&root->fs_info->mutually_exclusive_operation_running,
  			1)) {
e57138b3e   Anand Jain   btrfs: return btr...
4225
  			ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4226
  		} else {
b5255456c   Anand Jain   btrfs: refactor b...
4227
  			ret = btrfs_dev_replace_by_ioctl(root, p);
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
  			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...
4247
  out:
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4248
4249
4250
  	kfree(p);
  	return ret;
  }
d7728c960   Jan Schmidt   btrfs: new ioctls...
4251
4252
4253
4254
  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...
4255
  	u64 rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4256
  	int size;
806468f8b   Chris Mason   Merge git://git.j...
4257
  	struct btrfs_ioctl_ino_path_args *ipa = NULL;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4258
4259
  	struct inode_fs_paths *ipath = NULL;
  	struct btrfs_path *path;
82b22ac8f   Kusanagi Kouichi   Btrfs: Check CAP_...
4260
  	if (!capable(CAP_DAC_READ_SEARCH))
d7728c960   Jan Schmidt   btrfs: new ioctls...
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
  		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/...
4289
4290
  		rel_ptr = ipath->fspath->val[i] -
  			  (u64)(unsigned long)ipath->fspath->val;
740c3d226   Chris Mason   Btrfs: fix the ne...
4291
  		ipath->fspath->val[i] = rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4292
  	}
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
4293
4294
  	ret = copy_to_user((void *)(unsigned long)ipa->fspath,
  			   (void *)(unsigned long)ipath->fspath, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
  	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...
4333
4334
4335
  	struct btrfs_ioctl_logical_ino_args *loi;
  	struct btrfs_data_container *inodes = NULL;
  	struct btrfs_path *path = NULL;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
  
  	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;
  	}
ee22184b5   Byongho Lee   Btrfs: use linux/...
4352
  	size = min_t(u32, loi->size, SZ_64K);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4353
4354
4355
4356
4357
4358
  	inodes = init_data_container(size);
  	if (IS_ERR(inodes)) {
  		ret = PTR_ERR(inodes);
  		inodes = NULL;
  		goto out;
  	}
df031f075   Liu Bo   Btrfs: use helper...
4359
4360
4361
  	ret = iterate_inodes_from_logical(loi->logical, root->fs_info, path,
  					  build_ino_list, inodes);
  	if (ret == -EINVAL)
d7728c960   Jan Schmidt   btrfs: new ioctls...
4362
4363
4364
  		ret = -ENOENT;
  	if (ret < 0)
  		goto out;
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
4365
4366
  	ret = copy_to_user((void *)(unsigned long)loi->inodes,
  			   (void *)(unsigned long)inodes, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4367
4368
4369
4370
4371
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	btrfs_free_path(path);
425d17a29   Liu Bo   Btrfs: use larger...
4372
  	vfree(inodes);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4373
4374
4375
4376
  	kfree(loi);
  
  	return ret;
  }
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4377
  void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4378
4379
4380
4381
4382
  			       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 ...
4383
4384
4385
4386
  	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 ...
4387
4388
  	if (atomic_read(&fs_info->balance_cancel_req))
  		bargs->state |= BTRFS_BALANCE_STATE_CANCEL_REQ;
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4389

c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4390
4391
4392
  	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...
4393
4394
4395
4396
4397
4398
4399
4400
  
  	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 ...
4401
  }
9ba1f6e44   Liu Bo   Btrfs: do not do ...
4402
  static long btrfs_ioctl_balance(struct file *file, void __user *arg)
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4403
  {
496ad9aa8   Al Viro   new helper: file_...
4404
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4405
4406
4407
  	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...
4408
  	bool need_unlock; /* for mut. excl. ops lock */
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4409
4410
4411
4412
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
e54bfa310   Liu Bo   Btrfs: use mnt_wa...
4413
  	ret = mnt_want_write_file(file);
9ba1f6e44   Liu Bo   Btrfs: do not do ...
4414
4415
  	if (ret)
  		return ret;
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4416
4417
4418
4419
4420
4421
4422
4423
4424
  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;
  	}
  
  	/*
013276101   Nicholas D Steeves   btrfs: fix string...
4425
  	 * mut. excl. ops lock is locked.  Three possibilities:
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4426
4427
4428
4429
  	 *   (1) some other op is running
  	 *   (2) balance is running
  	 *   (3) balance is paused -- special case (think resume)
  	 */
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4430
  	mutex_lock(&fs_info->balance_mutex);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
  	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...
4458
  		ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4459
4460
4461
4462
4463
  		goto out;
  	}
  
  locked:
  	BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4464
4465
4466
4467
4468
  
  	if (arg) {
  		bargs = memdup_user(arg, sizeof(*bargs));
  		if (IS_ERR(bargs)) {
  			ret = PTR_ERR(bargs);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4469
  			goto out_unlock;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4470
  		}
de322263d   Ilya Dryomov   Btrfs: allow for ...
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
  
  		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 ...
4485
4486
4487
  	} else {
  		bargs = NULL;
  	}
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4488
  	if (fs_info->balance_ctl) {
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4489
4490
4491
  		ret = -EINPROGRESS;
  		goto out_bargs;
  	}
8d2db7855   David Sterba   btrfs: use GFP_KE...
4492
  	bctl = kzalloc(sizeof(*bctl), GFP_KERNEL);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
  	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 ...
4505
4506
4507
  	} else {
  		/* balance everything - no filters */
  		bctl->flags |= BTRFS_BALANCE_TYPE_MASK;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4508
  	}
8eb934591   David Sterba   btrfs: check unsu...
4509
4510
  	if (bctl->flags & ~(BTRFS_BALANCE_ARGS_MASK | BTRFS_BALANCE_TYPE_MASK)) {
  		ret = -EINVAL;
0f89abf56   Christian Engelmayer   btrfs: fix possib...
4511
  		goto out_bctl;
8eb934591   David Sterba   btrfs: check unsu...
4512
  	}
de322263d   Ilya Dryomov   Btrfs: allow for ...
4513
  do_balance:
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4514
  	/*
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4515
4516
4517
4518
4519
  	 * 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 ...
4520
  	 */
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4521
4522
4523
  	need_unlock = false;
  
  	ret = btrfs_balance(bctl, bargs);
0f89abf56   Christian Engelmayer   btrfs: fix possib...
4524
  	bctl = NULL;
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4525

c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4526
4527
4528
4529
  	if (arg) {
  		if (copy_to_user(arg, bargs, sizeof(*bargs)))
  			ret = -EFAULT;
  	}
0f89abf56   Christian Engelmayer   btrfs: fix possib...
4530
4531
  out_bctl:
  	kfree(bctl);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4532
4533
  out_bargs:
  	kfree(bargs);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4534
  out_unlock:
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4535
4536
  	mutex_unlock(&fs_info->balance_mutex);
  	mutex_unlock(&fs_info->volume_mutex);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4537
4538
4539
  	if (need_unlock)
  		atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
  out:
e54bfa310   Liu Bo   Btrfs: use mnt_wa...
4540
  	mnt_drop_write_file(file);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4541
4542
  	return ret;
  }
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4543
4544
4545
4546
4547
4548
4549
4550
  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 ...
4551
4552
  	case BTRFS_BALANCE_CTL_CANCEL:
  		return btrfs_cancel_balance(root->fs_info);
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4553
4554
4555
4556
  	}
  
  	return -EINVAL;
  }
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
  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;
  	}
8d2db7855   David Sterba   btrfs: use GFP_KE...
4572
  	bargs = kzalloc(sizeof(*bargs), GFP_KERNEL);
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
  	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 ...
4588
  static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4589
  {
496ad9aa8   Al Viro   new helper: file_...
4590
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4591
4592
4593
4594
4595
4596
4597
  	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 ...
4598
4599
4600
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4601
4602
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4603
4604
4605
4606
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4607

7708f029d   Wang Shilong   Btrfs: creating t...
4608
  	down_write(&root->fs_info->subvol_sem);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4609
4610
4611
4612
  	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...
4613
4614
4615
4616
4617
4618
4619
4620
4621
  	}
  
  	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...
4622
4623
4624
4625
  	default:
  		ret = -EINVAL;
  		break;
  	}
2f2320360   Jan Schmidt   Btrfs: rescan for...
4626
4627
4628
  	err = btrfs_commit_transaction(trans, root->fs_info->tree_root);
  	if (err && !ret)
  		ret = err;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4629
4630
  out:
  	kfree(sa);
7708f029d   Wang Shilong   Btrfs: creating t...
4631
  	up_write(&root->fs_info->subvol_sem);
905b0dda0   Miao Xie   Btrfs: get write ...
4632
4633
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4634
4635
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4636
  static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4637
  {
496ad9aa8   Al Viro   new helper: file_...
4638
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4639
4640
4641
4642
4643
4644
4645
  	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 ...
4646
4647
4648
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4649
4650
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4651
4652
4653
4654
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
  
  	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);
  	}
e082f5631   Qu Wenruo   btrfs: quota: Upd...
4670
4671
4672
  	/* update qgroup status and info */
  	err = btrfs_run_qgroups(trans, root->fs_info);
  	if (err < 0)
ad8403df0   Anand Jain   btrfs: pass the r...
4673
4674
  		btrfs_handle_fs_error(root->fs_info, err,
  			    "failed to update qgroup status and info");
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4675
4676
4677
4678
4679
4680
  	err = btrfs_end_transaction(trans, root);
  	if (err && !ret)
  		ret = err;
  
  out:
  	kfree(sa);
905b0dda0   Miao Xie   Btrfs: get write ...
4681
4682
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4683
4684
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4685
  static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4686
  {
496ad9aa8   Al Viro   new helper: file_...
4687
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4688
4689
4690
4691
4692
4693
4694
  	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 ...
4695
4696
4697
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4698
4699
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4700
4701
4702
4703
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4704

d86e56cf7   Miao Xie   Btrfs: disable qg...
4705
4706
4707
4708
  	if (!sa->qgroupid) {
  		ret = -EINVAL;
  		goto out;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4709
4710
4711
4712
4713
4714
4715
4716
  	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) {
4087cf24a   Dongsheng Yang   Btrfs: qgroup: cl...
4717
  		ret = btrfs_create_qgroup(trans, root->fs_info, sa->qgroupid);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
  	} 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 ...
4728
4729
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4730
4731
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4732
  static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4733
  {
496ad9aa8   Al Viro   new helper: file_...
4734
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4735
4736
4737
4738
4739
4740
4741
4742
  	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 ...
4743
4744
4745
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4746
4747
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4748
4749
4750
4751
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
  
  	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 ...
4774
4775
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4776
4777
  	return ret;
  }
2f2320360   Jan Schmidt   Btrfs: rescan for...
4778
4779
  static long btrfs_ioctl_quota_rescan(struct file *file, void __user *arg)
  {
6d0379ec4   Al Viro   btrfs: more open-...
4780
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
2f2320360   Jan Schmidt   Btrfs: rescan for...
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
  	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-...
4813
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
2f2320360   Jan Schmidt   Btrfs: rescan for...
4814
4815
4816
4817
4818
  	struct btrfs_ioctl_quota_rescan_args *qsa;
  	int ret = 0;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
8d2db7855   David Sterba   btrfs: use GFP_KE...
4819
  	qsa = kzalloc(sizeof(*qsa), GFP_KERNEL);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
  	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 ...
4834
4835
  static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg)
  {
54563d41a   Al Viro   btrfs: get rid of...
4836
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4837
4838
4839
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
d06f23d6a   Jeff Mahoney   btrfs: waiting on...
4840
  	return btrfs_qgroup_wait_for_completion(root->fs_info, true);
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4841
  }
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4842
4843
  static long _btrfs_ioctl_set_received_subvol(struct file *file,
  					    struct btrfs_ioctl_received_subvol_args *sa)
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4844
  {
496ad9aa8   Al Viro   new helper: file_...
4845
  	struct inode *inode = file_inode(file);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4846
4847
4848
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_root_item *root_item = &root->root_item;
  	struct btrfs_trans_handle *trans;
c2050a454   Deepa Dinamani   fs: Replace curre...
4849
  	struct timespec ct = current_time(inode);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4850
  	int ret = 0;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4851
  	int received_uuid_changed;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4852

bd60ea0fe   David Sterba   btrfs: call permi...
4853
4854
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
  	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...
4870
4871
4872
4873
4874
  	/*
  	 * 1 - root item
  	 * 2 - uuid items (received uuid + subvol uuid)
  	 */
  	trans = btrfs_start_transaction(root, 3);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4875
4876
4877
4878
4879
4880
4881
4882
4883
  	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...
4884
4885
4886
4887
4888
4889
4890
4891
  	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 ...
4892
4893
4894
  	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...
4895
4896
4897
4898
  	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 ...
4899
4900
4901
4902
4903
  
  	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 ...
4904
  		goto out;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4905
4906
4907
4908
4909
4910
4911
  	}
  	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) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
4912
  			btrfs_abort_transaction(trans, ret);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4913
  			goto out;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4914
4915
4916
4917
  		}
  	}
  	ret = btrfs_commit_transaction(trans, root);
  	if (ret < 0) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
4918
  		btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4919
  		goto out;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4920
  	}
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
  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;
  	}
8d2db7855   David Sterba   btrfs: use GFP_KE...
4941
  	args64 = kmalloc(sizeof(*args64), GFP_KERNEL);
84dbeb87d   Dan Carpenter   Btrfs: kmalloc() ...
4942
4943
  	if (!args64) {
  		ret = -ENOMEM;
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
  		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 ...
4997
4998
4999
5000
5001
5002
  	ret = copy_to_user(arg, sa, sizeof(*sa));
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	kfree(sa);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
5003
5004
  	return ret;
  }
867ab667e   jeff.liu   Btrfs: Add a new ...
5005
5006
  static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg)
  {
6d0379ec4   Al Viro   btrfs: more open-...
5007
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
a1b83ac52   Anand Jain   btrfs: fix get se...
5008
  	size_t len;
867ab667e   jeff.liu   Btrfs: Add a new ...
5009
  	int ret;
a1b83ac52   Anand Jain   btrfs: fix get se...
5010
5011
5012
5013
5014
5015
5016
  	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 ...
5017
5018
  
  	if (len == BTRFS_LABEL_SIZE) {
efe120a06   Frank Holton   Btrfs: convert pr...
5019
5020
  		btrfs_warn(root->fs_info,
  			"label is too long, return the first %zu bytes", --len);
867ab667e   jeff.liu   Btrfs: Add a new ...
5021
  	}
867ab667e   jeff.liu   Btrfs: Add a new ...
5022
  	ret = copy_to_user(arg, label, len);
867ab667e   jeff.liu   Btrfs: Add a new ...
5023
5024
5025
  
  	return ret ? -EFAULT : 0;
  }
a8bfd4abe   jeff.liu   Btrfs: set/change...
5026
5027
  static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
  {
6d0379ec4   Al Viro   btrfs: more open-...
5028
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
a8bfd4abe   jeff.liu   Btrfs: set/change...
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
  	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) {
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
5041
5042
5043
  		btrfs_err(root->fs_info,
  			  "unable to set label with more than %d bytes",
  			  BTRFS_LABEL_SIZE - 1);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5044
5045
5046
5047
5048
5049
  		return -EINVAL;
  	}
  
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
a8bfd4abe   jeff.liu   Btrfs: set/change...
5050
5051
5052
5053
5054
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_unlock;
  	}
a1b83ac52   Anand Jain   btrfs: fix get se...
5055
  	spin_lock(&root->fs_info->super_lock);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5056
  	strcpy(super_block->label, label);
a1b83ac52   Anand Jain   btrfs: fix get se...
5057
  	spin_unlock(&root->fs_info->super_lock);
d0270aca8   Jeff Mahoney   btrfs: commit tra...
5058
  	ret = btrfs_commit_transaction(trans, root);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5059
5060
  
  out_unlock:
a8bfd4abe   jeff.liu   Btrfs: set/change...
5061
5062
5063
  	mnt_drop_write_file(file);
  	return ret;
  }
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5064
5065
5066
5067
  #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 }
d5131b658   David Sterba   btrfs: drop unuse...
5068
  int btrfs_ioctl_get_supported_features(void __user *arg)
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5069
  {
4d4ab6d6b   David Sterba   btrfs: constify s...
5070
  	static const struct btrfs_ioctl_feature_flags features[3] = {
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
  		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...
5097
5098
  static int check_feature_bits(struct btrfs_root *root,
  			      enum btrfs_feature_set set,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5099
5100
5101
  			      u64 change_mask, u64 flags, u64 supported_flags,
  			      u64 safe_set, u64 safe_clear)
  {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5102
5103
  	const char *type = btrfs_feature_set_names[set];
  	char *names;
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5104
5105
5106
5107
5108
5109
  	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...
5110
5111
5112
5113
5114
5115
5116
5117
  		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...
5118
5119
5120
5121
5122
5123
5124
  			   "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...
5125
5126
5127
5128
5129
5130
5131
5132
  		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...
5133
5134
5135
5136
5137
5138
5139
  			   "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...
5140
5141
5142
5143
5144
5145
5146
5147
  		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...
5148
5149
5150
5151
5152
5153
5154
5155
5156
  			   "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...
5157
  check_feature_bits(root, FEAT_##mask_base, change_mask, flags,	\
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
  		   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;
7ab19625a   David Sterba   btrfs: add write ...
5196
5197
5198
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
8051aa1a3   David Sterba   btrfs: reserve no...
5199
  	trans = btrfs_start_transaction(root, 0);
7ab19625a   David Sterba   btrfs: add write ...
5200
5201
5202
5203
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_drop_write;
  	}
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
  
  	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);
7ab19625a   David Sterba   btrfs: add write ...
5221
5222
5223
5224
5225
  	ret = btrfs_commit_transaction(trans, root);
  out_drop_write:
  	mnt_drop_write_file(file);
  
  	return ret;
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5226
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5227
5228
5229
  long btrfs_ioctl(struct file *file, unsigned int
  		cmd, unsigned long arg)
  {
496ad9aa8   Al Viro   new helper: file_...
5230
  	struct btrfs_root *root = BTRFS_I(file_inode(file))->root;
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
5231
  	void __user *argp = (void __user *)arg;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5232
5233
  
  	switch (cmd) {
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
5234
5235
5236
5237
5238
5239
  	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_...
5240
5241
  	case FITRIM:
  		return btrfs_ioctl_fitrim(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5242
  	case BTRFS_IOC_SNAP_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
5243
  		return btrfs_ioctl_snap_create(file, argp, 0);
fdfb1e4f6   Li Zefan   Btrfs: Make async...
5244
  	case BTRFS_IOC_SNAP_CREATE_V2:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
5245
  		return btrfs_ioctl_snap_create_v2(file, argp, 0);
3de4586c5   Chris Mason   Btrfs: Allow subv...
5246
  	case BTRFS_IOC_SUBVOL_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
5247
  		return btrfs_ioctl_snap_create(file, argp, 1);
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
5248
5249
  	case BTRFS_IOC_SUBVOL_CREATE_V2:
  		return btrfs_ioctl_snap_create_v2(file, argp, 1);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
5250
5251
  	case BTRFS_IOC_SNAP_DESTROY:
  		return btrfs_ioctl_snap_destroy(file, argp);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
5252
5253
5254
5255
  	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 ...
5256
5257
  	case BTRFS_IOC_DEFAULT_SUBVOL:
  		return btrfs_ioctl_default_subvol(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5258
  	case BTRFS_IOC_DEFRAG:
1e701a329   Chris Mason   Btrfs: add new de...
5259
5260
5261
  		return btrfs_ioctl_defrag(file, NULL);
  	case BTRFS_IOC_DEFRAG_RANGE:
  		return btrfs_ioctl_defrag(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5262
  	case BTRFS_IOC_RESIZE:
198605a8e   Miao Xie   Btrfs: get write ...
5263
  		return btrfs_ioctl_resize(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5264
  	case BTRFS_IOC_ADD_DEV:
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
5265
  		return btrfs_ioctl_add_dev(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5266
  	case BTRFS_IOC_RM_DEV:
da24927b1   Miao Xie   Btrfs: get write ...
5267
  		return btrfs_ioctl_rm_dev(file, argp);
6b526ed70   Anand Jain   btrfs: introduce ...
5268
5269
  	case BTRFS_IOC_RM_DEV_V2:
  		return btrfs_ioctl_rm_dev_v2(file, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
5270
5271
5272
5273
  	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 ...
5274
  	case BTRFS_IOC_BALANCE:
9ba1f6e44   Liu Bo   Btrfs: do not do ...
5275
  		return btrfs_ioctl_balance(file, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5276
5277
5278
5279
  	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...
5280
5281
  	case BTRFS_IOC_TREE_SEARCH:
  		return btrfs_ioctl_tree_search(file, argp);
cc68a8a5a   Gerhard Heift   btrfs: new ioctl ...
5282
5283
  	case BTRFS_IOC_TREE_SEARCH_V2:
  		return btrfs_ioctl_tree_search_v2(file, argp);
ac8e9819d   Chris Mason   Btrfs: add search...
5284
5285
  	case BTRFS_IOC_INO_LOOKUP:
  		return btrfs_ioctl_ino_lookup(file, argp);
d7728c960   Jan Schmidt   btrfs: new ioctls...
5286
5287
5288
5289
  	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"...
5290
5291
  	case BTRFS_IOC_SPACE_INFO:
  		return btrfs_ioctl_space_info(root, argp);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
5292
5293
  	case BTRFS_IOC_SYNC: {
  		int ret;
6c255e67c   Miao Xie   Btrfs: don't flus...
5294
  		ret = btrfs_start_delalloc_roots(root->fs_info, 0, -1);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
5295
5296
  		if (ret)
  			return ret;
ddb52f4fd   Al Viro   btrfs: get rid of...
5297
  		ret = btrfs_sync_fs(file_inode(file)->i_sb, 1);
2fad4e83e   David Sterba   btrfs: wake up tr...
5298
5299
  		/*
  		 * The transaction thread may want to do more work,
013276101   Nicholas D Steeves   btrfs: fix string...
5300
  		 * namely it pokes the cleaner kthread that will start
2fad4e83e   David Sterba   btrfs: wake up tr...
5301
5302
5303
  		 * processing uncleaned subvols.
  		 */
  		wake_up_process(root->fs_info->transaction_kthread);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
5304
5305
  		return ret;
  	}
462045928   Sage Weil   Btrfs: add START_...
5306
  	case BTRFS_IOC_START_SYNC:
9a8c28bec   Miao Xie   Btrfs: pass root ...
5307
  		return btrfs_ioctl_start_sync(root, argp);
462045928   Sage Weil   Btrfs: add START_...
5308
  	case BTRFS_IOC_WAIT_SYNC:
9a8c28bec   Miao Xie   Btrfs: pass root ...
5309
  		return btrfs_ioctl_wait_sync(root, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
5310
  	case BTRFS_IOC_SCRUB:
b8e95489b   Miao Xie   Btrfs: get write ...
5311
  		return btrfs_ioctl_scrub(file, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
5312
5313
5314
5315
  	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 ...
5316
  	case BTRFS_IOC_BALANCE_V2:
9ba1f6e44   Liu Bo   Btrfs: do not do ...
5317
  		return btrfs_ioctl_balance(file, argp);
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
5318
5319
  	case BTRFS_IOC_BALANCE_CTL:
  		return btrfs_ioctl_balance_ctl(root, arg);
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
5320
5321
  	case BTRFS_IOC_BALANCE_PROGRESS:
  		return btrfs_ioctl_balance_progress(root, argp);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
5322
5323
  	case BTRFS_IOC_SET_RECEIVED_SUBVOL:
  		return btrfs_ioctl_set_received_subvol(file, argp);
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
5324
5325
5326
5327
  #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 ...
5328
5329
  	case BTRFS_IOC_SEND:
  		return btrfs_ioctl_send(file, argp);
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
5330
  	case BTRFS_IOC_GET_DEV_STATS:
b27f7c0c1   David Sterba   btrfs: join DEV_S...
5331
  		return btrfs_ioctl_get_dev_stats(root, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5332
  	case BTRFS_IOC_QUOTA_CTL:
905b0dda0   Miao Xie   Btrfs: get write ...
5333
  		return btrfs_ioctl_quota_ctl(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5334
  	case BTRFS_IOC_QGROUP_ASSIGN:
905b0dda0   Miao Xie   Btrfs: get write ...
5335
  		return btrfs_ioctl_qgroup_assign(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5336
  	case BTRFS_IOC_QGROUP_CREATE:
905b0dda0   Miao Xie   Btrfs: get write ...
5337
  		return btrfs_ioctl_qgroup_create(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5338
  	case BTRFS_IOC_QGROUP_LIMIT:
905b0dda0   Miao Xie   Btrfs: get write ...
5339
  		return btrfs_ioctl_qgroup_limit(file, argp);
2f2320360   Jan Schmidt   Btrfs: rescan for...
5340
5341
5342
5343
  	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 ...
5344
5345
  	case BTRFS_IOC_QUOTA_RESCAN_WAIT:
  		return btrfs_ioctl_quota_rescan_wait(file, argp);
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
5346
5347
  	case BTRFS_IOC_DEV_REPLACE:
  		return btrfs_ioctl_dev_replace(root, argp);
867ab667e   jeff.liu   Btrfs: Add a new ...
5348
5349
  	case BTRFS_IOC_GET_FSLABEL:
  		return btrfs_ioctl_get_fslabel(file, argp);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5350
5351
  	case BTRFS_IOC_SET_FSLABEL:
  		return btrfs_ioctl_set_fslabel(file, argp);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5352
  	case BTRFS_IOC_GET_SUPPORTED_FEATURES:
d5131b658   David Sterba   btrfs: drop unuse...
5353
  		return btrfs_ioctl_get_supported_features(argp);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5354
5355
5356
5357
  	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 ...
5358
5359
5360
5361
  	}
  
  	return -ENOTTY;
  }
4c63c2454   Luke Dashjr   btrfs: bugfix: ha...
5362
5363
5364
5365
  
  #ifdef CONFIG_COMPAT
  long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
93fb04347   Jeff Mahoney   btrfs: fix btrfs_...
5366
5367
5368
5369
  	/*
  	 * These all access 32-bit values anyway so no further
  	 * handling is necessary.
  	 */
4c63c2454   Luke Dashjr   btrfs: bugfix: ha...
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
  	switch (cmd) {
  	case FS_IOC32_GETFLAGS:
  		cmd = FS_IOC_GETFLAGS;
  		break;
  	case FS_IOC32_SETFLAGS:
  		cmd = FS_IOC_SETFLAGS;
  		break;
  	case FS_IOC32_GETVERSION:
  		cmd = FS_IOC_GETVERSION;
  		break;
4c63c2454   Luke Dashjr   btrfs: bugfix: ha...
5380
5381
5382
5383
5384
  	}
  
  	return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
  }
  #endif