Blame view

fs/btrfs/ioctl.c 138 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
  #include <linux/swap.h>
  #include <linux/writeback.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
36
37
  #include <linux/compat.h>
  #include <linux/bit_spinlock.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
38
  #include <linux/security.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
39
  #include <linux/xattr.h>
f54de068d   David Sterba   btrfs: use GFP_KE...
40
  #include <linux/mm.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
41
  #include <linux/slab.h>
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
42
  #include <linux/blkdev.h>
8ea05e3a4   Alexander Block   Btrfs: introduce ...
43
  #include <linux/uuid.h>
55e301fd5   Filipe Brandenburger   Btrfs: move fs/bt...
44
  #include <linux/btrfs.h>
416161db9   Mark Fasheh   btrfs: offline de...
45
  #include <linux/uaccess.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
46
47
48
49
  #include "ctree.h"
  #include "disk-io.h"
  #include "transaction.h"
  #include "btrfs_inode.h"
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
50
51
  #include "print-tree.h"
  #include "volumes.h"
925baeddc   Chris Mason   Btrfs: Start btre...
52
  #include "locking.h"
581bb0509   Li Zefan   Btrfs: Cache free...
53
  #include "inode-map.h"
d7728c960   Jan Schmidt   btrfs: new ioctls...
54
  #include "backref.h"
606686eea   Josef Bacik   Btrfs: use rcu to...
55
  #include "rcu-string.h"
31db9f7c2   Alexander Block   Btrfs: introduce ...
56
  #include "send.h"
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
57
  #include "dev-replace.h"
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
58
  #include "props.h"
3b02a68a6   Jeff Mahoney   btrfs: use featur...
59
  #include "sysfs.h"
fcebe4562   Josef Bacik   Btrfs: rework qgr...
60
  #include "qgroup.h"
1ec9a1ae1   Filipe Manana   Btrfs: fix unrepl...
61
  #include "tree-log.h"
ebb8765b2   Anand Jain   btrfs: move btrfs...
62
  #include "compression.h"
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
63

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

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  /* 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...
122
123
  	if (flags & BTRFS_INODE_NODATACOW)
  		iflags |= FS_NOCOW_FL;
13f48dc90   Satoru Takeuchi   btrfs: Simplify c...
124
  	if (flags & BTRFS_INODE_NOCOMPRESS)
d0092bdda   Li Zefan   Btrfs: fix FS_IOC...
125
  		iflags |= FS_NOCOMP_FL;
13f48dc90   Satoru Takeuchi   btrfs: Simplify c...
126
127
  	else if (flags & BTRFS_INODE_COMPRESS)
  		iflags |= FS_COMPR_FL;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
128
129
130
131
132
133
134
135
136
137
  
  	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...
138
  	unsigned int new_fl = 0;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
139
140
  
  	if (ip->flags & BTRFS_INODE_SYNC)
3cc793925   Filipe Manana   Btrfs: atomically...
141
  		new_fl |= S_SYNC;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
142
  	if (ip->flags & BTRFS_INODE_IMMUTABLE)
3cc793925   Filipe Manana   Btrfs: atomically...
143
  		new_fl |= S_IMMUTABLE;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
144
  	if (ip->flags & BTRFS_INODE_APPEND)
3cc793925   Filipe Manana   Btrfs: atomically...
145
  		new_fl |= S_APPEND;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
146
  	if (ip->flags & BTRFS_INODE_NOATIME)
3cc793925   Filipe Manana   Btrfs: atomically...
147
  		new_fl |= S_NOATIME;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
148
  	if (ip->flags & BTRFS_INODE_DIRSYNC)
3cc793925   Filipe Manana   Btrfs: atomically...
149
150
151
152
153
  		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 ...
154
  }
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
155
156
  static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
157
  	struct btrfs_inode *ip = BTRFS_I(file_inode(file));
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
158
159
160
161
162
163
  	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...
164
165
166
167
168
  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
169
170
  		      FS_NOCOMP_FL | FS_COMPR_FL |
  		      FS_NOCOW_FL))
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
171
172
173
174
  		return -EOPNOTSUPP;
  
  	if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
  		return -EINVAL;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
175
176
  	return 0;
  }
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
177
178
  static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
179
  	struct inode *inode = file_inode(file);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
180
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
181
182
183
184
185
  	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...
186
187
  	u64 ip_oldflags;
  	unsigned int i_oldflags;
7e97b8daf   David Sterba   btrfs: allow sett...
188
  	umode_t mode;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
189

bd60ea0fe   David Sterba   btrfs: call permi...
190
191
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
b83cc9693   Li Zefan   Btrfs: Add readon...
192
193
  	if (btrfs_root_readonly(root))
  		return -EROFS;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
194
195
  	if (copy_from_user(&flags, arg, sizeof(flags)))
  		return -EFAULT;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
196
197
198
  	ret = check_flags(flags);
  	if (ret)
  		return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
199

e7848683a   Jan Kara   btrfs: Push mnt_w...
200
201
202
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5955102c9   Al Viro   wrappers for ->i_...
203
  	inode_lock(inode);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
204

f062abf08   Li Zefan   Btrfs: remove BUG...
205
206
  	ip_oldflags = ip->flags;
  	i_oldflags = inode->i_flags;
7e97b8daf   David Sterba   btrfs: allow sett...
207
  	mode = inode->i_mode;
f062abf08   Li Zefan   Btrfs: remove BUG...
208

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
209
210
211
212
213
214
215
216
  	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 ...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  	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...
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  	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...
256
  		 * Revert back under same assumptions as above
7e97b8daf   David Sterba   btrfs: allow sett...
257
258
259
260
261
262
263
264
265
  		 */
  		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 ...
266

75e7cb7fe   Liu Bo   Btrfs: Per file/d...
267
268
269
270
271
272
273
274
  	/*
  	 * 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...
275
276
277
278
  
  		ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0);
  		if (ret && ret != -ENODATA)
  			goto out_drop;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
279
  	} else if (flags & FS_COMPR_FL) {
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
280
  		const char *comp;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
281
282
  		ip->flags |= BTRFS_INODE_COMPRESS;
  		ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
283

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
284
  		if (fs_info->compress_type == BTRFS_COMPRESS_LZO)
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
285
  			comp = "lzo";
5c1aab1dd   Nick Terrell   btrfs: Add zstd s...
286
  		else if (fs_info->compress_type == BTRFS_COMPRESS_ZLIB)
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
287
  			comp = "zlib";
5c1aab1dd   Nick Terrell   btrfs: Add zstd s...
288
289
  		else
  			comp = "zstd";
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
290
291
292
293
  		ret = btrfs_set_prop(inode, "btrfs.compression",
  				     comp, strlen(comp), 0);
  		if (ret)
  			goto out_drop;
ebcb904df   Li Zefan   Btrfs: fix FS_IOC...
294
  	} else {
78a017a2c   Filipe Manana   Btrfs: add missin...
295
296
297
  		ret = btrfs_set_prop(inode, "btrfs.compression", NULL, 0, 0);
  		if (ret && ret != -ENODATA)
  			goto out_drop;
ebcb904df   Li Zefan   Btrfs: fix FS_IOC...
298
  		ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
299
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
300

4da6f1a33   Li Zefan   Btrfs: reserve me...
301
  	trans = btrfs_start_transaction(root, 1);
f062abf08   Li Zefan   Btrfs: remove BUG...
302
303
304
305
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_drop;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
306

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

3a45bb207   Jeff Mahoney   btrfs: remove roo...
312
  	btrfs_end_transaction(trans);
f062abf08   Li Zefan   Btrfs: remove BUG...
313
314
315
316
317
   out_drop:
  	if (ret) {
  		ip->flags = ip_oldflags;
  		inode->i_flags = i_oldflags;
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
318

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
319
   out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
320
  	inode_unlock(inode);
e7848683a   Jan Kara   btrfs: Push mnt_w...
321
  	mnt_drop_write_file(file);
2d4e6f6ad   liubo   Btrfs: fix return...
322
  	return ret;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
323
324
325
326
  }
  
  static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
327
  	struct inode *inode = file_inode(file);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
328
329
330
  
  	return put_user(inode->i_generation, arg);
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
331

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
332
333
  static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
334
335
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
336
337
338
339
340
341
342
343
344
  	struct btrfs_device *device;
  	struct request_queue *q;
  	struct fstrim_range range;
  	u64 minlen = ULLONG_MAX;
  	u64 num_devices = 0;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
1f78160ce   Xiao Guangrong   Btrfs: using rcu ...
345
346
347
  	rcu_read_lock();
  	list_for_each_entry_rcu(device, &fs_info->fs_devices->devices,
  				dev_list) {
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
348
349
350
351
352
  		if (!device->bdev)
  			continue;
  		q = bdev_get_queue(device->bdev);
  		if (blk_queue_discard(q)) {
  			num_devices++;
50d0446e6   Seraphime Kirkovski   Btrfs: code clean...
353
  			minlen = min_t(u64, q->limits.discard_granularity,
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
354
355
356
  				     minlen);
  		}
  	}
1f78160ce   Xiao Guangrong   Btrfs: using rcu ...
357
  	rcu_read_unlock();
f4c697e64   Lukas Czerner   btrfs: return EIN...
358

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
359
360
  	if (!num_devices)
  		return -EOPNOTSUPP;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
361
362
  	if (copy_from_user(&range, arg, sizeof(range)))
  		return -EFAULT;
2fdb337b6   Qu Wenruo   btrfs: Ensure btr...
363
364
365
366
367
368
369
  
  	/*
  	 * NOTE: Don't truncate the range using super->total_bytes.  Bytenr of
  	 * block group is in the logical address space, which can be any
  	 * sectorsize aligned bytenr in  the range [0, U64_MAX].
  	 */
  	if (range.len < fs_info->sb->s_blocksize)
f4c697e64   Lukas Czerner   btrfs: return EIN...
370
  		return -EINVAL;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
371
372
  
  	range.minlen = max(range.minlen, minlen);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
373
  	ret = btrfs_trim_fs(fs_info, &range);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
374
375
376
377
378
379
380
381
  	if (ret < 0)
  		return ret;
  
  	if (copy_to_user(arg, &range, sizeof(range)))
  		return -EFAULT;
  
  	return 0;
  }
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
382
383
  int btrfs_is_empty_uuid(u8 *uuid)
  {
46e0f66a0   Chris Mason   btrfs: fix empty_...
384
385
386
387
388
389
390
  	int i;
  
  	for (i = 0; i < BTRFS_UUID_SIZE; i++) {
  		if (uuid[i])
  			return 0;
  	}
  	return 1;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
391
  }
d5c120701   Miao Xie   Btrfs: fix wrong ...
392
  static noinline int create_subvol(struct inode *dir,
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
393
  				  struct dentry *dentry,
52f75f4fe   David Sterba   btrfs: constify n...
394
  				  const char *name, int namelen,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
395
  				  u64 *async_transid,
8696c5330   Miao Xie   Btrfs: fix memory...
396
  				  struct btrfs_qgroup_inherit *inherit)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
397
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
398
  	struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
399
400
  	struct btrfs_trans_handle *trans;
  	struct btrfs_key key;
49a3c4d9b   David Sterba   btrfs: use dynami...
401
  	struct btrfs_root_item *root_item;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
402
403
  	struct btrfs_inode_item *inode_item;
  	struct extent_buffer *leaf;
d5c120701   Miao Xie   Btrfs: fix wrong ...
404
  	struct btrfs_root *root = BTRFS_I(dir)->root;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
405
  	struct btrfs_root *new_root;
d5c120701   Miao Xie   Btrfs: fix wrong ...
406
  	struct btrfs_block_rsv block_rsv;
c2050a454   Deepa Dinamani   fs: Replace curre...
407
  	struct timespec cur_time = current_time(dir);
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
408
  	struct inode *inode;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
409
410
411
412
  	int ret;
  	int err;
  	u64 objectid;
  	u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
3de4586c5   Chris Mason   Btrfs: Allow subv...
413
  	u64 index = 0;
d5c120701   Miao Xie   Btrfs: fix wrong ...
414
  	u64 qgroup_reserved;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
415
  	uuid_le new_uuid;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
416

49a3c4d9b   David Sterba   btrfs: use dynami...
417
418
419
  	root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
  	if (!root_item)
  		return -ENOMEM;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
420
  	ret = btrfs_find_free_objectid(fs_info->tree_root, &objectid);
2fbe8c8ad   Al Viro   get rid of useles...
421
  	if (ret)
49a3c4d9b   David Sterba   btrfs: use dynami...
422
  		goto fail_free;
6a9122130   Josef Bacik   Btrfs: use dget_p...
423

e09fe2d21   Qu Wenruo   btrfs: Don't allo...
424
425
  	/*
  	 * Don't create subvolume whose level is not zero. Or qgroup will be
013276101   Nicholas D Steeves   btrfs: fix string...
426
  	 * screwed up since it assumes subvolume qgroup's level to be 0.
e09fe2d21   Qu Wenruo   btrfs: Don't allo...
427
  	 */
49a3c4d9b   David Sterba   btrfs: use dynami...
428
429
430
431
  	if (btrfs_qgroup_level(objectid)) {
  		ret = -ENOSPC;
  		goto fail_free;
  	}
e09fe2d21   Qu Wenruo   btrfs: Don't allo...
432

d5c120701   Miao Xie   Btrfs: fix wrong ...
433
  	btrfs_init_block_rsv(&block_rsv, BTRFS_BLOCK_RSV_TEMP);
9ed74f2db   Josef Bacik   Btrfs: proper -EN...
434
  	/*
d5c120701   Miao Xie   Btrfs: fix wrong ...
435
436
  	 * The same as the snapshot creation, please see the comment
  	 * of create_snapshot().
9ed74f2db   Josef Bacik   Btrfs: proper -EN...
437
  	 */
d5c120701   Miao Xie   Btrfs: fix wrong ...
438
  	ret = btrfs_subvolume_reserve_metadata(root, &block_rsv,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
439
  					       8, &qgroup_reserved, false);
d5c120701   Miao Xie   Btrfs: fix wrong ...
440
  	if (ret)
49a3c4d9b   David Sterba   btrfs: use dynami...
441
  		goto fail_free;
d5c120701   Miao Xie   Btrfs: fix wrong ...
442
443
444
445
  
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
7775c8184   David Sterba   btrfs: remove unu...
446
  		btrfs_subvolume_release_metadata(fs_info, &block_rsv);
49a3c4d9b   David Sterba   btrfs: use dynami...
447
  		goto fail_free;
d5c120701   Miao Xie   Btrfs: fix wrong ...
448
449
450
  	}
  	trans->block_rsv = &block_rsv;
  	trans->bytes_reserved = block_rsv.size;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
451

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
452
  	ret = btrfs_qgroup_inherit(trans, fs_info, 0, objectid, inherit);
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
453
454
  	if (ret)
  		goto fail;
4d75f8a9c   David Sterba   btrfs: remove blo...
455
  	leaf = btrfs_alloc_tree_block(trans, root, 0, objectid, NULL, 0, 0, 0);
8e8a1e31f   Josef Bacik   Btrfs: Fix a few ...
456
457
458
459
  	if (IS_ERR(leaf)) {
  		ret = PTR_ERR(leaf);
  		goto fail;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
460

b159fa280   David Sterba   btrfs: remove con...
461
  	memzero_extent_buffer(leaf, 0, sizeof(struct btrfs_header));
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
462
463
  	btrfs_set_header_bytenr(leaf, leaf->start);
  	btrfs_set_header_generation(leaf, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
464
  	btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
465
  	btrfs_set_header_owner(leaf, objectid);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
466
467
  	write_extent_buffer_fsid(leaf, fs_info->fsid);
  	write_extent_buffer_chunk_tree_uuid(leaf, fs_info->chunk_tree_uuid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
468
  	btrfs_mark_buffer_dirty(leaf);
49a3c4d9b   David Sterba   btrfs: use dynami...
469
  	inode_item = &root_item->inode;
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
470
471
472
  	btrfs_set_stack_inode_generation(inode_item, 1);
  	btrfs_set_stack_inode_size(inode_item, 3);
  	btrfs_set_stack_inode_nlink(inode_item, 1);
da17066c4   Jeff Mahoney   btrfs: pull node/...
473
  	btrfs_set_stack_inode_nbytes(inode_item,
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
474
  				     fs_info->nodesize);
3cae210fa   Qu Wenruo   btrfs: Cleanup fo...
475
  	btrfs_set_stack_inode_mode(inode_item, S_IFDIR | 0755);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
476

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

49a3c4d9b   David Sterba   btrfs: use dynami...
481
482
483
484
485
486
  	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 ...
487

49a3c4d9b   David Sterba   btrfs: use dynami...
488
489
  	btrfs_set_root_generation_v2(root_item,
  			btrfs_root_generation(root_item));
8ea05e3a4   Alexander Block   Btrfs: introduce ...
490
  	uuid_le_gen(&new_uuid);
49a3c4d9b   David Sterba   btrfs: use dynami...
491
492
493
494
495
496
  	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 ...
497

925baeddc   Chris Mason   Btrfs: Start btre...
498
  	btrfs_tree_unlock(leaf);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
499
500
  	free_extent_buffer(leaf);
  	leaf = NULL;
49a3c4d9b   David Sterba   btrfs: use dynami...
501
  	btrfs_set_root_dirid(root_item, new_dirid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
502
503
  
  	key.objectid = objectid;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
504
  	key.offset = 0;
962a298f3   David Sterba   btrfs: kill the k...
505
  	key.type = BTRFS_ROOT_ITEM_KEY;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
506
  	ret = btrfs_insert_root(trans, fs_info->tree_root, &key,
49a3c4d9b   David Sterba   btrfs: use dynami...
507
  				root_item);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
508
509
  	if (ret)
  		goto fail;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
510
  	key.offset = (u64)-1;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
511
  	new_root = btrfs_read_fs_root_no_name(fs_info, &key);
79787eaab   Jeff Mahoney   btrfs: replace ma...
512
  	if (IS_ERR(new_root)) {
79787eaab   Jeff Mahoney   btrfs: replace ma...
513
  		ret = PTR_ERR(new_root);
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
514
  		btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
515
516
  		goto fail;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
517
518
  
  	btrfs_record_root_in_trans(trans, new_root);
63541927c   Filipe David Borba Manana   Btrfs: add suppor...
519
  	ret = btrfs_create_subvol_root(trans, new_root, root, new_dirid);
ce598979b   Mark Fasheh   btrfs: Don't BUG_...
520
521
  	if (ret) {
  		/* We potentially lose an unused inode item here */
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
522
  		btrfs_abort_transaction(trans, ret);
ce598979b   Mark Fasheh   btrfs: Don't BUG_...
523
524
  		goto fail;
  	}
f32e48e92   Chandan Rajendra   Btrfs: Initialize...
525
526
527
  	mutex_lock(&new_root->objectid_mutex);
  	new_root->highest_objectid = new_dirid;
  	mutex_unlock(&new_root->objectid_mutex);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
528
529
530
  	/*
  	 * insert the directory item
  	 */
877574e25   Nikolay Borisov   btrfs: Make btrfs...
531
  	ret = btrfs_set_inode_index(BTRFS_I(dir), &index);
79787eaab   Jeff Mahoney   btrfs: replace ma...
532
  	if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
533
  		btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
534
535
  		goto fail;
  	}
3de4586c5   Chris Mason   Btrfs: Allow subv...
536
537
  
  	ret = btrfs_insert_dir_item(trans, root,
8e7611cf3   Nikolay Borisov   btrfs: Make btrfs...
538
  				    name, namelen, BTRFS_I(dir), &key,
3de4586c5   Chris Mason   Btrfs: Allow subv...
539
  				    BTRFS_FT_DIR, index);
79787eaab   Jeff Mahoney   btrfs: replace ma...
540
  	if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
541
  		btrfs_abort_transaction(trans, ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
542
  		goto fail;
79787eaab   Jeff Mahoney   btrfs: replace ma...
543
  	}
0660b5af3   Chris Mason   Btrfs: Add backre...
544

6ef06d279   Nikolay Borisov   btrfs: Make btrfs...
545
  	btrfs_i_size_write(BTRFS_I(dir), dir->i_size + namelen * 2);
52c261799   Yan Zheng   Btrfs: update dir...
546
547
  	ret = btrfs_update_inode(trans, root, dir);
  	BUG_ON(ret);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
548
  	ret = btrfs_add_root_ref(trans, fs_info,
4df27c4d5   Yan, Zheng   Btrfs: change how...
549
  				 objectid, root->root_key.objectid,
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
550
  				 btrfs_ino(BTRFS_I(dir)), index, name, namelen);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
551
  	BUG_ON(ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
552

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
553
  	ret = btrfs_uuid_tree_add(trans, fs_info, root_item->uuid,
6bccf3ab1   Jeff Mahoney   btrfs: call funct...
554
  				  BTRFS_UUID_KEY_SUBVOL, objectid);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
555
  	if (ret)
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
556
  		btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
557

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
558
  fail:
49a3c4d9b   David Sterba   btrfs: use dynami...
559
  	kfree(root_item);
d5c120701   Miao Xie   Btrfs: fix wrong ...
560
561
  	trans->block_rsv = NULL;
  	trans->bytes_reserved = 0;
7775c8184   David Sterba   btrfs: remove unu...
562
  	btrfs_subvolume_release_metadata(fs_info, &block_rsv);
de6e82006   Liu Bo   Btrfs: release su...
563

72fd032e9   Sage Weil   Btrfs: add SNAP_C...
564
565
  	if (async_transid) {
  		*async_transid = trans->transid;
3a45bb207   Jeff Mahoney   btrfs: remove roo...
566
  		err = btrfs_commit_transaction_async(trans, 1);
00d71c9c1   Miao Xie   Btrfs: fix unclos...
567
  		if (err)
3a45bb207   Jeff Mahoney   btrfs: remove roo...
568
  			err = btrfs_commit_transaction(trans);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
569
  	} else {
3a45bb207   Jeff Mahoney   btrfs: remove roo...
570
  		err = btrfs_commit_transaction(trans);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
571
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
572
573
  	if (err && !ret)
  		ret = err;
1a65e24b0   Chris Mason   Btrfs: move d_ins...
574

5662344b3   Tsutomu Itoh   Btrfs: fix error ...
575
576
  	if (!ret) {
  		inode = btrfs_lookup_dentry(dir, dentry);
de6e82006   Liu Bo   Btrfs: release su...
577
578
  		if (IS_ERR(inode))
  			return PTR_ERR(inode);
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
579
580
  		d_instantiate(dentry, inode);
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
581
  	return ret;
49a3c4d9b   David Sterba   btrfs: use dynami...
582
583
584
585
  
  fail_free:
  	kfree(root_item);
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
586
  }
ea14b57fd   David Sterba   btrfs: fix spelli...
587
  static void btrfs_wait_for_no_snapshotting_writes(struct btrfs_root *root)
8257b2dc3   Miao Xie   Btrfs: introduce ...
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
  {
  	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...
603
  static int create_snapshot(struct btrfs_root *root, struct inode *dir,
61d7e4cb1   David Sterba   btrfs: remove unu...
604
  			   struct dentry *dentry,
e9662f701   Miao Xie   Btrfs: remove unn...
605
606
  			   u64 *async_transid, bool readonly,
  			   struct btrfs_qgroup_inherit *inherit)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
607
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
608
  	struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
609
  	struct inode *inode;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
610
611
  	struct btrfs_pending_snapshot *pending_snapshot;
  	struct btrfs_trans_handle *trans;
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
612
  	int ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
613

27cdeb709   Miao Xie   Btrfs: use bitfie...
614
  	if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state))
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
615
  		return -EINVAL;
23269bf5e   David Sterba   btrfs: use GFP_KE...
616
  	pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_KERNEL);
a1ee73626   David Sterba   btrfs: do an allo...
617
618
  	if (!pending_snapshot)
  		return -ENOMEM;
b0c0ea633   David Sterba   btrfs: allocate r...
619
  	pending_snapshot->root_item = kzalloc(sizeof(struct btrfs_root_item),
23269bf5e   David Sterba   btrfs: use GFP_KE...
620
  			GFP_KERNEL);
8546b5705   David Sterba   btrfs: preallocat...
621
622
  	pending_snapshot->path = btrfs_alloc_path();
  	if (!pending_snapshot->root_item || !pending_snapshot->path) {
b0c0ea633   David Sterba   btrfs: allocate r...
623
624
625
  		ret = -ENOMEM;
  		goto free_pending;
  	}
ea14b57fd   David Sterba   btrfs: fix spelli...
626
  	atomic_inc(&root->will_be_snapshotted);
4e857c58e   Peter Zijlstra   arch: Mass conver...
627
  	smp_mb__after_atomic();
ea14b57fd   David Sterba   btrfs: fix spelli...
628
  	btrfs_wait_for_no_snapshotting_writes(root);
8257b2dc3   Miao Xie   Btrfs: introduce ...
629

6a03843df   Miao Xie   Btrfs: just flush...
630
631
  	ret = btrfs_start_delalloc_inodes(root, 0);
  	if (ret)
a1ee73626   David Sterba   btrfs: do an allo...
632
  		goto dec_and_free;
6a03843df   Miao Xie   Btrfs: just flush...
633

6374e57ad   Chris Mason   btrfs: fix intege...
634
  	btrfs_wait_ordered_extents(root, U64_MAX, 0, (u64)-1);
6a03843df   Miao Xie   Btrfs: just flush...
635

66d8f3dd1   Miao Xie   Btrfs: add a new ...
636
637
  	btrfs_init_block_rsv(&pending_snapshot->block_rsv,
  			     BTRFS_BLOCK_RSV_TEMP);
d5c120701   Miao Xie   Btrfs: fix wrong ...
638
639
640
641
642
643
  	/*
  	 * 1 - parent dir inode
  	 * 2 - dir entries
  	 * 1 - root item
  	 * 2 - root ref/backref
  	 * 1 - root of snapshot
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
644
  	 * 1 - UUID item
d5c120701   Miao Xie   Btrfs: fix wrong ...
645
646
  	 */
  	ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
647
  					&pending_snapshot->block_rsv, 8,
ee3441b49   Jeff Mahoney   btrfs: fall back ...
648
649
  					&pending_snapshot->qgroup_reserved,
  					false);
d5c120701   Miao Xie   Btrfs: fix wrong ...
650
  	if (ret)
a1ee73626   David Sterba   btrfs: do an allo...
651
  		goto dec_and_free;
d5c120701   Miao Xie   Btrfs: fix wrong ...
652

3de4586c5   Chris Mason   Btrfs: Allow subv...
653
  	pending_snapshot->dentry = dentry;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
654
  	pending_snapshot->root = root;
b83cc9693   Li Zefan   Btrfs: Add readon...
655
  	pending_snapshot->readonly = readonly;
e9662f701   Miao Xie   Btrfs: remove unn...
656
  	pending_snapshot->dir = dir;
8696c5330   Miao Xie   Btrfs: fix memory...
657
  	pending_snapshot->inherit = inherit;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
658

d5c120701   Miao Xie   Btrfs: fix wrong ...
659
  	trans = btrfs_start_transaction(root, 0);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
660
661
662
663
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto fail;
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
664
  	spin_lock(&fs_info->trans_lock);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
665
666
  	list_add(&pending_snapshot->list,
  		 &trans->transaction->pending_snapshots);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
667
  	spin_unlock(&fs_info->trans_lock);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
668
669
  	if (async_transid) {
  		*async_transid = trans->transid;
3a45bb207   Jeff Mahoney   btrfs: remove roo...
670
  		ret = btrfs_commit_transaction_async(trans, 1);
00d71c9c1   Miao Xie   Btrfs: fix unclos...
671
  		if (ret)
3a45bb207   Jeff Mahoney   btrfs: remove roo...
672
  			ret = btrfs_commit_transaction(trans);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
673
  	} else {
3a45bb207   Jeff Mahoney   btrfs: remove roo...
674
  		ret = btrfs_commit_transaction(trans);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
675
  	}
aec8030a8   Miao Xie   Btrfs: fix wrong ...
676
  	if (ret)
c37b2b626   Josef Bacik   Btrfs: do not bug...
677
  		goto fail;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
678
679
680
681
  
  	ret = pending_snapshot->error;
  	if (ret)
  		goto fail;
d37973082   Chris Mason   Revert "Btrfs: ra...
682
683
684
  	ret = btrfs_orphan_cleanup(pending_snapshot->snap);
  	if (ret)
  		goto fail;
2b0143b5c   David Howells   VFS: normal files...
685
  	inode = btrfs_lookup_dentry(d_inode(dentry->d_parent), dentry);
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
686
687
688
689
  	if (IS_ERR(inode)) {
  		ret = PTR_ERR(inode);
  		goto fail;
  	}
5662344b3   Tsutomu Itoh   Btrfs: fix error ...
690

2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
691
692
693
  	d_instantiate(dentry, inode);
  	ret = 0;
  fail:
7775c8184   David Sterba   btrfs: remove unu...
694
  	btrfs_subvolume_release_metadata(fs_info, &pending_snapshot->block_rsv);
a1ee73626   David Sterba   btrfs: do an allo...
695
  dec_and_free:
ea14b57fd   David Sterba   btrfs: fix spelli...
696
697
  	if (atomic_dec_and_test(&root->will_be_snapshotted))
  		wake_up_atomic_t(&root->will_be_snapshotted);
b0c0ea633   David Sterba   btrfs: allocate r...
698
699
  free_pending:
  	kfree(pending_snapshot->root_item);
8546b5705   David Sterba   btrfs: preallocat...
700
  	btrfs_free_path(pending_snapshot->path);
a1ee73626   David Sterba   btrfs: do an allo...
701
  	kfree(pending_snapshot);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
702
703
  	return ret;
  }
4260f7c75   Sage Weil   Btrfs: allow subv...
704
705
706
707
708
709
710
711
712
713
714
  /*  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...
715
   *  6. If the victim is append-only or immutable we can't do anything with
4260f7c75   Sage Weil   Btrfs: allow subv...
716
717
718
719
720
721
722
   *     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...
723
  static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
4260f7c75   Sage Weil   Btrfs: allow subv...
724
725
  {
  	int error;
2b0143b5c   David Howells   VFS: normal files...
726
  	if (d_really_is_negative(victim))
4260f7c75   Sage Weil   Btrfs: allow subv...
727
  		return -ENOENT;
2b0143b5c   David Howells   VFS: normal files...
728
  	BUG_ON(d_inode(victim->d_parent) != dir);
4fa6b5ecb   Jeff Layton   audit: overhaul _...
729
  	audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
4260f7c75   Sage Weil   Btrfs: allow subv...
730
731
732
733
734
735
  
  	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
  	if (error)
  		return error;
  	if (IS_APPEND(dir))
  		return -EPERM;
2b0143b5c   David Howells   VFS: normal files...
736
737
  	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...
738
739
  		return -EPERM;
  	if (isdir) {
e36cb0b89   David Howells   VFS: (Scripted) C...
740
  		if (!d_is_dir(victim))
4260f7c75   Sage Weil   Btrfs: allow subv...
741
742
743
  			return -ENOTDIR;
  		if (IS_ROOT(victim))
  			return -EBUSY;
e36cb0b89   David Howells   VFS: (Scripted) C...
744
  	} else if (d_is_dir(victim))
4260f7c75   Sage Weil   Btrfs: allow subv...
745
746
747
748
749
750
751
  		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...
752
753
754
  /* 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...
755
  	if (d_really_is_positive(child))
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
756
757
758
759
760
761
762
763
764
765
766
  		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.
   */
92872094a   Al Viro   constify btrfs_mk...
767
  static noinline int btrfs_mksubvol(const struct path *parent,
52f75f4fe   David Sterba   btrfs: constify n...
768
  				   const char *name, int namelen,
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
769
  				   struct btrfs_root *snap_src,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
770
  				   u64 *async_transid, bool readonly,
8696c5330   Miao Xie   Btrfs: fix memory...
771
  				   struct btrfs_qgroup_inherit *inherit)
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
772
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
773
774
  	struct inode *dir = d_inode(parent->dentry);
  	struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
775
776
  	struct dentry *dentry;
  	int error;
002354112   Al Viro   restore killabili...
777
778
779
  	error = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
  	if (error == -EINTR)
  		return error;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
780
781
782
783
784
  
  	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...
785
  	error = btrfs_may_create(dir, dentry);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
786
  	if (error)
a874a63e1   Liu Bo   Btrfs: check writ...
787
  		goto out_dput;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
788

9c52057c6   Chris Mason   Btrfs: fix hash o...
789
790
791
792
793
794
795
796
797
  	/*
  	 * 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;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
798
  	down_read(&fs_info->subvol_sem);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
799
800
801
  
  	if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0)
  		goto out_up_read;
3de4586c5   Chris Mason   Btrfs: Allow subv...
802
  	if (snap_src) {
61d7e4cb1   David Sterba   btrfs: remove unu...
803
  		error = create_snapshot(snap_src, dir, dentry,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
804
  					async_transid, readonly, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
805
  	} else {
d5c120701   Miao Xie   Btrfs: fix wrong ...
806
807
  		error = create_subvol(dir, dentry, name, namelen,
  				      async_transid, inherit);
3de4586c5   Chris Mason   Btrfs: Allow subv...
808
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
809
810
811
  	if (!error)
  		fsnotify_mkdir(dir, dentry);
  out_up_read:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
812
  	up_read(&fs_info->subvol_sem);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
813
814
815
  out_dput:
  	dput(dentry);
  out_unlock:
5955102c9   Al Viro   wrappers for ->i_...
816
  	inode_unlock(dir);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
817
818
  	return error;
  }
4cb5300bc   Chris Mason   Btrfs: add mount ...
819
820
821
822
823
824
825
  /*
   * 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...
826
  static int check_defrag_in_cache(struct inode *inode, u64 offset, u32 thresh)
4cb5300bc   Chris Mason   Btrfs: add mount ...
827
828
829
830
831
832
833
  {
  	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...
834
  	em = lookup_extent_mapping(em_tree, offset, PAGE_SIZE);
4cb5300bc   Chris Mason   Btrfs: add mount ...
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
  	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...
861
  			    u64 *off, u32 thresh)
4cb5300bc   Chris Mason   Btrfs: add mount ...
862
863
864
  {
  	struct btrfs_path *path;
  	struct btrfs_key min_key;
4cb5300bc   Chris Mason   Btrfs: add mount ...
865
866
867
868
  	struct extent_buffer *leaf;
  	struct btrfs_file_extent_item *extent;
  	int type;
  	int ret;
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
869
  	u64 ino = btrfs_ino(BTRFS_I(inode));
4cb5300bc   Chris Mason   Btrfs: add mount ...
870
871
872
873
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
a4689d2bd   David Sterba   btrfs: use btrfs_...
874
  	min_key.objectid = ino;
4cb5300bc   Chris Mason   Btrfs: add mount ...
875
876
  	min_key.type = BTRFS_EXTENT_DATA_KEY;
  	min_key.offset = *off;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
877
  	while (1) {
6174d3cb4   Filipe David Borba Manana   Btrfs: remove unu...
878
  		ret = btrfs_search_forward(root, &min_key, path, newer_than);
4cb5300bc   Chris Mason   Btrfs: add mount ...
879
880
  		if (ret != 0)
  			goto none;
f094c9bd3   Filipe Manana   Btrfs: less fs tr...
881
  process_slot:
a4689d2bd   David Sterba   btrfs: use btrfs_...
882
  		if (min_key.objectid != ino)
4cb5300bc   Chris Mason   Btrfs: add mount ...
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
  			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...
899
900
901
902
903
  		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 ...
904
905
906
907
908
909
910
911
912
913
  		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...
914
  static struct extent_map *defrag_lookup_extent(struct inode *inode, u64 start)
17ce6ef8d   Liu Bo   Btrfs: add a chec...
915
916
  {
  	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
6c282eb40   Li Zefan   Btrfs: fix defrag...
917
918
  	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
  	struct extent_map *em;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
919
  	u64 len = PAGE_SIZE;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
920

6c282eb40   Li Zefan   Btrfs: fix defrag...
921
922
923
924
  	/*
  	 * hopefully we have this extent in the tree already, try without
  	 * the full extent lock
  	 */
17ce6ef8d   Liu Bo   Btrfs: add a chec...
925
  	read_lock(&em_tree->lock);
6c282eb40   Li Zefan   Btrfs: fix defrag...
926
  	em = lookup_extent_mapping(em_tree, start, len);
17ce6ef8d   Liu Bo   Btrfs: add a chec...
927
  	read_unlock(&em_tree->lock);
6c282eb40   Li Zefan   Btrfs: fix defrag...
928
  	if (!em) {
308d9800b   Filipe Manana   Btrfs: cache exte...
929
930
  		struct extent_state *cached = NULL;
  		u64 end = start + len - 1;
6c282eb40   Li Zefan   Btrfs: fix defrag...
931
  		/* get the big lock and read metadata off disk */
ff13db41f   David Sterba   btrfs: drop unuse...
932
  		lock_extent_bits(io_tree, start, end, &cached);
fc4f21b1d   Nikolay Borisov   btrfs: Make get_e...
933
  		em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, start, len, 0);
308d9800b   Filipe Manana   Btrfs: cache exte...
934
  		unlock_extent_cached(io_tree, start, end, &cached, GFP_NOFS);
6c282eb40   Li Zefan   Btrfs: fix defrag...
935
936
937
938
939
940
941
  
  		if (IS_ERR(em))
  			return NULL;
  	}
  
  	return em;
  }
17ce6ef8d   Liu Bo   Btrfs: add a chec...
942

6c282eb40   Li Zefan   Btrfs: fix defrag...
943
944
945
946
947
948
949
950
951
952
  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...
953
954
955
  	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/...
956
  		 (em->block_len > SZ_128K && next->block_len > SZ_128K))
6c282eb40   Li Zefan   Btrfs: fix defrag...
957
958
959
  		ret = false;
  
  	free_extent_map(next);
17ce6ef8d   Liu Bo   Btrfs: add a chec...
960
961
  	return ret;
  }
aab110abc   David Sterba   btrfs: defrag, us...
962
  static int should_defrag_range(struct inode *inode, u64 start, u32 thresh,
a43a21113   Andrew Mahone   btrfs: ignore unf...
963
964
  			       u64 *last_len, u64 *skip, u64 *defrag_end,
  			       int compress)
940100a4a   Chris Mason   Btrfs: be more se...
965
  {
6c282eb40   Li Zefan   Btrfs: fix defrag...
966
  	struct extent_map *em;
940100a4a   Chris Mason   Btrfs: be more se...
967
  	int ret = 1;
6c282eb40   Li Zefan   Btrfs: fix defrag...
968
  	bool next_mergeable = true;
4a3560c4f   Liu Bo   Btrfs: fix defrag...
969
  	bool prev_mergeable = true;
940100a4a   Chris Mason   Btrfs: be more se...
970
971
  
  	/*
008873eaf   Li Zefan   Btrfs: honor exte...
972
  	 * make sure that once we start defragging an extent, we keep on
940100a4a   Chris Mason   Btrfs: be more se...
973
974
975
976
977
978
  	 * defragging it
  	 */
  	if (start < *defrag_end)
  		return 1;
  
  	*skip = 0;
6c282eb40   Li Zefan   Btrfs: fix defrag...
979
980
981
  	em = defrag_lookup_extent(inode, start);
  	if (!em)
  		return 0;
940100a4a   Chris Mason   Btrfs: be more se...
982
983
  
  	/* this will cover holes, and inline extents */
17ce6ef8d   Liu Bo   Btrfs: add a chec...
984
  	if (em->block_start >= EXTENT_MAP_LAST_BYTE) {
940100a4a   Chris Mason   Btrfs: be more se...
985
  		ret = 0;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
986
987
  		goto out;
  	}
4a3560c4f   Liu Bo   Btrfs: fix defrag...
988
989
  	if (!*defrag_end)
  		prev_mergeable = false;
6c282eb40   Li Zefan   Btrfs: fix defrag...
990
  	next_mergeable = defrag_check_next_extent(inode, em);
940100a4a   Chris Mason   Btrfs: be more se...
991
  	/*
6c282eb40   Li Zefan   Btrfs: fix defrag...
992
993
  	 * 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...
994
  	 */
a43a21113   Andrew Mahone   btrfs: ignore unf...
995
  	if (!compress && (*last_len == 0 || *last_len >= thresh) &&
4a3560c4f   Liu Bo   Btrfs: fix defrag...
996
  	    (em->len >= thresh || (!next_mergeable && !prev_mergeable)))
940100a4a   Chris Mason   Btrfs: be more se...
997
  		ret = 0;
17ce6ef8d   Liu Bo   Btrfs: add a chec...
998
  out:
940100a4a   Chris Mason   Btrfs: be more se...
999
1000
1001
1002
1003
1004
1005
1006
1007
  	/*
  	 * 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...
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  		*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 ...
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
  /*
   * 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...
1033
  				    unsigned long num_pages)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1034
  {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1035
1036
1037
1038
  	unsigned long file_end;
  	u64 isize = i_size_read(inode);
  	u64 page_start;
  	u64 page_end;
1f12bd063   Liu Bo   Btrfs: fix the mi...
1039
  	u64 page_cnt;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1040
1041
1042
  	int ret;
  	int i;
  	int i_done;
3eaa28852   Chris Mason   Btrfs: Fix the de...
1043
  	struct btrfs_ordered_extent *ordered;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1044
  	struct extent_state *cached_state = NULL;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1045
  	struct extent_io_tree *tree;
364ecf365   Qu Wenruo   btrfs: qgroup: In...
1046
  	struct extent_changeset *data_reserved = NULL;
3b16a4e3c   Josef Bacik   Btrfs: use the in...
1047
  	gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1048

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1049
  	file_end = (isize - 1) >> PAGE_SHIFT;
1f12bd063   Liu Bo   Btrfs: fix the mi...
1050
1051
1052
1053
  	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 ...
1054

364ecf365   Qu Wenruo   btrfs: qgroup: In...
1055
  	ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1056
1057
  			start_index << PAGE_SHIFT,
  			page_cnt << PAGE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1058
1059
  	if (ret)
  		return ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1060
  	i_done = 0;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1061
  	tree = &BTRFS_I(inode)->io_tree;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1062
1063
  
  	/* step one, lock all the pages */
1f12bd063   Liu Bo   Btrfs: fix the mi...
1064
  	for (i = 0; i < page_cnt; i++) {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1065
  		struct page *page;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1066
  again:
a94733d0b   Josef Bacik   Btrfs: use find_o...
1067
  		page = find_or_create_page(inode->i_mapping,
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1068
  					   start_index + i, mask);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1069
1070
  		if (!page)
  			break;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1071
  		page_start = page_offset(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1072
  		page_end = page_start + PAGE_SIZE - 1;
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1073
  		while (1) {
308d9800b   Filipe Manana   Btrfs: cache exte...
1074
  			lock_extent_bits(tree, page_start, page_end,
ff13db41f   David Sterba   btrfs: drop unuse...
1075
  					 &cached_state);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1076
1077
  			ordered = btrfs_lookup_ordered_extent(inode,
  							      page_start);
308d9800b   Filipe Manana   Btrfs: cache exte...
1078
1079
  			unlock_extent_cached(tree, page_start, page_end,
  					     &cached_state, GFP_NOFS);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1080
1081
1082
1083
1084
1085
1086
  			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...
1087
1088
1089
1090
1091
1092
  			/*
  			 * 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...
1093
  				put_page(page);
1f12bd063   Liu Bo   Btrfs: fix the mi...
1094
1095
  				goto again;
  			}
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1096
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1097
1098
1099
1100
1101
  		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...
1102
  				put_page(page);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1103
1104
1105
1106
  				ret = -EIO;
  				break;
  			}
  		}
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1107

600a45e1d   Miao Xie   Btrfs: fix deadlo...
1108
1109
  		if (page->mapping != inode->i_mapping) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1110
  			put_page(page);
600a45e1d   Miao Xie   Btrfs: fix deadlo...
1111
1112
  			goto again;
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
  		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...
1130
  	page_end = page_offset(pages[i_done - 1]) + PAGE_SIZE;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1131
1132
  
  	lock_extent_bits(&BTRFS_I(inode)->io_tree,
ff13db41f   David Sterba   btrfs: drop unuse...
1133
  			 page_start, page_end - 1, &cached_state);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1134
1135
  	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
  			  page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
9e8a4a8b0   Liu Bo   Btrfs: use flag E...
1136
1137
  			  EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 0, 0,
  			  &cached_state, GFP_NOFS);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1138

1f12bd063   Liu Bo   Btrfs: fix the mi...
1139
  	if (i_done != page_cnt) {
9e0baf60d   Josef Bacik   Btrfs: fix enospc...
1140
1141
1142
  		spin_lock(&BTRFS_I(inode)->lock);
  		BTRFS_I(inode)->outstanding_extents++;
  		spin_unlock(&BTRFS_I(inode)->lock);
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
1143
  		btrfs_delalloc_release_space(inode, data_reserved,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1144
1145
  				start_index << PAGE_SHIFT,
  				(page_cnt - i_done) << PAGE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1146
  	}
9e8a4a8b0   Liu Bo   Btrfs: use flag E...
1147
  	set_extent_defrag(&BTRFS_I(inode)->io_tree, page_start, page_end - 1,
018ed4f78   David Sterba   btrfs: sink gfp p...
1148
  			  &cached_state);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
  
  	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...
1160
  		put_page(pages[i]);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1161
  	}
364ecf365   Qu Wenruo   btrfs: qgroup: In...
1162
  	extent_changeset_free(data_reserved);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1163
1164
1165
1166
  	return i_done;
  out:
  	for (i = 0; i < i_done; i++) {
  		unlock_page(pages[i]);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1167
  		put_page(pages[i]);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1168
  	}
bc42bda22   Qu Wenruo   btrfs: qgroup: Fi...
1169
  	btrfs_delalloc_release_space(inode, data_reserved,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1170
1171
  			start_index << PAGE_SHIFT,
  			page_cnt << PAGE_SHIFT);
364ecf365   Qu Wenruo   btrfs: qgroup: In...
1172
  	extent_changeset_free(data_reserved);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1173
1174
1175
1176
1177
1178
1179
1180
  	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)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1181
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1182
  	struct btrfs_root *root = BTRFS_I(inode)->root;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1183
  	struct file_ra_state *ra = NULL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1184
  	unsigned long last_index;
151a31b25   Li Zefan   Btrfs: use i_size...
1185
  	u64 isize = i_size_read(inode);
940100a4a   Chris Mason   Btrfs: be more se...
1186
1187
1188
  	u64 last_len = 0;
  	u64 skip = 0;
  	u64 defrag_end = 0;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1189
  	u64 newer_off = range->start;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1190
  	unsigned long i;
008873eaf   Li Zefan   Btrfs: honor exte...
1191
  	unsigned long ra_index = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1192
  	int ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1193
  	int defrag_count = 0;
1a419d85a   Li Zefan   btrfs: Allow to s...
1194
  	int compress_type = BTRFS_COMPRESS_ZLIB;
aab110abc   David Sterba   btrfs: defrag, us...
1195
  	u32 extent_thresh = range->extent_thresh;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1196
  	unsigned long max_cluster = SZ_256K >> PAGE_SHIFT;
c41570c9d   Justin Maggard   btrfs: fix defrag...
1197
  	unsigned long cluster = max_cluster;
ee22184b5   Byongho Lee   Btrfs: use linux/...
1198
  	u64 new_align = ~((u64)SZ_128K - 1);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1199
  	struct page **pages = NULL;
1e2ef46d8   David Sterba   btrfs: defrag: cl...
1200
  	bool do_compress = range->flags & BTRFS_DEFRAG_RANGE_COMPRESS;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1201

0abd5b172   Liu Bo   Btrfs: return err...
1202
1203
1204
1205
1206
  	if (isize == 0)
  		return 0;
  
  	if (range->start >= isize)
  		return -EINVAL;
1a419d85a   Li Zefan   btrfs: Allow to s...
1207

1e2ef46d8   David Sterba   btrfs: defrag: cl...
1208
  	if (do_compress) {
1a419d85a   Li Zefan   btrfs: Allow to s...
1209
1210
1211
1212
1213
  		if (range->compress_type > BTRFS_COMPRESS_TYPES)
  			return -EINVAL;
  		if (range->compress_type)
  			compress_type = range->compress_type;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1214

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

4cb5300bc   Chris Mason   Btrfs: add mount ...
1218
  	/*
0a52d1080   David Sterba   btrfs: defrag: ma...
1219
1220
1221
  	 * If we were not given a file, allocate a readahead context. As
  	 * readahead is just an optimization, defrag will work without it so
  	 * we don't error out.
4cb5300bc   Chris Mason   Btrfs: add mount ...
1222
1223
  	 */
  	if (!file) {
63e727ecd   David Sterba   btrfs: use GFP_KE...
1224
  		ra = kzalloc(sizeof(*ra), GFP_KERNEL);
0a52d1080   David Sterba   btrfs: defrag: ma...
1225
1226
  		if (ra)
  			file_ra_state_init(ra, inode->i_mapping);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1227
1228
1229
  	} else {
  		ra = &file->f_ra;
  	}
63e727ecd   David Sterba   btrfs: use GFP_KE...
1230
  	pages = kmalloc_array(max_cluster, sizeof(struct page *), GFP_KERNEL);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1231
1232
1233
1234
1235
1236
  	if (!pages) {
  		ret = -ENOMEM;
  		goto out_ra;
  	}
  
  	/* find the last page to defrag */
1e701a329   Chris Mason   Btrfs: add new de...
1237
  	if (range->start + range->len > range->start) {
151a31b25   Li Zefan   Btrfs: use i_size...
1238
  		last_index = min_t(u64, isize - 1,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1239
  			 range->start + range->len - 1) >> PAGE_SHIFT;
1e701a329   Chris Mason   Btrfs: add new de...
1240
  	} else {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1241
  		last_index = (isize - 1) >> PAGE_SHIFT;
1e701a329   Chris Mason   Btrfs: add new de...
1242
  	}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1243
1244
  	if (newer_than) {
  		ret = find_new_extents(root, inode, newer_than,
ee22184b5   Byongho Lee   Btrfs: use linux/...
1245
  				       &newer_off, SZ_64K);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1246
1247
1248
1249
1250
1251
  		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...
1252
  			i = (newer_off & new_align) >> PAGE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1253
1254
1255
  		} else
  			goto out_ra;
  	} else {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1256
  		i = range->start >> PAGE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1257
1258
  	}
  	if (!max_to_defrag)
070034bdf   chandan   Btrfs: btrfs_defr...
1259
  		max_to_defrag = last_index - i + 1;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1260

2a0f7f576   Li Zefan   Btrfs: fix recurs...
1261
1262
1263
1264
1265
1266
  	/*
  	 * 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 ...
1267
  	while (i <= last_index && defrag_count < max_to_defrag &&
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1268
  	       (i < DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE))) {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1269
1270
1271
1272
1273
1274
  		/*
  		 * make sure we stop running if someone unmounts
  		 * the FS
  		 */
  		if (!(inode->i_sb->s_flags & MS_ACTIVE))
  			break;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1275
1276
  		if (btrfs_defrag_cancelled(fs_info)) {
  			btrfs_debug(fs_info, "defrag_file cancelled");
210549ebe   David Sterba   btrfs: add cancel...
1277
1278
1279
  			ret = -EAGAIN;
  			break;
  		}
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1280
  		if (!should_defrag_range(inode, (u64)i << PAGE_SHIFT,
6c282eb40   Li Zefan   Btrfs: fix defrag...
1281
  					 extent_thresh, &last_len, &skip,
1e2ef46d8   David Sterba   btrfs: defrag: cl...
1282
  					 &defrag_end, do_compress)){
940100a4a   Chris Mason   Btrfs: be more se...
1283
1284
1285
1286
1287
  			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...
1288
  			next = DIV_ROUND_UP(skip, PAGE_SIZE);
940100a4a   Chris Mason   Btrfs: be more se...
1289
1290
1291
  			i = max(i + 1, next);
  			continue;
  		}
008873eaf   Li Zefan   Btrfs: honor exte...
1292
1293
  
  		if (!newer_than) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1294
1295
  			cluster = (PAGE_ALIGN(defrag_end) >>
  				   PAGE_SHIFT) - i;
008873eaf   Li Zefan   Btrfs: honor exte...
1296
1297
1298
1299
  			cluster = min(cluster, max_cluster);
  		} else {
  			cluster = max_cluster;
  		}
008873eaf   Li Zefan   Btrfs: honor exte...
1300
1301
  		if (i + cluster > ra_index) {
  			ra_index = max(i, ra_index);
0a52d1080   David Sterba   btrfs: defrag: ma...
1302
  			if (ra)
d3c0bab56   David Sterba   btrfs: remove tri...
1303
1304
  				page_cache_sync_readahead(inode->i_mapping, ra,
  						file, ra_index, cluster);
e4826a5b2   chandan   Btrfs: btrfs_defr...
1305
  			ra_index += cluster;
008873eaf   Li Zefan   Btrfs: honor exte...
1306
  		}
940100a4a   Chris Mason   Btrfs: be more se...
1307

5955102c9   Al Viro   wrappers for ->i_...
1308
  		inode_lock(inode);
1e2ef46d8   David Sterba   btrfs: defrag: cl...
1309
  		if (do_compress)
eec63c65d   David Sterba   btrfs: separate d...
1310
  			BTRFS_I(inode)->defrag_compress = compress_type;
008873eaf   Li Zefan   Btrfs: honor exte...
1311
  		ret = cluster_pages_for_defrag(inode, pages, i, cluster);
ecb8bea87   Liu Bo   Btrfs: fix race b...
1312
  		if (ret < 0) {
5955102c9   Al Viro   wrappers for ->i_...
1313
  			inode_unlock(inode);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1314
  			goto out_ra;
ecb8bea87   Liu Bo   Btrfs: fix race b...
1315
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1316
1317
  
  		defrag_count += ret;
d0e1d66b5   Namjae Jeon   writeback: remove...
1318
  		balance_dirty_pages_ratelimited(inode->i_mapping);
5955102c9   Al Viro   wrappers for ->i_...
1319
  		inode_unlock(inode);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1320
1321
1322
1323
  
  		if (newer_than) {
  			if (newer_off == (u64)-1)
  				break;
e1f041e14   Liu Bo   Btrfs: update to ...
1324
1325
  			if (ret > 0)
  				i += ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1326
  			newer_off = max(newer_off + 1,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1327
  					(u64)i << PAGE_SHIFT);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1328

ee22184b5   Byongho Lee   Btrfs: use linux/...
1329
1330
  			ret = find_new_extents(root, inode, newer_than,
  					       &newer_off, SZ_64K);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1331
1332
  			if (!ret) {
  				range->start = newer_off;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1333
  				i = (newer_off & new_align) >> PAGE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1334
1335
  			} else {
  				break;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1336
  			}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1337
  		} else {
008873eaf   Li Zefan   Btrfs: honor exte...
1338
  			if (ret > 0) {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1339
  				i += ret;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1340
  				last_len += ret << PAGE_SHIFT;
008873eaf   Li Zefan   Btrfs: honor exte...
1341
  			} else {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1342
  				i++;
008873eaf   Li Zefan   Btrfs: honor exte...
1343
1344
  				last_len = 0;
  			}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1345
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1346
  	}
dec8ef905   Filipe Manana   Btrfs: correctly ...
1347
  	if ((range->flags & BTRFS_DEFRAG_RANGE_START_IO)) {
1e701a329   Chris Mason   Btrfs: add new de...
1348
  		filemap_flush(inode->i_mapping);
dec8ef905   Filipe Manana   Btrfs: correctly ...
1349
1350
1351
1352
  		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...
1353

1e2ef46d8   David Sterba   btrfs: defrag: cl...
1354
  	if (do_compress) {
1e701a329   Chris Mason   Btrfs: add new de...
1355
1356
1357
1358
  		/* 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
  		 */
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1359
1360
1361
1362
1363
1364
  		atomic_inc(&fs_info->async_submit_draining);
  		while (atomic_read(&fs_info->nr_async_submits) ||
  		       atomic_read(&fs_info->async_delalloc_pages)) {
  			wait_event(fs_info->async_submit_wait,
  				   (atomic_read(&fs_info->nr_async_submits) == 0 &&
  				    atomic_read(&fs_info->async_delalloc_pages) == 0));
1e701a329   Chris Mason   Btrfs: add new de...
1365
  		}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1366
  		atomic_dec(&fs_info->async_submit_draining);
1e701a329   Chris Mason   Btrfs: add new de...
1367
  	}
1a419d85a   Li Zefan   btrfs: Allow to s...
1368
  	if (range->compress_type == BTRFS_COMPRESS_LZO) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1369
  		btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
5c1aab1dd   Nick Terrell   btrfs: Add zstd s...
1370
1371
  	} else if (range->compress_type == BTRFS_COMPRESS_ZSTD) {
  		btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
1a419d85a   Li Zefan   btrfs: Allow to s...
1372
  	}
60ccf82f5   Diego Calleja   btrfs: fix memory...
1373
  	ret = defrag_count;
940100a4a   Chris Mason   Btrfs: be more se...
1374

4cb5300bc   Chris Mason   Btrfs: add mount ...
1375
  out_ra:
1e2ef46d8   David Sterba   btrfs: defrag: cl...
1376
  	if (do_compress) {
5955102c9   Al Viro   wrappers for ->i_...
1377
  		inode_lock(inode);
eec63c65d   David Sterba   btrfs: separate d...
1378
  		BTRFS_I(inode)->defrag_compress = BTRFS_COMPRESS_NONE;
5955102c9   Al Viro   wrappers for ->i_...
1379
  		inode_unlock(inode);
633085c79   Filipe David Borba Manana   Btrfs: reset forc...
1380
  	}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1381
1382
1383
  	if (!file)
  		kfree(ra);
  	kfree(pages);
940100a4a   Chris Mason   Btrfs: be more se...
1384
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1385
  }
198605a8e   Miao Xie   Btrfs: get write ...
1386
  static noinline int btrfs_ioctl_resize(struct file *file,
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1387
  					void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1388
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1389
1390
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1391
1392
1393
  	u64 new_size;
  	u64 old_size;
  	u64 devid = 1;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1394
  	struct btrfs_root *root = BTRFS_I(inode)->root;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1395
1396
1397
1398
  	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...
1399
  	char *retptr;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1400
1401
  	char *devstr = NULL;
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1402
  	int mod = 0;
e441d54de   Chris Mason   Btrfs: add permis...
1403
1404
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
198605a8e   Miao Xie   Btrfs: get write ...
1405
1406
1407
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
171938e52   David Sterba   btrfs: track excl...
1408
  	if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
975476765   Miao Xie   Btrfs: fix missin...
1409
  		mnt_drop_write_file(file);
e57138b3e   Anand Jain   btrfs: return btr...
1410
  		return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1411
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1412
  	mutex_lock(&fs_info->volume_mutex);
dae7b665c   Li Zefan   btrfs: use memdup...
1413
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1414
1415
1416
1417
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
  		goto out;
  	}
5516e5957   Mark Fasheh   Btrfs: Null termi...
1418
1419
  
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1420

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1421
1422
1423
  	sizestr = vol_args->name;
  	devstr = strchr(sizestr, ':');
  	if (devstr) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1424
1425
1426
  		sizestr = devstr + 1;
  		*devstr = '\0';
  		devstr = vol_args->name;
58dfae636   ZhangZhen   btrfs: replace si...
1427
1428
1429
  		ret = kstrtoull(devstr, 10, &devid);
  		if (ret)
  			goto out_free;
dfd79829b   Miao Xie   Btrfs: fix trivia...
1430
1431
1432
1433
  		if (!devid) {
  			ret = -EINVAL;
  			goto out_free;
  		}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1434
  		btrfs_info(fs_info, "resizing devid %llu", devid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1435
  	}
dba60f3f5   Miao Xie   Btrfs: fix resize...
1436

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1437
  	device = btrfs_find_device(fs_info, devid, NULL, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1438
  	if (!device) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1439
1440
  		btrfs_info(fs_info, "resizer unable to find device %llu",
  			   devid);
dfd79829b   Miao Xie   Btrfs: fix trivia...
1441
  		ret = -ENODEV;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1442
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1443
  	}
dba60f3f5   Miao Xie   Btrfs: fix resize...
1444
1445
  
  	if (!device->writeable) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1446
  		btrfs_info(fs_info,
efe120a06   Frank Holton   Btrfs: convert pr...
1447
  			   "resizer unable to apply on readonly device %llu",
c1c9ff7c9   Geert Uytterhoeven   Btrfs: Remove sup...
1448
  		       devid);
dfd79829b   Miao Xie   Btrfs: fix trivia...
1449
  		ret = -EPERM;
4e42ae1bd   Liu Bo   Btrfs: do not res...
1450
1451
  		goto out_free;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  	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...
1462
1463
  		new_size = memparse(sizestr, &retptr);
  		if (*retptr != '\0' || new_size == 0) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1464
  			ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1465
  			goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1466
1467
  		}
  	}
63a212abc   Stefan Behrens   Btrfs: disallow s...
1468
  	if (device->is_tgtdev_for_dev_replace) {
dfd79829b   Miao Xie   Btrfs: fix trivia...
1469
  		ret = -EPERM;
63a212abc   Stefan Behrens   Btrfs: disallow s...
1470
1471
  		goto out_free;
  	}
7cc8e58d5   Miao Xie   Btrfs: fix unprot...
1472
  	old_size = btrfs_device_get_total_bytes(device);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1473
1474
1475
1476
  
  	if (mod < 0) {
  		if (new_size > old_size) {
  			ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1477
  			goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1478
1479
1480
  		}
  		new_size = old_size - new_size;
  	} else if (mod > 0) {
eb8052e01   Wenliang Fan   fs/btrfs: Integer...
1481
  		if (new_size > ULLONG_MAX - old_size) {
902c68a4d   Gui Hecheng   btrfs: replace EI...
1482
  			ret = -ERANGE;
eb8052e01   Wenliang Fan   fs/btrfs: Integer...
1483
1484
  			goto out_free;
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1485
1486
  		new_size = old_size + new_size;
  	}
ee22184b5   Byongho Lee   Btrfs: use linux/...
1487
  	if (new_size < SZ_256M) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1488
  		ret = -EINVAL;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1489
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1490
1491
1492
  	}
  	if (new_size > device->bdev->bd_inode->i_size) {
  		ret = -EFBIG;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1493
  		goto out_free;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1494
  	}
47f08b969   Nikolay Borisov   btrfs: Use explic...
1495
  	new_size = round_down(new_size, fs_info->sectorsize);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1496

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1497
1498
  	btrfs_info_in_rcu(fs_info, "new size for %s is %llu",
  			  rcu_str_deref(device->name), new_size);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1499
1500
  
  	if (new_size > old_size) {
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
1501
  		trans = btrfs_start_transaction(root, 0);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
1502
1503
  		if (IS_ERR(trans)) {
  			ret = PTR_ERR(trans);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1504
  			goto out_free;
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
1505
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1506
  		ret = btrfs_grow_device(trans, device, new_size);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
1507
  		btrfs_commit_transaction(trans);
ece7d20e8   Mike Fleetwood   Btrfs: Don't erro...
1508
  	} else if (new_size < old_size) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1509
  		ret = btrfs_shrink_device(device, new_size);
0253f40ef   jeff.liu   Btrfs: Remove the...
1510
  	} /* equal, nothing need to do */
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1511

c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1512
  out_free:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1513
  	kfree(vol_args);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
1514
  out:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1515
  	mutex_unlock(&fs_info->volume_mutex);
171938e52   David Sterba   btrfs: track excl...
1516
  	clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
18f39c416   Ilya Dryomov   Btrfs: fix unlock...
1517
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1518
1519
  	return ret;
  }
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1520
  static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
52f75f4fe   David Sterba   btrfs: constify n...
1521
  				const char *name, unsigned long fd, int subvol,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1522
  				u64 *transid, bool readonly,
8696c5330   Miao Xie   Btrfs: fix memory...
1523
  				struct btrfs_qgroup_inherit *inherit)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1524
  {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1525
  	int namelen;
3de4586c5   Chris Mason   Btrfs: Allow subv...
1526
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1527

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

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

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1593
1594
1595
  	kfree(vol_args);
  	return ret;
  }
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1596

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1597
1598
1599
1600
1601
1602
1603
  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...
1604
  	bool readonly = false;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1605
  	struct btrfs_qgroup_inherit *inherit = NULL;
75eaa0e22   Sage Weil   Btrfs: fix sync s...
1606

325c50e3c   Jeff Mahoney   btrfs: ensure tha...
1607
1608
  	if (!S_ISDIR(file_inode(file)->i_mode))
  		return -ENOTDIR;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1609
1610
1611
1612
  	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...
1613

b83cc9693   Li Zefan   Btrfs: Add readon...
1614
  	if (vol_args->flags &
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1615
1616
  	    ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY |
  	      BTRFS_SUBVOL_QGROUP_INHERIT)) {
b83cc9693   Li Zefan   Btrfs: Add readon...
1617
  		ret = -EOPNOTSUPP;
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1618
  		goto free_args;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1619
  	}
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1620
1621
1622
  
  	if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
  		ptr = &transid;
b83cc9693   Li Zefan   Btrfs: Add readon...
1623
1624
  	if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
  		readonly = true;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1625
  	if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
1626
  		if (vol_args->size > PAGE_SIZE) {
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1627
  			ret = -EINVAL;
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1628
  			goto free_args;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1629
1630
1631
1632
  		}
  		inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size);
  		if (IS_ERR(inherit)) {
  			ret = PTR_ERR(inherit);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1633
  			goto free_args;
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1634
1635
  		}
  	}
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1636
1637
  
  	ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1638
  					      vol_args->fd, subvol, ptr,
8696c5330   Miao Xie   Btrfs: fix memory...
1639
  					      readonly, inherit);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1640
1641
  	if (ret)
  		goto free_inherit;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1642

c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1643
1644
1645
1646
  	if (ptr && copy_to_user(arg +
  				offsetof(struct btrfs_ioctl_vol_args_v2,
  					transid),
  				ptr, sizeof(*ptr)))
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1647
  		ret = -EFAULT;
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1648
1649
  
  free_inherit:
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
1650
  	kfree(inherit);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
1651
1652
  free_args:
  	kfree(vol_args);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1653
1654
  	return ret;
  }
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1655
1656
1657
  static noinline int btrfs_ioctl_subvol_getflags(struct file *file,
  						void __user *arg)
  {
496ad9aa8   Al Viro   new helper: file_...
1658
  	struct inode *inode = file_inode(file);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1659
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1660
1661
1662
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret = 0;
  	u64 flags = 0;
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
1663
  	if (btrfs_ino(BTRFS_I(inode)) != BTRFS_FIRST_FREE_OBJECTID)
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1664
  		return -EINVAL;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1665
  	down_read(&fs_info->subvol_sem);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1666
1667
  	if (btrfs_root_readonly(root))
  		flags |= BTRFS_SUBVOL_RDONLY;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1668
  	up_read(&fs_info->subvol_sem);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
  
  	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_...
1679
  	struct inode *inode = file_inode(file);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1680
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1681
1682
1683
1684
1685
  	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...
1686
1687
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
b9ca0664d   Liu Bo   Btrfs: do not set...
1688
1689
1690
  	ret = mnt_want_write_file(file);
  	if (ret)
  		goto out;
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1691

4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
1692
  	if (btrfs_ino(BTRFS_I(inode)) != BTRFS_FIRST_FREE_OBJECTID) {
b9ca0664d   Liu Bo   Btrfs: do not set...
1693
1694
1695
  		ret = -EINVAL;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1696

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

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

b9ca0664d   Liu Bo   Btrfs: do not set...
1707
1708
1709
1710
  	if (flags & ~BTRFS_SUBVOL_RDONLY) {
  		ret = -EOPNOTSUPP;
  		goto out_drop_write;
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1711

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1712
  	down_write(&fs_info->subvol_sem);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1713
1714
1715
  
  	/* nothing to do */
  	if (!!(flags & BTRFS_SUBVOL_RDONLY) == btrfs_root_readonly(root))
b9ca0664d   Liu Bo   Btrfs: do not set...
1716
  		goto out_drop_sem;
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1717
1718
  
  	root_flags = btrfs_root_flags(&root->root_item);
2c6865378   David Sterba   btrfs: Check read...
1719
  	if (flags & BTRFS_SUBVOL_RDONLY) {
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1720
1721
  		btrfs_set_root_flags(&root->root_item,
  				     root_flags | BTRFS_ROOT_SUBVOL_RDONLY);
2c6865378   David Sterba   btrfs: Check read...
1722
1723
1724
1725
1726
1727
1728
1729
  	} 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_...
1730
  				     root_flags & ~BTRFS_ROOT_SUBVOL_RDONLY);
2c6865378   David Sterba   btrfs: Check read...
1731
1732
1733
  			spin_unlock(&root->root_item_lock);
  		} else {
  			spin_unlock(&root->root_item_lock);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1734
1735
1736
  			btrfs_warn(fs_info,
  				   "Attempt to set subvolume %llu read-write during send",
  				   root->root_key.objectid);
2c6865378   David Sterba   btrfs: Check read...
1737
1738
1739
1740
  			ret = -EPERM;
  			goto out_drop_sem;
  		}
  	}
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1741
1742
1743
1744
1745
1746
  
  	trans = btrfs_start_transaction(root, 1);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_reset;
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1747
  	ret = btrfs_update_root(trans, fs_info->tree_root,
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1748
  				&root->root_key, &root->root_item);
9e87c49d6   Nikolay Borisov   btrfs: Explicitly...
1749
1750
1751
1752
1753
1754
  	if (ret < 0) {
  		btrfs_end_transaction(trans);
  		goto out_reset;
  	}
  
  	ret = btrfs_commit_transaction(trans);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1755

0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1756
1757
1758
  out_reset:
  	if (ret)
  		btrfs_set_root_flags(&root->root_item, root_flags);
b9ca0664d   Liu Bo   Btrfs: do not set...
1759
  out_drop_sem:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1760
  	up_write(&fs_info->subvol_sem);
b9ca0664d   Liu Bo   Btrfs: do not set...
1761
1762
1763
  out_drop_write:
  	mnt_drop_write_file(file);
  out:
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1764
1765
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1766
1767
1768
1769
1770
  /*
   * helper to check if the subvolume references other subvolumes
   */
  static noinline int may_destroy_subvol(struct btrfs_root *root)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1771
  	struct btrfs_fs_info *fs_info = root->fs_info;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1772
  	struct btrfs_path *path;
175a2b871   Josef Bacik   Btrfs: don't allo...
1773
  	struct btrfs_dir_item *di;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1774
  	struct btrfs_key key;
175a2b871   Josef Bacik   Btrfs: don't allo...
1775
  	u64 dir_id;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1776
1777
1778
1779
1780
  	int ret;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
175a2b871   Josef Bacik   Btrfs: don't allo...
1781
  	/* Make sure this root isn't set as the default subvol */
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1782
1783
  	dir_id = btrfs_super_root_dir(fs_info->super_copy);
  	di = btrfs_lookup_dir_item(NULL, fs_info->tree_root, path,
175a2b871   Josef Bacik   Btrfs: don't allo...
1784
1785
1786
1787
  				   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...
1788
  			ret = -EPERM;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1789
  			btrfs_err(fs_info,
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
1790
1791
  				  "deleting default subvolume %llu is not allowed",
  				  key.objectid);
175a2b871   Josef Bacik   Btrfs: don't allo...
1792
1793
1794
1795
  			goto out;
  		}
  		btrfs_release_path(path);
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1796
1797
1798
  	key.objectid = root->root_key.objectid;
  	key.type = BTRFS_ROOT_REF_KEY;
  	key.offset = (u64)-1;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1799
  	ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, path, 0, 0);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
  	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...
1816
1817
1818
  static noinline int key_in_sk(struct btrfs_key *key,
  			      struct btrfs_ioctl_search_key *sk)
  {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1819
1820
1821
1822
1823
1824
1825
1826
1827
  	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...
1828
  		return 0;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1829
1830
1831
1832
1833
1834
1835
  
  	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...
1836
1837
1838
  		return 0;
  	return 1;
  }
df3975652   Jeff Mahoney   btrfs: copy_to_sk...
1839
  static noinline int copy_to_sk(struct btrfs_path *path,
ac8e9819d   Chris Mason   Btrfs: add search...
1840
1841
  			       struct btrfs_key *key,
  			       struct btrfs_ioctl_search_key *sk,
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1842
  			       size_t *buf_size,
ba346b357   Gerhard Heift   btrfs: tree_searc...
1843
  			       char __user *ubuf,
ac8e9819d   Chris Mason   Btrfs: add search...
1844
1845
1846
1847
1848
1849
  			       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...
1850
  	struct btrfs_key test;
ac8e9819d   Chris Mason   Btrfs: add search...
1851
1852
1853
1854
1855
  	unsigned long item_off;
  	unsigned long item_len;
  	int nritems;
  	int i;
  	int slot;
ac8e9819d   Chris Mason   Btrfs: add search...
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
  	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...
1871
1872
1873
  		btrfs_item_key_to_cpu(leaf, key, i);
  		if (!key_in_sk(key, sk))
  			continue;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1874
  		if (sizeof(sh) + item_len > *buf_size) {
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
1875
1876
1877
1878
1879
1880
1881
1882
1883
  			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...
1884
  			*buf_size = sizeof(sh) + item_len;
ac8e9819d   Chris Mason   Btrfs: add search...
1885
  			item_len = 0;
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
1886
1887
  			ret = -EOVERFLOW;
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1888

9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1889
  		if (sizeof(sh) + item_len + *sk_offset > *buf_size) {
ac8e9819d   Chris Mason   Btrfs: add search...
1890
  			ret = 1;
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
1891
  			goto out;
ac8e9819d   Chris Mason   Btrfs: add search...
1892
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1893
1894
1895
1896
1897
1898
1899
  		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...
1900
1901
1902
1903
  		if (copy_to_user(ubuf + *sk_offset, &sh, sizeof(sh))) {
  			ret = -EFAULT;
  			goto out;
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1904
1905
1906
  		*sk_offset += sizeof(sh);
  
  		if (item_len) {
ba346b357   Gerhard Heift   btrfs: tree_searc...
1907
  			char __user *up = ubuf + *sk_offset;
ac8e9819d   Chris Mason   Btrfs: add search...
1908
  			/* copy the item */
ba346b357   Gerhard Heift   btrfs: tree_searc...
1909
1910
1911
1912
1913
  			if (read_extent_buffer_to_user(leaf, up,
  						       item_off, item_len)) {
  				ret = -EFAULT;
  				goto out;
  			}
ac8e9819d   Chris Mason   Btrfs: add search...
1914
  			*sk_offset += item_len;
ac8e9819d   Chris Mason   Btrfs: add search...
1915
  		}
e21568671   Hugo Mills   btrfs: Ensure the...
1916
  		(*num_found)++;
ac8e9819d   Chris Mason   Btrfs: add search...
1917

8f5f6178f   Gerhard Heift   btrfs: tree_searc...
1918
1919
  		if (ret) /* -EOVERFLOW from above */
  			goto out;
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
1920
1921
1922
1923
  		if (*num_found >= sk->nr_items) {
  			ret = 1;
  			goto out;
  		}
ac8e9819d   Chris Mason   Btrfs: add search...
1924
1925
  	}
  advance_key:
abc6e1341   Chris Mason   Btrfs: fix key ch...
1926
  	ret = 0;
dd81d459a   Naohiro Aota   btrfs: fix search...
1927
1928
1929
1930
1931
1932
  	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...
1933
  		key->offset++;
dd81d459a   Naohiro Aota   btrfs: fix search...
1934
  	else if (key->type < (u8)-1) {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1935
  		key->offset = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1936
  		key->type++;
dd81d459a   Naohiro Aota   btrfs: fix search...
1937
  	} else if (key->objectid < (u64)-1) {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1938
1939
  		key->offset = 0;
  		key->type = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1940
  		key->objectid++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1941
1942
  	} else
  		ret = 1;
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
1943
  out:
ba346b357   Gerhard Heift   btrfs: tree_searc...
1944
1945
1946
1947
1948
1949
1950
1951
1952
  	/*
  	 *  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...
1953
1954
1955
1956
  	return ret;
  }
  
  static noinline int search_ioctl(struct inode *inode,
125444428   Gerhard Heift   btrfs: tree_searc...
1957
  				 struct btrfs_ioctl_search_key *sk,
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1958
  				 size_t *buf_size,
ba346b357   Gerhard Heift   btrfs: tree_searc...
1959
  				 char __user *ubuf)
ac8e9819d   Chris Mason   Btrfs: add search...
1960
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
1961
  	struct btrfs_fs_info *info = btrfs_sb(inode->i_sb);
ac8e9819d   Chris Mason   Btrfs: add search...
1962
1963
  	struct btrfs_root *root;
  	struct btrfs_key key;
ac8e9819d   Chris Mason   Btrfs: add search...
1964
  	struct btrfs_path *path;
ac8e9819d   Chris Mason   Btrfs: add search...
1965
1966
1967
  	int ret;
  	int num_found = 0;
  	unsigned long sk_offset = 0;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1968
1969
  	if (*buf_size < sizeof(struct btrfs_ioctl_search_header)) {
  		*buf_size = sizeof(struct btrfs_ioctl_search_header);
125444428   Gerhard Heift   btrfs: tree_searc...
1970
  		return -EOVERFLOW;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
1971
  	}
125444428   Gerhard Heift   btrfs: tree_searc...
1972

ac8e9819d   Chris Mason   Btrfs: add search...
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
  	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...
1986
1987
1988
1989
1990
1991
1992
1993
  			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...
1994
  	while (1) {
6174d3cb4   Filipe David Borba Manana   Btrfs: remove unu...
1995
  		ret = btrfs_search_forward(root, &key, path, sk->min_transid);
ac8e9819d   Chris Mason   Btrfs: add search...
1996
1997
1998
1999
2000
  		if (ret != 0) {
  			if (ret > 0)
  				ret = 0;
  			goto err;
  		}
df3975652   Jeff Mahoney   btrfs: copy_to_sk...
2001
  		ret = copy_to_sk(path, &key, sk, buf_size, ubuf,
ac8e9819d   Chris Mason   Btrfs: add search...
2002
  				 &sk_offset, &num_found);
b3b4aa74b   David Sterba   btrfs: drop unuse...
2003
  		btrfs_release_path(path);
25c9bc2e2   Gerhard Heift   btrfs: tree_searc...
2004
  		if (ret)
ac8e9819d   Chris Mason   Btrfs: add search...
2005
2006
2007
  			break;
  
  	}
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
2008
2009
  	if (ret > 0)
  		ret = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
2010
2011
2012
2013
2014
2015
2016
2017
2018
  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...
2019
2020
  	struct btrfs_ioctl_search_args __user *uargs;
  	struct btrfs_ioctl_search_key sk;
9b6e817d0   Gerhard Heift   btrfs: tree_searc...
2021
2022
2023
  	struct inode *inode;
  	int ret;
  	size_t buf_size;
ac8e9819d   Chris Mason   Btrfs: add search...
2024
2025
2026
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
ba346b357   Gerhard Heift   btrfs: tree_searc...
2027
2028
2029
2030
  	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...
2031

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

496ad9aa8   Al Viro   new helper: file_...
2034
  	inode = file_inode(file);
ba346b357   Gerhard Heift   btrfs: tree_searc...
2035
  	ret = search_ioctl(inode, &sk, &buf_size, uargs->buf);
8f5f6178f   Gerhard Heift   btrfs: tree_searc...
2036
2037
2038
2039
2040
2041
2042
  
  	/*
  	 * 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...
2043
  	if (ret == 0 && copy_to_user(&uargs->key, &sk, sizeof(sk)))
ac8e9819d   Chris Mason   Btrfs: add search...
2044
  		ret = -EFAULT;
ac8e9819d   Chris Mason   Btrfs: add search...
2045
2046
  	return ret;
  }
cc68a8a5a   Gerhard Heift   btrfs: new ioctl ...
2047
2048
2049
2050
2051
2052
2053
2054
  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/...
2055
  	const size_t buf_limit = SZ_16M;
cc68a8a5a   Gerhard Heift   btrfs: new ioctl ...
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
  
  	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;
cc68a8a5a   Gerhard Heift   btrfs: new ioctl ...
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
  	/* 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...
2078
2079
  	return ret;
  }
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2080
  /*
ac8e9819d   Chris Mason   Btrfs: add search...
2081
2082
2083
   * 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...
2084
2085
2086
2087
2088
  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...
2089
  	char *ptr;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
  	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;
90b0805d6   Nikolay Borisov   btrfs: Fix possib...
2106
  	ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX - 1];
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2107
2108
2109
2110
2111
2112
  
  	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...
2113
  		btrfs_err(info, "could not find root %llu", tree_id);
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2114
2115
  		ret = -ENOENT;
  		goto out;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2116
2117
2118
2119
  	}
  
  	key.objectid = dirid;
  	key.type = BTRFS_INODE_REF_KEY;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2120
  	key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2121

678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2122
  	while (1) {
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2123
2124
2125
  		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  		if (ret < 0)
  			goto out;
18674c6cc   Filipe David Borba Manana   Btrfs: don't miss...
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
  		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...
2136
2137
2138
2139
  
  		l = path->nodes[0];
  		slot = path->slots[0];
  		btrfs_item_key_to_cpu(l, &key, slot);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2140
2141
2142
2143
  		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...
2144
2145
  		if (ptr < name) {
  			ret = -ENAMETOOLONG;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2146
  			goto out;
a696cf352   Filipe David Borba Manana   Btrfs: add missin...
2147
  		}
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2148
2149
  
  		*(ptr + len) = '/';
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2150
  		read_extent_buffer(l, ptr, (unsigned long)(iref + 1), len);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2151
2152
2153
  
  		if (key.offset == BTRFS_FIRST_FREE_OBJECTID)
  			break;
b3b4aa74b   David Sterba   btrfs: drop unuse...
2154
  		btrfs_release_path(path);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2155
  		key.objectid = key.offset;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
2156
  		key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2157
  		dirid = key.objectid;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2158
  	}
77906a507   Li Zefan   Btrfs: copy strin...
2159
  	memmove(name, ptr, total_len);
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2160
  	name[total_len] = '\0';
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2161
2162
2163
  	ret = 0;
  out:
  	btrfs_free_path(path);
ac8e9819d   Chris Mason   Btrfs: add search...
2164
2165
2166
2167
2168
2169
2170
2171
  	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 ...
2172
  	int ret = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
2173

2354d08fe   Julia Lawall   Btrfs: use memdup...
2174
2175
2176
  	args = memdup_user(argp, sizeof(*args));
  	if (IS_ERR(args))
  		return PTR_ERR(args);
c2b96929e   Dan Carpenter   Btrfs: handle kma...
2177

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

01b810b88   David Sterba   btrfs: make root ...
2180
2181
2182
2183
  	/*
  	 * 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...
2184
2185
  	if (args->treeid == 0)
  		args->treeid = BTRFS_I(inode)->root->root_key.objectid;
01b810b88   David Sterba   btrfs: make root ...
2186
2187
2188
2189
2190
2191
2192
2193
2194
  	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...
2195
2196
2197
  	ret = btrfs_search_path_in_tree(BTRFS_I(inode)->root->fs_info,
  					args->treeid, args->objectid,
  					args->name);
01b810b88   David Sterba   btrfs: make root ...
2198
  out:
ac8e9819d   Chris Mason   Btrfs: add search...
2199
2200
2201
2202
  	if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
  		ret = -EFAULT;
  
  	kfree(args);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
2203
2204
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2205
2206
2207
  static noinline int btrfs_ioctl_snap_destroy(struct file *file,
  					     void __user *arg)
  {
54563d41a   Al Viro   btrfs: get rid of...
2208
  	struct dentry *parent = file->f_path.dentry;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2209
  	struct btrfs_fs_info *fs_info = btrfs_sb(parent->d_sb);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2210
  	struct dentry *dentry;
2b0143b5c   David Howells   VFS: normal files...
2211
  	struct inode *dir = d_inode(parent);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2212
2213
2214
2215
2216
  	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 ...
2217
  	struct btrfs_block_rsv block_rsv;
521e0546c   David Sterba   btrfs: protect sn...
2218
  	u64 root_flags;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2219
  	u64 qgroup_reserved;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2220
2221
2222
  	int namelen;
  	int ret;
  	int err = 0;
325c50e3c   Jeff Mahoney   btrfs: ensure tha...
2223
2224
  	if (!S_ISDIR(dir->i_mode))
  		return -ENOTDIR;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
  	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...
2236
  	err = mnt_want_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2237
2238
  	if (err)
  		goto out;
521e0546c   David Sterba   btrfs: protect sn...
2239

002354112   Al Viro   restore killabili...
2240
2241
2242
  	err = down_write_killable_nested(&dir->i_rwsem, I_MUTEX_PARENT);
  	if (err == -EINTR)
  		goto out_drop_write;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2243
2244
2245
2246
2247
  	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...
2248
  	if (d_really_is_negative(dentry)) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2249
2250
2251
  		err = -ENOENT;
  		goto out_dput;
  	}
2b0143b5c   David Howells   VFS: normal files...
2252
  	inode = d_inode(dentry);
4260f7c75   Sage Weil   Btrfs: allow subv...
2253
  	dest = BTRFS_I(inode)->root;
678712545   Dulshani Gunawardhana   btrfs: Fix checkp...
2254
  	if (!capable(CAP_SYS_ADMIN)) {
4260f7c75   Sage Weil   Btrfs: allow subv...
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
  		/*
  		 * 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;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2269
  		if (!btrfs_test_opt(fs_info, USER_SUBVOL_RM_ALLOWED))
4260f7c75   Sage Weil   Btrfs: allow subv...
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
  			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...
2286
  	}
5c39da5b6   Miao Xie   Btrfs: do not del...
2287
2288
2289
2290
  	/* check if subvolume may be deleted by a user */
  	err = btrfs_may_delete(dir, dentry, 1);
  	if (err)
  		goto out_dput;
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
2291
  	if (btrfs_ino(BTRFS_I(inode)) != BTRFS_FIRST_FREE_OBJECTID) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2292
2293
2294
  		err = -EINVAL;
  		goto out_dput;
  	}
5955102c9   Al Viro   wrappers for ->i_...
2295
  	inode_lock(inode);
521e0546c   David Sterba   btrfs: protect sn...
2296
2297
2298
2299
2300
2301
2302
  
  	/*
  	 * 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...
2303
2304
2305
  	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...
2306
2307
2308
2309
  				root_flags | BTRFS_ROOT_SUBVOL_DEAD);
  		spin_unlock(&dest->root_item_lock);
  	} else {
  		spin_unlock(&dest->root_item_lock);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2310
2311
2312
  		btrfs_warn(fs_info,
  			   "Attempt to delete subvolume %llu during send",
  			   dest->root_key.objectid);
521e0546c   David Sterba   btrfs: protect sn...
2313
  		err = -EPERM;
909e26dce   Omar Sandoval   btrfs: unlock i_m...
2314
  		goto out_unlock_inode;
521e0546c   David Sterba   btrfs: protect sn...
2315
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2316
  	down_write(&fs_info->subvol_sem);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2317
2318
2319
2320
  
  	err = may_destroy_subvol(dest);
  	if (err)
  		goto out_up_write;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2321
2322
2323
2324
2325
2326
  	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 ...
2327
  					       5, &qgroup_reserved, true);
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2328
2329
  	if (err)
  		goto out_up_write;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2330
2331
2332
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		err = PTR_ERR(trans);
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2333
  		goto out_release;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2334
  	}
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2335
2336
  	trans->block_rsv = &block_rsv;
  	trans->bytes_reserved = block_rsv.size;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2337

436635571   Nikolay Borisov   btrfs: Make btrfs...
2338
  	btrfs_record_snapshot_destroy(trans, BTRFS_I(dir));
2be63d5ce   Filipe Manana   Btrfs: fix file l...
2339

76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2340
2341
2342
2343
  	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...
2344
2345
  	if (ret) {
  		err = ret;
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2346
  		btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2347
2348
  		goto out_end_trans;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2349
2350
2351
2352
2353
2354
2355
  
  	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...
2356
  	if (!test_and_set_bit(BTRFS_ROOT_ORPHAN_ITEM_INSERTED, &dest->state)) {
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
2357
  		ret = btrfs_insert_orphan_item(trans,
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2358
  					fs_info->tree_root,
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
2359
  					dest->root_key.objectid);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2360
  		if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2361
  			btrfs_abort_transaction(trans, ret);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2362
2363
2364
  			err = ret;
  			goto out_end_trans;
  		}
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
2365
  	}
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2366

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2367
  	ret = btrfs_uuid_tree_rem(trans, fs_info, dest->root_item.uuid,
6bccf3ab1   Jeff Mahoney   btrfs: call funct...
2368
  				  BTRFS_UUID_KEY_SUBVOL,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2369
2370
  				  dest->root_key.objectid);
  	if (ret && ret != -ENOENT) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2371
  		btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2372
2373
2374
2375
  		err = ret;
  		goto out_end_trans;
  	}
  	if (!btrfs_is_empty_uuid(dest->root_item.received_uuid)) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2376
  		ret = btrfs_uuid_tree_rem(trans, fs_info,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2377
2378
2379
2380
  					  dest->root_item.received_uuid,
  					  BTRFS_UUID_KEY_RECEIVED_SUBVOL,
  					  dest->root_key.objectid);
  		if (ret && ret != -ENOENT) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
2381
  			btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2382
2383
2384
2385
  			err = ret;
  			goto out_end_trans;
  		}
  	}
79787eaab   Jeff Mahoney   btrfs: replace ma...
2386
  out_end_trans:
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2387
2388
  	trans->block_rsv = NULL;
  	trans->bytes_reserved = 0;
3a45bb207   Jeff Mahoney   btrfs: remove roo...
2389
  	ret = btrfs_end_transaction(trans);
79787eaab   Jeff Mahoney   btrfs: replace ma...
2390
2391
  	if (ret && !err)
  		err = ret;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2392
  	inode->i_flags |= S_DEAD;
c58aaad2a   Miao Xie   Btrfs: fix wrong ...
2393
  out_release:
7775c8184   David Sterba   btrfs: remove unu...
2394
  	btrfs_subvolume_release_metadata(fs_info, &block_rsv);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2395
  out_up_write:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2396
  	up_write(&fs_info->subvol_sem);
521e0546c   David Sterba   btrfs: protect sn...
2397
2398
  	if (err) {
  		spin_lock(&dest->root_item_lock);
c55bfa67e   Filipe Manana   Btrfs: set dead f...
2399
2400
  		root_flags = btrfs_root_flags(&dest->root_item);
  		btrfs_set_root_flags(&dest->root_item,
521e0546c   David Sterba   btrfs: protect sn...
2401
2402
2403
  				root_flags & ~BTRFS_ROOT_SUBVOL_DEAD);
  		spin_unlock(&dest->root_item_lock);
  	}
909e26dce   Omar Sandoval   btrfs: unlock i_m...
2404
  out_unlock_inode:
5955102c9   Al Viro   wrappers for ->i_...
2405
  	inode_unlock(inode);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2406
  	if (!err) {
64ad6c488   Omar Sandoval   Btrfs: don't inva...
2407
  		d_invalidate(dentry);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2408
2409
  		btrfs_invalidate_inodes(dest);
  		d_delete(dentry);
61155aa04   David Sterba   btrfs: assert tha...
2410
  		ASSERT(dest->send_in_progress == 0);
fa6ac8765   Liu Bo   Btrfs: fix cleane...
2411
2412
  
  		/* the last ref */
57cdc8db2   David Sterba   btrfs: cleanup in...
2413
2414
2415
  		if (dest->ino_cache_inode) {
  			iput(dest->ino_cache_inode);
  			dest->ino_cache_inode = NULL;
fa6ac8765   Liu Bo   Btrfs: fix cleane...
2416
  		}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2417
2418
2419
2420
  	}
  out_dput:
  	dput(dentry);
  out_unlock_dir:
5955102c9   Al Viro   wrappers for ->i_...
2421
  	inode_unlock(dir);
002354112   Al Viro   restore killabili...
2422
  out_drop_write:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
2423
  	mnt_drop_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2424
2425
2426
2427
  out:
  	kfree(vol_args);
  	return err;
  }
1e701a329   Chris Mason   Btrfs: add new de...
2428
  static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2429
  {
496ad9aa8   Al Viro   new helper: file_...
2430
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2431
  	struct btrfs_root *root = BTRFS_I(inode)->root;
1e701a329   Chris Mason   Btrfs: add new de...
2432
  	struct btrfs_ioctl_defrag_range_args *range;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2433
  	int ret;
25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2434
2435
2436
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
b83cc9693   Li Zefan   Btrfs: Add readon...
2437

25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2438
2439
2440
  	if (btrfs_root_readonly(root)) {
  		ret = -EROFS;
  		goto out;
5ac00addc   Stefan Behrens   Btrfs: disallow m...
2441
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2442
2443
2444
  
  	switch (inode->i_mode & S_IFMT) {
  	case S_IFDIR:
e441d54de   Chris Mason   Btrfs: add permis...
2445
2446
2447
2448
  		if (!capable(CAP_SYS_ADMIN)) {
  			ret = -EPERM;
  			goto out;
  		}
de78b51a2   Eric Sandeen   btrfs: remove cac...
2449
  		ret = btrfs_defrag_root(root);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2450
2451
  		break;
  	case S_IFREG:
e441d54de   Chris Mason   Btrfs: add permis...
2452
2453
2454
2455
  		if (!(file->f_mode & FMODE_WRITE)) {
  			ret = -EINVAL;
  			goto out;
  		}
1e701a329   Chris Mason   Btrfs: add new de...
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
  
  		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...
2468
  				goto out;
1e701a329   Chris Mason   Btrfs: add new de...
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
  			}
  			/* 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_...
2479
  		ret = btrfs_defrag_file(file_inode(file), file,
4cb5300bc   Chris Mason   Btrfs: add mount ...
2480
2481
2482
  					range, 0, 0);
  		if (ret > 0)
  			ret = 0;
1e701a329   Chris Mason   Btrfs: add new de...
2483
  		kfree(range);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2484
  		break;
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
2485
2486
  	default:
  		ret = -EINVAL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2487
  	}
e441d54de   Chris Mason   Btrfs: add permis...
2488
  out:
25122d15e   Ilya Dryomov   Btrfs: reorder lo...
2489
  	mnt_drop_write_file(file);
e441d54de   Chris Mason   Btrfs: add permis...
2490
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2491
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
2492
  static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2493
2494
2495
  {
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2496
2497
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
171938e52   David Sterba   btrfs: track excl...
2498
  	if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags))
e57138b3e   Anand Jain   btrfs: return btr...
2499
  		return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2500

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2501
  	mutex_lock(&fs_info->volume_mutex);
dae7b665c   Li Zefan   btrfs: use memdup...
2502
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2503
2504
2505
2506
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
  		goto out;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2507

5516e5957   Mark Fasheh   Btrfs: Null termi...
2508
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
2509
  	ret = btrfs_init_new_device(fs_info, vol_args->name);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2510

43d207616   Anand Jain   btrfs: device add...
2511
  	if (!ret)
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2512
  		btrfs_info(fs_info, "disk added %s", vol_args->name);
43d207616   Anand Jain   btrfs: device add...
2513

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2514
  	kfree(vol_args);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2515
  out:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2516
  	mutex_unlock(&fs_info->volume_mutex);
171938e52   David Sterba   btrfs: track excl...
2517
  	clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2518
2519
  	return ret;
  }
6b526ed70   Anand Jain   btrfs: introduce ...
2520
  static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2521
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2522
2523
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
6b526ed70   Anand Jain   btrfs: introduce ...
2524
  	struct btrfs_ioctl_vol_args_v2 *vol_args;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2525
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2526
2527
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
da24927b1   Miao Xie   Btrfs: get write ...
2528
2529
2530
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2531

dae7b665c   Li Zefan   btrfs: use memdup...
2532
  	vol_args = memdup_user(arg, sizeof(*vol_args));
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2533
2534
  	if (IS_ERR(vol_args)) {
  		ret = PTR_ERR(vol_args);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
2535
  		goto err_drop;
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
2536
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2537

6b526ed70   Anand Jain   btrfs: introduce ...
2538
  	/* Check for compatibility reject unknown flags */
5f7e3b5b9   Omar Sandoval   Btrfs: fix memory...
2539
2540
2541
2542
  	if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED) {
  		ret = -EOPNOTSUPP;
  		goto out;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2543

171938e52   David Sterba   btrfs: track excl...
2544
  	if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
183860f6a   Anand Jain   btrfs: device del...
2545
2546
2547
  		ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
  		goto out;
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2548
  	mutex_lock(&fs_info->volume_mutex);
735654ea9   David Sterba   btrfs: rename fla...
2549
  	if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID) {
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
2550
  		ret = btrfs_rm_device(fs_info, NULL, vol_args->devid);
6b526ed70   Anand Jain   btrfs: introduce ...
2551
2552
  	} else {
  		vol_args->name[BTRFS_SUBVOL_NAME_MAX] = '\0';
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
2553
  		ret = btrfs_rm_device(fs_info, vol_args->name, 0);
6b526ed70   Anand Jain   btrfs: introduce ...
2554
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2555
  	mutex_unlock(&fs_info->volume_mutex);
171938e52   David Sterba   btrfs: track excl...
2556
  	clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
183860f6a   Anand Jain   btrfs: device del...
2557

6b526ed70   Anand Jain   btrfs: introduce ...
2558
  	if (!ret) {
735654ea9   David Sterba   btrfs: rename fla...
2559
  		if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID)
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2560
  			btrfs_info(fs_info, "device deleted: id %llu",
6b526ed70   Anand Jain   btrfs: introduce ...
2561
2562
  					vol_args->devid);
  		else
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2563
  			btrfs_info(fs_info, "device deleted: %s",
6b526ed70   Anand Jain   btrfs: introduce ...
2564
2565
  					vol_args->name);
  	}
183860f6a   Anand Jain   btrfs: device del...
2566
2567
  out:
  	kfree(vol_args);
c47ca32d3   Dan Carpenter   Btrfs: kfree()ing...
2568
  err_drop:
4ac20c70b   Ilya Dryomov   Btrfs: fix unlock...
2569
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2570
2571
  	return ret;
  }
da24927b1   Miao Xie   Btrfs: get write ...
2572
  static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2573
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2574
2575
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2576
2577
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
2578
2579
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
da24927b1   Miao Xie   Btrfs: get write ...
2580
2581
2582
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
c146afad2   Yan Zheng   Btrfs: mount ro a...
2583

171938e52   David Sterba   btrfs: track excl...
2584
  	if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
183860f6a   Anand Jain   btrfs: device del...
2585
  		ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2586
2587
2588
2589
2590
2591
  		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...
2592
2593
  		goto out;
  	}
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2594
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2595
  	mutex_lock(&fs_info->volume_mutex);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
2596
  	ret = btrfs_rm_device(fs_info, vol_args->name, 0);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2597
  	mutex_unlock(&fs_info->volume_mutex);
183860f6a   Anand Jain   btrfs: device del...
2598

ec95d4917   Anand Jain   btrfs: device del...
2599
  	if (!ret)
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2600
  		btrfs_info(fs_info, "disk deleted %s", vol_args->name);
183860f6a   Anand Jain   btrfs: device del...
2601
  	kfree(vol_args);
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2602
  out:
171938e52   David Sterba   btrfs: track excl...
2603
  	clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2604
  out_drop_write:
4ac20c70b   Ilya Dryomov   Btrfs: fix unlock...
2605
  	mnt_drop_write_file(file);
58d7bbf81   David Sterba   btrfs: ioctl: reo...
2606

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2607
2608
  	return ret;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
2609
2610
  static long btrfs_ioctl_fs_info(struct btrfs_fs_info *fs_info,
  				void __user *arg)
475f63874   Jan Schmidt   btrfs: new ioctls...
2611
  {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2612
  	struct btrfs_ioctl_fs_info_args *fi_args;
475f63874   Jan Schmidt   btrfs: new ioctls...
2613
  	struct btrfs_device *device;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2614
  	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
027ed2f00   Li Zefan   Btrfs: avoid stac...
2615
  	int ret = 0;
475f63874   Jan Schmidt   btrfs: new ioctls...
2616

027ed2f00   Li Zefan   Btrfs: avoid stac...
2617
2618
2619
  	fi_args = kzalloc(sizeof(*fi_args), GFP_KERNEL);
  	if (!fi_args)
  		return -ENOMEM;
f71717502   Filipe David Borba Manana   Btrfs: fix race c...
2620
  	mutex_lock(&fs_devices->device_list_mutex);
027ed2f00   Li Zefan   Btrfs: avoid stac...
2621
  	fi_args->num_devices = fs_devices->num_devices;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2622
  	memcpy(&fi_args->fsid, fs_info->fsid, sizeof(fi_args->fsid));
475f63874   Jan Schmidt   btrfs: new ioctls...
2623

d7641a49a   Byongho Lee   btrfs: replace un...
2624
  	list_for_each_entry(device, &fs_devices->devices, dev_list) {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2625
2626
  		if (device->devid > fi_args->max_id)
  			fi_args->max_id = device->devid;
475f63874   Jan Schmidt   btrfs: new ioctls...
2627
2628
  	}
  	mutex_unlock(&fs_devices->device_list_mutex);
bea7eafdb   Omar Sandoval   Btrfs: fix incorr...
2629
2630
2631
  	fi_args->nodesize = fs_info->nodesize;
  	fi_args->sectorsize = fs_info->sectorsize;
  	fi_args->clone_alignment = fs_info->sectorsize;
80a773fbf   David Sterba   btrfs: retrieve m...
2632

027ed2f00   Li Zefan   Btrfs: avoid stac...
2633
2634
  	if (copy_to_user(arg, fi_args, sizeof(*fi_args)))
  		ret = -EFAULT;
475f63874   Jan Schmidt   btrfs: new ioctls...
2635

027ed2f00   Li Zefan   Btrfs: avoid stac...
2636
2637
  	kfree(fi_args);
  	return ret;
475f63874   Jan Schmidt   btrfs: new ioctls...
2638
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
2639
2640
  static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
  				 void __user *arg)
475f63874   Jan Schmidt   btrfs: new ioctls...
2641
2642
2643
  {
  	struct btrfs_ioctl_dev_info_args *di_args;
  	struct btrfs_device *dev;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2644
  	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
475f63874   Jan Schmidt   btrfs: new ioctls...
2645
2646
  	int ret = 0;
  	char *s_uuid = NULL;
475f63874   Jan Schmidt   btrfs: new ioctls...
2647

475f63874   Jan Schmidt   btrfs: new ioctls...
2648
2649
2650
  	di_args = memdup_user(arg, sizeof(*di_args));
  	if (IS_ERR(di_args))
  		return PTR_ERR(di_args);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
2651
  	if (!btrfs_is_empty_uuid(di_args->uuid))
475f63874   Jan Schmidt   btrfs: new ioctls...
2652
2653
2654
  		s_uuid = di_args->uuid;
  
  	mutex_lock(&fs_devices->device_list_mutex);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
2655
  	dev = btrfs_find_device(fs_info, di_args->devid, s_uuid, NULL);
475f63874   Jan Schmidt   btrfs: new ioctls...
2656
2657
2658
2659
2660
2661
2662
  
  	if (!dev) {
  		ret = -ENODEV;
  		goto out;
  	}
  
  	di_args->devid = dev->devid;
7cc8e58d5   Miao Xie   Btrfs: fix unprot...
2663
2664
  	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...
2665
  	memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
a27202fbe   Jim Meyering   Btrfs: NUL-termin...
2666
  	if (dev->name) {
606686eea   Josef Bacik   Btrfs: use rcu to...
2667
2668
2669
2670
2671
2672
  		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...
2673
2674
  		di_args->path[sizeof(di_args->path) - 1] = 0;
  	} else {
99ba55ad6   Stefan Behrens   Btrfs: fix btrfs_...
2675
  		di_args->path[0] = '\0';
a27202fbe   Jim Meyering   Btrfs: NUL-termin...
2676
  	}
475f63874   Jan Schmidt   btrfs: new ioctls...
2677
2678
  
  out:
55793c0d0   David Sterba   btrfs: read entir...
2679
  	mutex_unlock(&fs_devices->device_list_mutex);
475f63874   Jan Schmidt   btrfs: new ioctls...
2680
2681
2682
2683
2684
2685
  	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...
2686
  static struct page *extent_same_get_page(struct inode *inode, pgoff_t index)
416161db9   Mark Fasheh   btrfs: offline de...
2687
2688
  {
  	struct page *page;
416161db9   Mark Fasheh   btrfs: offline de...
2689

416161db9   Mark Fasheh   btrfs: offline de...
2690
2691
  	page = grab_cache_page(inode->i_mapping, index);
  	if (!page)
313140023   Filipe Manana   Btrfs: fix page r...
2692
  		return ERR_PTR(-ENOMEM);
416161db9   Mark Fasheh   btrfs: offline de...
2693
2694
  
  	if (!PageUptodate(page)) {
313140023   Filipe Manana   Btrfs: fix page r...
2695
2696
2697
2698
2699
  		int ret;
  
  		ret = btrfs_readpage(NULL, page);
  		if (ret)
  			return ERR_PTR(ret);
416161db9   Mark Fasheh   btrfs: offline de...
2700
2701
2702
  		lock_page(page);
  		if (!PageUptodate(page)) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2703
  			put_page(page);
313140023   Filipe Manana   Btrfs: fix page r...
2704
2705
2706
2707
  			return ERR_PTR(-EIO);
  		}
  		if (page->mapping != inode->i_mapping) {
  			unlock_page(page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2708
  			put_page(page);
313140023   Filipe Manana   Btrfs: fix page r...
2709
  			return ERR_PTR(-EAGAIN);
416161db9   Mark Fasheh   btrfs: offline de...
2710
2711
  		}
  	}
416161db9   Mark Fasheh   btrfs: offline de...
2712
2713
2714
  
  	return page;
  }
f44146020   Mark Fasheh   btrfs: fix deadlo...
2715
2716
2717
2718
  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...
2719
  	pgoff_t index = off >> PAGE_SHIFT;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2720
2721
  
  	for (i = 0; i < num_pages; i++) {
313140023   Filipe Manana   Btrfs: fix page r...
2722
  again:
f44146020   Mark Fasheh   btrfs: fix deadlo...
2723
  		pages[i] = extent_same_get_page(inode, index + i);
313140023   Filipe Manana   Btrfs: fix page r...
2724
2725
2726
2727
2728
2729
2730
2731
  		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...
2732
2733
2734
  	}
  	return 0;
  }
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2735
2736
  static int lock_extent_range(struct inode *inode, u64 off, u64 len,
  			     bool retry_range_locking)
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2737
  {
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2738
2739
2740
2741
2742
2743
2744
2745
  	/*
  	 * 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...
2746
2747
2748
2749
2750
  	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...
2751
2752
2753
  		if ((!ordered ||
  		     ordered->file_offset + ordered->len <= off ||
  		     ordered->file_offset >= off + len) &&
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2754
  		    !test_range_bit(&BTRFS_I(inode)->io_tree, off,
ff5df9b88   Filipe Manana   Btrfs: ioctl, don...
2755
2756
2757
  				    off + len - 1, EXTENT_DELALLOC, 0, NULL)) {
  			if (ordered)
  				btrfs_put_ordered_extent(ordered);
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2758
  			break;
ff5df9b88   Filipe Manana   Btrfs: ioctl, don...
2759
  		}
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2760
2761
2762
  		unlock_extent(&BTRFS_I(inode)->io_tree, off, off + len - 1);
  		if (ordered)
  			btrfs_put_ordered_extent(ordered);
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2763
2764
  		if (!retry_range_locking)
  			return -EAGAIN;
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2765
2766
  		btrfs_wait_ordered_range(inode, off, len);
  	}
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2767
  	return 0;
77fe20dc6   Mark Fasheh   btrfs: abtract ou...
2768
  }
f44146020   Mark Fasheh   btrfs: fix deadlo...
2769
  static void btrfs_double_inode_unlock(struct inode *inode1, struct inode *inode2)
416161db9   Mark Fasheh   btrfs: offline de...
2770
  {
5955102c9   Al Viro   wrappers for ->i_...
2771
2772
  	inode_unlock(inode1);
  	inode_unlock(inode2);
416161db9   Mark Fasheh   btrfs: offline de...
2773
  }
f44146020   Mark Fasheh   btrfs: fix deadlo...
2774
2775
2776
2777
  static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2)
  {
  	if (inode1 < inode2)
  		swap(inode1, inode2);
5955102c9   Al Viro   wrappers for ->i_...
2778
2779
  	inode_lock_nested(inode1, I_MUTEX_PARENT);
  	inode_lock_nested(inode2, I_MUTEX_CHILD);
f44146020   Mark Fasheh   btrfs: fix deadlo...
2780
2781
2782
2783
2784
2785
2786
2787
  }
  
  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...
2788
2789
2790
  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...
2791
  {
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2792
  	int ret;
416161db9   Mark Fasheh   btrfs: offline de...
2793
2794
2795
2796
  	if (inode1 < inode2) {
  		swap(inode1, inode2);
  		swap(loff1, loff2);
  	}
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2797
2798
2799
2800
2801
2802
2803
2804
  	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...
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
  }
  
  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...
2820
2821
  		if (pg) {
  			unlock_page(pg);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2822
  			put_page(pg);
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2823
  		}
f44146020   Mark Fasheh   btrfs: fix deadlo...
2824
  		pg = cmp->dst_pages[i];
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2825
2826
  		if (pg) {
  			unlock_page(pg);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2827
  			put_page(pg);
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2828
  		}
f44146020   Mark Fasheh   btrfs: fix deadlo...
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
  	}
  	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...
2839
  	int num_pages = PAGE_ALIGN(len) >> PAGE_SHIFT;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2840
2841
2842
2843
2844
2845
2846
2847
  	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 ...
2848
2849
  	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...
2850
2851
2852
2853
  	if (!src_pgarr || !dst_pgarr) {
  		kfree(src_pgarr);
  		kfree(dst_pgarr);
  		return -ENOMEM;
416161db9   Mark Fasheh   btrfs: offline de...
2854
  	}
f44146020   Mark Fasheh   btrfs: fix deadlo...
2855
2856
2857
  	cmp->num_pages = num_pages;
  	cmp->src_pages = src_pgarr;
  	cmp->dst_pages = dst_pgarr;
b1517622f   Filipe Manana   Btrfs: fix deadlo...
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
  	/*
  	 * If deduping ranges in the same inode, locking rules make it mandatory
  	 * to always lock pages in ascending order to avoid deadlocks with
  	 * concurrent tasks (such as starting writeback/delalloc).
  	 */
  	if (src == dst && dst_loff < loff) {
  		swap(src_pgarr, dst_pgarr);
  		swap(loff, dst_loff);
  	}
  
  	ret = gather_extent_pages(src, src_pgarr, cmp->num_pages, loff);
f44146020   Mark Fasheh   btrfs: fix deadlo...
2869
2870
  	if (ret)
  		goto out;
b1517622f   Filipe Manana   Btrfs: fix deadlo...
2871
  	ret = gather_extent_pages(dst, dst_pgarr, cmp->num_pages, dst_loff);
f44146020   Mark Fasheh   btrfs: fix deadlo...
2872
2873
2874
2875
  
  out:
  	if (ret)
  		btrfs_cmp_data_free(cmp);
78ad4ce01   Naohiro Aota   btrfs: propagate ...
2876
  	return ret;
416161db9   Mark Fasheh   btrfs: offline de...
2877
  }
1a287cfea   David Sterba   btrfs: remove unu...
2878
  static int btrfs_cmp_data(u64 len, struct cmp_pages *cmp)
416161db9   Mark Fasheh   btrfs: offline de...
2879
2880
  {
  	int ret = 0;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2881
  	int i;
416161db9   Mark Fasheh   btrfs: offline de...
2882
  	struct page *src_page, *dst_page;
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2883
  	unsigned int cmp_len = PAGE_SIZE;
416161db9   Mark Fasheh   btrfs: offline de...
2884
  	void *addr, *dst_addr;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2885
  	i = 0;
416161db9   Mark Fasheh   btrfs: offline de...
2886
  	while (len) {
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
2887
  		if (len < PAGE_SIZE)
416161db9   Mark Fasheh   btrfs: offline de...
2888
  			cmp_len = len;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2889
2890
2891
2892
  		BUG_ON(i >= cmp->num_pages);
  
  		src_page = cmp->src_pages[i];
  		dst_page = cmp->dst_pages[i];
e0bd70c67   Filipe Manana   Btrfs: fix invali...
2893
2894
  		ASSERT(PageLocked(src_page));
  		ASSERT(PageLocked(dst_page));
f44146020   Mark Fasheh   btrfs: fix deadlo...
2895

416161db9   Mark Fasheh   btrfs: offline de...
2896
2897
2898
2899
2900
2901
2902
  		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...
2903
  			ret = -EBADE;
416161db9   Mark Fasheh   btrfs: offline de...
2904
2905
2906
  
  		kunmap_atomic(addr);
  		kunmap_atomic(dst_addr);
416161db9   Mark Fasheh   btrfs: offline de...
2907
2908
2909
  
  		if (ret)
  			break;
416161db9   Mark Fasheh   btrfs: offline de...
2910
  		len -= cmp_len;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2911
  		i++;
416161db9   Mark Fasheh   btrfs: offline de...
2912
2913
2914
2915
  	}
  
  	return ret;
  }
e1d227a42   Mark Fasheh   btrfs: Handle una...
2916
2917
  static int extent_same_check_offsets(struct inode *inode, u64 off, u64 *plen,
  				     u64 olen)
416161db9   Mark Fasheh   btrfs: offline de...
2918
  {
e1d227a42   Mark Fasheh   btrfs: Handle una...
2919
  	u64 len = *plen;
416161db9   Mark Fasheh   btrfs: offline de...
2920
  	u64 bs = BTRFS_I(inode)->root->fs_info->sb->s_blocksize;
e1d227a42   Mark Fasheh   btrfs: Handle una...
2921
  	if (off + olen > inode->i_size || off + olen < off)
416161db9   Mark Fasheh   btrfs: offline de...
2922
  		return -EINVAL;
e1d227a42   Mark Fasheh   btrfs: Handle una...
2923
2924
2925
2926
  
  	/* 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...
2927
2928
2929
2930
2931
2932
  	/* 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...
2933
  static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen,
416161db9   Mark Fasheh   btrfs: offline de...
2934
2935
2936
  			     struct inode *dst, u64 dst_loff)
  {
  	int ret;
e1d227a42   Mark Fasheh   btrfs: Handle una...
2937
  	u64 len = olen;
f44146020   Mark Fasheh   btrfs: fix deadlo...
2938
  	struct cmp_pages cmp;
fc4badd9f   Omar Sandoval   Btrfs: refactor b...
2939
  	bool same_inode = (src == dst);
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
2940
2941
  	u64 same_lock_start = 0;
  	u64 same_lock_len = 0;
416161db9   Mark Fasheh   btrfs: offline de...
2942

113e82838   Filipe Manana   Btrfs: fix inode ...
2943
2944
  	if (len == 0)
  		return 0;
fc4badd9f   Omar Sandoval   Btrfs: refactor b...
2945
  	if (same_inode)
5955102c9   Al Viro   wrappers for ->i_...
2946
  		inode_lock(src);
fc4badd9f   Omar Sandoval   Btrfs: refactor b...
2947
2948
  	else
  		btrfs_double_inode_lock(src, dst);
416161db9   Mark Fasheh   btrfs: offline de...
2949

fc4badd9f   Omar Sandoval   Btrfs: refactor b...
2950
2951
2952
  	ret = extent_same_check_offsets(src, loff, &len, olen);
  	if (ret)
  		goto out_unlock;
416161db9   Mark Fasheh   btrfs: offline de...
2953

fc4badd9f   Omar Sandoval   Btrfs: refactor b...
2954
2955
2956
2957
2958
  	ret = extent_same_check_offsets(dst, dst_loff, &len, olen);
  	if (ret)
  		goto out_unlock;
  
  	if (same_inode) {
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
  		/*
  		 * 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;
ae3968b41   Filipe Manana   Btrfs: fix data c...
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
  	} else {
  		/*
  		 * If the source and destination inodes are different, the
  		 * source's range end offset matches the source's i_size, that
  		 * i_size is not a multiple of the sector size, and the
  		 * destination range does not go past the destination's i_size,
  		 * we must round down the length to the nearest sector size
  		 * multiple. If we don't do this adjustment we end replacing
  		 * with zeroes the bytes in the range that starts at the
  		 * deduplication range's end offset and ends at the next sector
  		 * size multiple.
  		 */
  		if (loff + olen == i_size_read(src) &&
  		    dst_loff + len < i_size_read(dst)) {
  			const u64 sz = BTRFS_I(src)->root->fs_info->sectorsize;
  
  			len = round_down(i_size_read(src), sz) - loff;
c7a082fb6   Filipe Manana   Btrfs: fix infini...
3003
3004
  			if (len == 0)
  				return 0;
ae3968b41   Filipe Manana   Btrfs: fix data c...
3005
3006
  			olen = len;
  		}
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3007
  	}
416161db9   Mark Fasheh   btrfs: offline de...
3008
3009
3010
3011
3012
3013
3014
  
  	/* 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...
3015
  again:
f44146020   Mark Fasheh   btrfs: fix deadlo...
3016
3017
3018
  	ret = btrfs_cmp_data_prepare(src, loff, dst, dst_loff, olen, &cmp);
  	if (ret)
  		goto out_unlock;
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3019
  	if (same_inode)
e0bd70c67   Filipe Manana   Btrfs: fix invali...
3020
3021
  		ret = lock_extent_range(src, same_lock_start, same_lock_len,
  					false);
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3022
  	else
e0bd70c67   Filipe Manana   Btrfs: fix invali...
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
3053
  		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...
3054

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

0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3060
3061
3062
3063
3064
  	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...
3065
3066
  
  	btrfs_cmp_data_free(&cmp);
416161db9   Mark Fasheh   btrfs: offline de...
3067
  out_unlock:
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3068
  	if (same_inode)
5955102c9   Al Viro   wrappers for ->i_...
3069
  		inode_unlock(src);
0efa9f48c   Mark Fasheh   btrfs: allow dedu...
3070
3071
  	else
  		btrfs_double_inode_unlock(src, dst);
416161db9   Mark Fasheh   btrfs: offline de...
3072
3073
3074
  
  	return ret;
  }
ee22184b5   Byongho Lee   Btrfs: use linux/...
3075
  #define BTRFS_MAX_DEDUPE_LEN	SZ_16M
416161db9   Mark Fasheh   btrfs: offline de...
3076

2b3909f8a   Darrick J. Wong   btrfs: use new de...
3077
3078
  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...
3079
  {
2b3909f8a   Darrick J. Wong   btrfs: use new de...
3080
3081
  	struct inode *src = file_inode(src_file);
  	struct inode *dst = file_inode(dst_file);
416161db9   Mark Fasheh   btrfs: offline de...
3082
  	u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize;
2b3909f8a   Darrick J. Wong   btrfs: use new de...
3083
  	ssize_t res;
416161db9   Mark Fasheh   btrfs: offline de...
3084

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

09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
3088
  	if (WARN_ON_ONCE(bs < PAGE_SIZE)) {
416161db9   Mark Fasheh   btrfs: offline de...
3089
3090
3091
3092
3093
  		/*
  		 * 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...
3094
  		return -EINVAL;
416161db9   Mark Fasheh   btrfs: offline de...
3095
  	}
2b3909f8a   Darrick J. Wong   btrfs: use new de...
3096
3097
3098
3099
  	res = btrfs_extent_same(src, loff, olen, dst, dst_loff);
  	if (res)
  		return res;
  	return olen;
416161db9   Mark Fasheh   btrfs: offline de...
3100
  }
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3101
3102
3103
3104
  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...
3105
3106
  				     const u64 olen,
  				     int no_time_update)
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3107
3108
3109
3110
3111
  {
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret;
  
  	inode_inc_iversion(inode);
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3112
  	if (!no_time_update)
c2050a454   Deepa Dinamani   fs: Replace curre...
3113
  		inode->i_mtime = inode->i_ctime = current_time(inode);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3114
3115
3116
3117
3118
3119
3120
  	/*
  	 * 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)
6ef06d279   Nikolay Borisov   btrfs: Make btrfs...
3121
  		btrfs_i_size_write(BTRFS_I(inode), endoff);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3122
3123
3124
  
  	ret = btrfs_update_inode(trans, root, inode);
  	if (ret) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
3125
  		btrfs_abort_transaction(trans, ret);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3126
  		btrfs_end_transaction(trans);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3127
3128
  		goto out;
  	}
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3129
  	ret = btrfs_end_transaction(trans);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3130
3131
3132
  out:
  	return ret;
  }
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3133
  static void clone_update_extent_map(struct btrfs_inode *inode,
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3134
3135
  				    const struct btrfs_trans_handle *trans,
  				    const struct btrfs_path *path,
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3136
3137
3138
  				    const u64 hole_offset,
  				    const u64 hole_len)
  {
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3139
  	struct extent_map_tree *em_tree = &inode->extent_tree;
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3140
3141
3142
3143
3144
  	struct extent_map *em;
  	int ret;
  
  	em = alloc_extent_map();
  	if (!em) {
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3145
  		set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags);
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3146
3147
  		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);
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3153
  		btrfs_extent_item_to_extent_map(inode, path, fi, false, em);
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3154
3155
3156
3157
  		em->generation = -1;
  		if (btrfs_file_extent_type(path->nodes[0], fi) ==
  		    BTRFS_FILE_EXTENT_INLINE)
  			set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3158
  					&inode->runtime_flags);
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
  	} 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;
  		}
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3179
  		btrfs_drop_extent_cache(inode, em->start,
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3180
3181
  					em->start + em->len - 1, 0);
  	}
ee39b432b   David Sterba   btrfs: remove unl...
3182
  	if (ret)
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3183
  		set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags);
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3184
  }
8039d87d9   Filipe Manana   Btrfs: fix file c...
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
  /*
   * 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.
   */
4a0ab9d71   David Sterba   btrfs: remove unu...
3210
  static int clone_copy_inline_extent(struct inode *dst,
8039d87d9   Filipe Manana   Btrfs: fix file c...
3211
3212
3213
3214
3215
3216
3217
3218
3219
  				    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)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3220
  	struct btrfs_fs_info *fs_info = btrfs_sb(dst->i_sb);
8039d87d9   Filipe Manana   Btrfs: fix file c...
3221
3222
  	struct btrfs_root *root = BTRFS_I(dst)->root;
  	const u64 aligned_end = ALIGN(new_key->offset + datal,
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3223
  				      fs_info->sectorsize);
8039d87d9   Filipe Manana   Btrfs: fix file c...
3224
3225
3226
3227
3228
  	int ret;
  	struct btrfs_key key;
  
  	if (new_key->offset > 0)
  		return -EOPNOTSUPP;
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
3229
  	key.objectid = btrfs_ino(BTRFS_I(dst));
8039d87d9   Filipe Manana   Btrfs: fix file c...
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
  	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]);
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
3244
  		if (key.objectid == btrfs_ino(BTRFS_I(dst)) &&
8039d87d9   Filipe Manana   Btrfs: fix file c...
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
  		    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]);
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
3278
  			if (key.objectid == btrfs_ino(BTRFS_I(dst)) &&
8039d87d9   Filipe Manana   Btrfs: fix file c...
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
  			    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...
3327
3328
3329
3330
3331
3332
3333
  /**
   * 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...
3334
   * @olen_aligned: Block-aligned value of olen
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3335
   * @destoff: Offset within @inode to start clone
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3336
   * @no_time_update: Whether to update mtime/ctime on the target inode
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3337
3338
   */
  static int btrfs_clone(struct inode *src, struct inode *inode,
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3339
  		       const u64 off, const u64 olen, const u64 olen_aligned,
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3340
  		       const u64 destoff, int no_time_update)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3341
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3342
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3343
  	struct btrfs_root *root = BTRFS_I(inode)->root;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3344
  	struct btrfs_path *path = NULL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3345
  	struct extent_buffer *leaf;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3346
3347
  	struct btrfs_trans_handle *trans;
  	char *buf = NULL;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3348
  	struct btrfs_key key;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3349
3350
  	u32 nritems;
  	int slot;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3351
  	int ret;
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3352
  	const u64 len = olen_aligned;
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3353
  	u64 last_dest_end = destoff;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3354
3355
  
  	ret = -ENOMEM;
752ade68c   Michal Hocko   treewide: use kv[...
3356
3357
3358
  	buf = kvmalloc(fs_info->nodesize, GFP_KERNEL);
  	if (!buf)
  		return ret;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3359
3360
3361
  
  	path = btrfs_alloc_path();
  	if (!path) {
153519559   David Sterba   btrfs: clone: use...
3362
  		kvfree(buf);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3363
  		return ret;
d525e8ab0   Li Zefan   Btrfs: add dummy ...
3364
  	}
e4058b54d   David Sterba   btrfs: cleanup, u...
3365
  	path->reada = READA_FORWARD;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3366
  	/* clone data */
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
3367
  	key.objectid = btrfs_ino(BTRFS_I(src));
ae01a0abf   Yan Zheng   Btrfs: Update clo...
3368
  	key.type = BTRFS_EXTENT_DATA_KEY;
2c463823c   Filipe Manana   Btrfs: avoid visi...
3369
  	key.offset = off;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3370
3371
  
  	while (1) {
de249e66a   Chris Mason   Btrfs: fix uninit...
3372
  		u64 next_key_min_offset = key.offset + 1;
df858e767   Filipe Manana   Btrfs: fix range ...
3373

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3374
3375
3376
3377
  		/*
  		 * note the key will change type as we walk through the
  		 * tree.
  		 */
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3378
  		path->leave_spinning = 1;
362a20c5e   David Sterba   btrfs: allow cros...
3379
3380
  		ret = btrfs_search_slot(NULL, BTRFS_I(src)->root, &key, path,
  				0, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3381
3382
  		if (ret < 0)
  			goto out;
2c463823c   Filipe Manana   Btrfs: avoid visi...
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
  		/*
  		 * 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 ...
3394

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

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

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

2c463823c   Filipe Manana   Btrfs: avoid visi...
3441
3442
3443
3444
3445
3446
  			/*
  			 * 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...
3447
3448
  				path->slots[0]++;
  				goto process_slot;
2c463823c   Filipe Manana   Btrfs: avoid visi...
3449
3450
  			} else if (key.offset >= off + len) {
  				break;
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3451
  			}
df858e767   Filipe Manana   Btrfs: fix range ...
3452
  			next_key_min_offset = key.offset + datal;
e4355f34e   Filipe David Borba Manana   Btrfs: faster fil...
3453
3454
3455
3456
3457
3458
3459
  			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...
3460

31840ae1a   Zheng Yan   Btrfs: Full back ...
3461
  			memcpy(&new_key, &key, sizeof(new_key));
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
3462
  			new_key.objectid = btrfs_ino(BTRFS_I(inode));
4d728ec7a   Li Zefan   Btrfs: Fix file c...
3463
3464
3465
3466
  			if (off <= key.offset)
  				new_key.offset = key.offset + destoff - off;
  			else
  				new_key.offset = destoff;
31840ae1a   Zheng Yan   Btrfs: Full back ...
3467

b6f3409b2   Sage Weil   Btrfs: reserve su...
3468
  			/*
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
  			 * 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...
3481
3482
3483
3484
3485
  			 * 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 ...
3486
3487
3488
3489
  			if (IS_ERR(trans)) {
  				ret = PTR_ERR(trans);
  				goto out;
  			}
c8a894d77   Chris Mason   Btrfs: fix the fi...
3490
3491
  			if (type == BTRFS_FILE_EXTENT_REG ||
  			    type == BTRFS_FILE_EXTENT_PREALLOC) {
d72c0842f   Li Zefan   Btrfs: calc file ...
3492
3493
3494
3495
  				/*
  				 *    a  | --- range to clone ---|  b
  				 * | ------------- extent ------------- |
  				 */
939155841   Antonio Ospite   trivial: fs/btrfs...
3496
  				/* subtract range b */
d72c0842f   Li Zefan   Btrfs: calc file ...
3497
3498
  				if (key.offset + datal > off + len)
  					datal = off + len - key.offset;
939155841   Antonio Ospite   trivial: fs/btrfs...
3499
  				/* subtract range a */
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3500
3501
3502
3503
  				if (off > key.offset) {
  					datao += off - key.offset;
  					datal -= off - key.offset;
  				}
5dc562c54   Josef Bacik   Btrfs: turbo char...
3504
  				ret = btrfs_drop_extents(trans, root, inode,
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3505
  							 drop_start,
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3506
  							 new_key.offset + datal,
2671485d3   Josef Bacik   Btrfs: remove unu...
3507
  							 1);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3508
  				if (ret) {
3f9e3df8d   David Sterba   btrfs: replace er...
3509
  					if (ret != -EOPNOTSUPP)
00fdf13a2   Liu Bo   Btrfs: fix a cras...
3510
  						btrfs_abort_transaction(trans,
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
3511
  									ret);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3512
  					btrfs_end_transaction(trans);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3513
3514
  					goto out;
  				}
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3515

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

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

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

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3542
3543
  				if (disko) {
  					inode_add_bytes(inode, datal);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
3544
3545
  					ret = btrfs_inc_extent_ref(trans,
  							fs_info,
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
3546
3547
  							disko, diskl, 0,
  							root->root_key.objectid,
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
3548
  							btrfs_ino(BTRFS_I(inode)),
b06c4bf5c   Filipe Manana   Btrfs: fix regres...
3549
  							new_key.offset - datao);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3550
3551
  					if (ret) {
  						btrfs_abort_transaction(trans,
79787eaab   Jeff Mahoney   btrfs: replace ma...
3552
  									ret);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3553
  						btrfs_end_transaction(trans);
79787eaab   Jeff Mahoney   btrfs: replace ma...
3554
3555
3556
  						goto out;
  
  					}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3557
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3558
3559
3560
  			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
  				u64 skip = 0;
  				u64 trim = 0;
ed9587626   Filipe Manana   Btrfs: fix file c...
3561

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3562
3563
3564
3565
  				if (off > key.offset) {
  					skip = off - key.offset;
  					new_key.offset += skip;
  				}
d397712bc   Chris Mason   Btrfs: Fix checkp...
3566

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

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3570
  				if (comp && (skip || trim)) {
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3571
  					ret = -EINVAL;
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3572
  					btrfs_end_transaction(trans);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3573
3574
3575
3576
  					goto out;
  				}
  				size -= skip + trim;
  				datal -= skip + trim;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
3577

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

7ffbb598a   Filipe Manana   Btrfs: make fsync...
3595
3596
  			/* If we have an implicit hole (NO_HOLES feature). */
  			if (drop_start < new_key.offset)
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3597
  				clone_update_extent_map(BTRFS_I(inode), trans,
14f597963   Filipe Manana   Btrfs: fix use-af...
3598
  						NULL, drop_start,
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3599
  						new_key.offset - drop_start);
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3600
3601
  			clone_update_extent_map(BTRFS_I(inode), trans,
  					path, 0, 0);
7ffbb598a   Filipe Manana   Btrfs: make fsync...
3602

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3603
  			btrfs_mark_buffer_dirty(leaf);
b3b4aa74b   David Sterba   btrfs: drop unuse...
3604
  			btrfs_release_path(path);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3605

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

f82a9901b   Filipe Manana   Btrfs: fix clone ...
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
  	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...
3647
  				btrfs_abort_transaction(trans, ret);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3648
  			btrfs_end_transaction(trans);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3649
3650
  			goto out;
  		}
a2f392e40   Nikolay Borisov   btrfs: Make clone...
3651
3652
3653
  		clone_update_extent_map(BTRFS_I(inode), trans, NULL,
  				last_dest_end,
  				destoff + len - last_dest_end);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3654
  		ret = clone_finish_inode_update(trans, inode, destoff + len,
1c919a5e1   Mark Fasheh   btrfs: don't upda...
3655
  						destoff, olen, no_time_update);
f82a9901b   Filipe Manana   Btrfs: fix clone ...
3656
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3657
  out:
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3658
  	btrfs_free_path(path);
153519559   David Sterba   btrfs: clone: use...
3659
  	kvfree(buf);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3660
3661
  	return ret;
  }
3db11b2ee   Zach Brown   btrfs: add .copy_...
3662
3663
  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...
3664
  {
54563d41a   Al Viro   btrfs: get rid of...
3665
  	struct inode *inode = file_inode(file);
3db11b2ee   Zach Brown   btrfs: add .copy_...
3666
  	struct inode *src = file_inode(file_src);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3667
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3668
  	struct btrfs_root *root = BTRFS_I(inode)->root;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3669
3670
  	int ret;
  	u64 len = olen;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3671
  	u64 bs = fs_info->sb->s_blocksize;
3db11b2ee   Zach Brown   btrfs: add .copy_...
3672
  	int same_inode = src == inode;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3673
3674
3675
3676
3677
3678
3679
  
  	/*
  	 * 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...
3680
3681
3682
  	 *
  	 * - split destination inode's inline extents.  The inline extents can
  	 *   be either compressed or non-compressed.
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3683
  	 */
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3684
3685
  	if (btrfs_root_readonly(root))
  		return -EROFS;
3db11b2ee   Zach Brown   btrfs: add .copy_...
3686
3687
3688
  	if (file_src->f_path.mnt != file->f_path.mnt ||
  	    src->i_sb != inode->i_sb)
  		return -EXDEV;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3689

32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3690
  	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
3db11b2ee   Zach Brown   btrfs: add .copy_...
3691
  		return -EISDIR;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3692
3693
  
  	if (!same_inode) {
293a8489f   Mark Fasheh   btrfs: fix clone ...
3694
  		btrfs_double_inode_lock(src, inode);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3695
  	} else {
5955102c9   Al Viro   wrappers for ->i_...
3696
  		inode_lock(src);
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3697
  	}
55d29ff48   Omar Sandoval   Btrfs: fix clone ...
3698
3699
3700
3701
3702
3703
  	/* don't make the dst file partly checksummed */
  	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
  	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
  		ret = -EINVAL;
  		goto out_unlock;
  	}
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3704
3705
3706
3707
3708
3709
  	/* 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;
d62eead02   Filipe Manana   Btrfs: fix data c...
3710
3711
3712
3713
3714
3715
3716
3717
3718
  	/*
  	 * If we extend to eof, continue to block boundary if and only if the
  	 * destination end offset matches the destination file's size, otherwise
  	 * we would be corrupting data by placing the eof block into the middle
  	 * of a file.
  	 */
  	if (off + len == src->i_size) {
  		if (!IS_ALIGNED(len, bs) && destoff + len < inode->i_size)
  			goto out_unlock;
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3719
  		len = ALIGN(src->i_size, bs) - off;
d62eead02   Filipe Manana   Btrfs: fix data c...
3720
  	}
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3721

ccccf3d67   Filipe Manana   Btrfs: fix inode ...
3722
3723
3724
3725
  	if (len == 0) {
  		ret = 0;
  		goto out_unlock;
  	}
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
  	/* 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...
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
  	/*
  	 * 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...
3752

e0bd70c67   Filipe Manana   Btrfs: fix invali...
3753
  		ret = lock_extent_range(src, lock_start, lock_len, true);
c125b8bff   Filipe Manana   Btrfs: ensure rea...
3754
  	} else {
e0bd70c67   Filipe Manana   Btrfs: fix invali...
3755
3756
3757
3758
3759
3760
3761
  		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...
3762
  	}
32b7c687c   Mark Fasheh   btrfs_ioctl_clone...
3763

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

c125b8bff   Filipe Manana   Btrfs: ensure rea...
3766
3767
3768
3769
3770
3771
  	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 ...
3772
  		btrfs_double_extent_unlock(src, off, inode, destoff, len);
c125b8bff   Filipe Manana   Btrfs: ensure rea...
3773
3774
3775
3776
3777
  	}
  	/*
  	 * 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...
3778
  	truncate_inode_pages_range(&inode->i_data,
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
3779
3780
  				round_down(destoff, PAGE_SIZE),
  				round_up(destoff + len, PAGE_SIZE) - 1);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3781
  out_unlock:
293a8489f   Mark Fasheh   btrfs: fix clone ...
3782
3783
3784
  	if (!same_inode)
  		btrfs_double_inode_unlock(src, inode);
  	else
5955102c9   Al Viro   wrappers for ->i_...
3785
  		inode_unlock(src);
3db11b2ee   Zach Brown   btrfs: add .copy_...
3786
3787
  	return ret;
  }
04b38d601   Christoph Hellwig   vfs: pull btrfs c...
3788
3789
  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_...
3790
  {
04b38d601   Christoph Hellwig   vfs: pull btrfs c...
3791
  	return btrfs_clone_files(dst_file, src_file, off, len, destoff);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
3792
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3793
3794
3795
3796
3797
3798
  /*
   * 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...
3799
  static long btrfs_ioctl_trans_start(struct file *file)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3800
  {
496ad9aa8   Al Viro   new helper: file_...
3801
  	struct inode *inode = file_inode(file);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3802
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3803
3804
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
23b5ec749   Josef Bacik   btrfs: fix readdi...
3805
  	struct btrfs_file_private *private;
1ab86aedb   Sage Weil   Btrfs: fix error ...
3806
  	int ret;
3558d4f88   Nikolay Borisov   btrfs: Deprecate ...
3807
  	static bool warned = false;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3808

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

3558d4f88   Nikolay Borisov   btrfs: Deprecate ...
3813
3814
3815
3816
3817
3818
3819
3820
3821
  	if (!warned) {
  		btrfs_warn(fs_info,
  			"Userspace transaction mechanism is considered "
  			"deprecated and slated to be removed in 4.17. "
  			"If you have a valid use case please "
  			"speak up on the mailing list");
  		WARN_ON(1);
  		warned = true;
  	}
1ab86aedb   Sage Weil   Btrfs: fix error ...
3822
  	ret = -EINPROGRESS;
23b5ec749   Josef Bacik   btrfs: fix readdi...
3823
3824
  	private = file->private_data;
  	if (private && private->trans)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3825
  		goto out;
23b5ec749   Josef Bacik   btrfs: fix readdi...
3826
3827
3828
3829
3830
3831
3832
  	if (!private) {
  		private = kzalloc(sizeof(struct btrfs_file_private),
  				  GFP_KERNEL);
  		if (!private)
  			return -ENOMEM;
  		file->private_data = private;
  	}
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3833

b83cc9693   Li Zefan   Btrfs: Add readon...
3834
3835
3836
  	ret = -EROFS;
  	if (btrfs_root_readonly(root))
  		goto out;
a561be710   Al Viro   switch a bunch of...
3837
  	ret = mnt_want_write_file(file);
c146afad2   Yan Zheng   Btrfs: mount ro a...
3838
3839
  	if (ret)
  		goto out;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3840
  	atomic_inc(&fs_info->open_ioctl_trans);
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
3841

1ab86aedb   Sage Weil   Btrfs: fix error ...
3842
  	ret = -ENOMEM;
7a7eaa40a   Josef Bacik   Btrfs: take away ...
3843
  	trans = btrfs_start_ioctl_transaction(root);
abd30bb0a   Tsutomu Itoh   btrfs: check retu...
3844
  	if (IS_ERR(trans))
1ab86aedb   Sage Weil   Btrfs: fix error ...
3845
  		goto out_drop;
23b5ec749   Josef Bacik   btrfs: fix readdi...
3846
  	private->trans = trans;
1ab86aedb   Sage Weil   Btrfs: fix error ...
3847
3848
3849
  	return 0;
  
  out_drop:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3850
  	atomic_dec(&fs_info->open_ioctl_trans);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
3851
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3852
  out:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
3853
3854
  	return ret;
  }
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3855
3856
  static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
  {
496ad9aa8   Al Viro   new helper: file_...
3857
  	struct inode *inode = file_inode(file);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3858
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3859
3860
3861
3862
3863
3864
3865
  	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 ...
3866
3867
  	u64 objectid = 0;
  	u64 dir_id;
3c04ce010   Miao Xie   Btrfs: get write ...
3868
  	int ret;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3869
3870
3871
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
3c04ce010   Miao Xie   Btrfs: get write ...
3872
3873
3874
3875
3876
3877
3878
3879
  	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 ...
3880
3881
  
  	if (!objectid)
1cecf579d   chandan   Btrfs: btrfs_ioct...
3882
  		objectid = BTRFS_FS_TREE_OBJECTID;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3883
3884
3885
3886
  
  	location.objectid = objectid;
  	location.type = BTRFS_ROOT_ITEM_KEY;
  	location.offset = (u64)-1;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3887
  	new_root = btrfs_read_fs_root_no_name(fs_info, &location);
3c04ce010   Miao Xie   Btrfs: get write ...
3888
3889
3890
3891
  	if (IS_ERR(new_root)) {
  		ret = PTR_ERR(new_root);
  		goto out;
  	}
6d6d28293   satoru takeuchi   btrfs: prevent to...
3892
3893
3894
3895
  	if (!is_fstree(new_root->objectid)) {
  		ret = -ENOENT;
  		goto out;
  	}
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3896

6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3897
  	path = btrfs_alloc_path();
3c04ce010   Miao Xie   Btrfs: get write ...
3898
3899
3900
3901
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3902
3903
3904
  	path->leave_spinning = 1;
  
  	trans = btrfs_start_transaction(root, 1);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
3905
  	if (IS_ERR(trans)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3906
  		btrfs_free_path(path);
3c04ce010   Miao Xie   Btrfs: get write ...
3907
3908
  		ret = PTR_ERR(trans);
  		goto out;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3909
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3910
3911
  	dir_id = btrfs_super_root_dir(fs_info->super_copy);
  	di = btrfs_lookup_dir_item(trans, fs_info->tree_root, path,
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3912
  				   dir_id, "default", 7, 1);
cf1e99a4e   Dan Carpenter   Btrfs: btrfs_look...
3913
  	if (IS_ERR_OR_NULL(di)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3914
  		btrfs_free_path(path);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3915
  		btrfs_end_transaction(trans);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3916
  		btrfs_err(fs_info,
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
3917
  			  "Umm, you don't have the default diritem, this isn't going to work");
3c04ce010   Miao Xie   Btrfs: get write ...
3918
3919
  		ret = -ENOENT;
  		goto out;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3920
3921
3922
3923
3924
3925
  	}
  
  	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);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3926
  	btrfs_set_fs_incompat(fs_info, DEFAULT_SUBVOL);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
3927
  	btrfs_end_transaction(trans);
3c04ce010   Miao Xie   Btrfs: get write ...
3928
3929
3930
  out:
  	mnt_drop_write_file(file);
  	return ret;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
3931
  }
5af3e8cce   Stefan Behrens   Btrfs: make files...
3932
3933
  void btrfs_get_block_group_info(struct list_head *groups_list,
  				struct btrfs_ioctl_space_info *space)
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
  {
  	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);
  	}
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
3947
3948
  static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info,
  				   void __user *arg)
1406e4327   Josef Bacik   Btrfs: add a "df"...
3949
3950
3951
3952
  {
  	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...
3953
  	struct btrfs_ioctl_space_info *dest_orig;
13f2696f1   Daniel J Blueman   fix user annotati...
3954
  	struct btrfs_ioctl_space_info __user *user_dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3955
  	struct btrfs_space_info *info;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3956
3957
3958
3959
3960
  	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...
3961
  	int alloc_size;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3962
  	int ret = 0;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
3963
  	u64 slot_count = 0;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3964
  	int i, c;
1406e4327   Josef Bacik   Btrfs: add a "df"...
3965
3966
3967
3968
3969
  
  	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...
3970
3971
3972
3973
3974
  	for (i = 0; i < num_types; i++) {
  		struct btrfs_space_info *tmp;
  
  		info = NULL;
  		rcu_read_lock();
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
3975
  		list_for_each_entry_rcu(tmp, &fs_info->space_info,
bf5fc093c   Josef Bacik   Btrfs: fix the df...
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
  					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...
3994

36523e951   David Sterba   btrfs: export glo...
3995
3996
3997
3998
  	/*
  	 * Global block reserve, exported as a space_info
  	 */
  	slot_count++;
7fde62bff   Chris Mason   Btrfs: buffer res...
3999
4000
4001
4002
4003
  	/* 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...
4004

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

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

7fde62bff   Chris Mason   Btrfs: buffer res...
4009
4010
4011
  	/* 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...
4012
  	if (alloc_size > PAGE_SIZE)
7fde62bff   Chris Mason   Btrfs: buffer res...
4013
  		return -ENOMEM;
1406e4327   Josef Bacik   Btrfs: add a "df"...
4014
  	space_args.total_spaces = 0;
8d2db7855   David Sterba   btrfs: use GFP_KE...
4015
  	dest = kmalloc(alloc_size, GFP_KERNEL);
7fde62bff   Chris Mason   Btrfs: buffer res...
4016
4017
4018
  	if (!dest)
  		return -ENOMEM;
  	dest_orig = dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
4019

7fde62bff   Chris Mason   Btrfs: buffer res...
4020
  	/* now we have a buffer to copy into */
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4021
4022
  	for (i = 0; i < num_types; i++) {
  		struct btrfs_space_info *tmp;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
4023
4024
  		if (!slot_count)
  			break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4025
4026
  		info = NULL;
  		rcu_read_lock();
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4027
  		list_for_each_entry_rcu(tmp, &fs_info->space_info,
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4028
4029
4030
4031
4032
4033
4034
  					list) {
  			if (tmp->flags == types[i]) {
  				info = tmp;
  				break;
  			}
  		}
  		rcu_read_unlock();
7fde62bff   Chris Mason   Btrfs: buffer res...
4035

bf5fc093c   Josef Bacik   Btrfs: fix the df...
4036
4037
4038
4039
4040
  		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...
4041
4042
  				btrfs_get_block_group_info(
  					&info->block_groups[c], &space);
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4043
4044
4045
  				memcpy(dest, &space, sizeof(space));
  				dest++;
  				space_args.total_spaces++;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
4046
  				slot_count--;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4047
  			}
51788b1bd   Dan Rosenberg   btrfs: prevent he...
4048
4049
  			if (!slot_count)
  				break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
4050
4051
  		}
  		up_read(&info->groups_sem);
1406e4327   Josef Bacik   Btrfs: add a "df"...
4052
  	}
1406e4327   Josef Bacik   Btrfs: add a "df"...
4053

36523e951   David Sterba   btrfs: export glo...
4054
4055
4056
4057
  	/*
  	 * Add global block reserve
  	 */
  	if (slot_count) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4058
  		struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
36523e951   David Sterba   btrfs: export glo...
4059
4060
4061
4062
4063
4064
4065
4066
4067
  
  		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...
4068
  	user_dest = (struct btrfs_ioctl_space_info __user *)
7fde62bff   Chris Mason   Btrfs: buffer res...
4069
4070
4071
4072
4073
4074
4075
4076
  		(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"...
4077
4078
4079
4080
  		ret = -EFAULT;
  
  	return ret;
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4081
4082
4083
4084
4085
4086
4087
4088
  /*
   * 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_...
4089
  	struct inode *inode = file_inode(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4090
  	struct btrfs_root *root = BTRFS_I(inode)->root;
23b5ec749   Josef Bacik   btrfs: fix readdi...
4091
  	struct btrfs_file_private *private = file->private_data;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4092

23b5ec749   Josef Bacik   btrfs: fix readdi...
4093
  	if (!private || !private->trans)
1ab86aedb   Sage Weil   Btrfs: fix error ...
4094
  		return -EINVAL;
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
4095

23b5ec749   Josef Bacik   btrfs: fix readdi...
4096
4097
  	btrfs_end_transaction(private->trans);
  	private->trans = NULL;
1ab86aedb   Sage Weil   Btrfs: fix error ...
4098

a4abeea41   Josef Bacik   Btrfs: kill trans...
4099
  	atomic_dec(&root->fs_info->open_ioctl_trans);
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
4100

2a79f17e4   Al Viro   vfs: mnt_drop_wri...
4101
  	mnt_drop_write_file(file);
1ab86aedb   Sage Weil   Btrfs: fix error ...
4102
  	return 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
4103
  }
9a8c28bec   Miao Xie   Btrfs: pass root ...
4104
4105
  static noinline long btrfs_ioctl_start_sync(struct btrfs_root *root,
  					    void __user *argp)
462045928   Sage Weil   Btrfs: add START_...
4106
  {
462045928   Sage Weil   Btrfs: add START_...
4107
4108
  	struct btrfs_trans_handle *trans;
  	u64 transid;
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
4109
  	int ret;
462045928   Sage Weil   Btrfs: add START_...
4110

d4edf39bd   Miao Xie   Btrfs: fix uncomp...
4111
  	trans = btrfs_attach_transaction_barrier(root);
ff7c1d335   Miao Xie   Btrfs: don't star...
4112
4113
4114
4115
4116
4117
4118
4119
  	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_...
4120
  	transid = trans->transid;
3a45bb207   Jeff Mahoney   btrfs: remove roo...
4121
  	ret = btrfs_commit_transaction_async(trans, 0);
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
4122
  	if (ret) {
3a45bb207   Jeff Mahoney   btrfs: remove roo...
4123
  		btrfs_end_transaction(trans);
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
4124
  		return ret;
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
4125
  	}
ff7c1d335   Miao Xie   Btrfs: don't star...
4126
  out:
462045928   Sage Weil   Btrfs: add START_...
4127
4128
4129
4130
4131
  	if (argp)
  		if (copy_to_user(argp, &transid, sizeof(transid)))
  			return -EFAULT;
  	return 0;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4132
  static noinline long btrfs_ioctl_wait_sync(struct btrfs_fs_info *fs_info,
9a8c28bec   Miao Xie   Btrfs: pass root ...
4133
  					   void __user *argp)
462045928   Sage Weil   Btrfs: add START_...
4134
  {
462045928   Sage Weil   Btrfs: add START_...
4135
4136
4137
4138
4139
4140
4141
4142
  	u64 transid;
  
  	if (argp) {
  		if (copy_from_user(&transid, argp, sizeof(transid)))
  			return -EFAULT;
  	} else {
  		transid = 0;  /* current trans */
  	}
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4143
  	return btrfs_wait_for_commit(fs_info, transid);
462045928   Sage Weil   Btrfs: add START_...
4144
  }
b8e95489b   Miao Xie   Btrfs: get write ...
4145
  static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
475f63874   Jan Schmidt   btrfs: new ioctls...
4146
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4147
  	struct btrfs_fs_info *fs_info = btrfs_sb(file_inode(file)->i_sb);
475f63874   Jan Schmidt   btrfs: new ioctls...
4148
  	struct btrfs_ioctl_scrub_args *sa;
b8e95489b   Miao Xie   Btrfs: get write ...
4149
  	int ret;
475f63874   Jan Schmidt   btrfs: new ioctls...
4150
4151
4152
4153
4154
4155
4156
  
  	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 ...
4157
4158
4159
4160
4161
  	if (!(sa->flags & BTRFS_SCRUB_READONLY)) {
  		ret = mnt_want_write_file(file);
  		if (ret)
  			goto out;
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4162
  	ret = btrfs_scrub_dev(fs_info, sa->devid, sa->start, sa->end,
63a212abc   Stefan Behrens   Btrfs: disallow s...
4163
4164
  			      &sa->progress, sa->flags & BTRFS_SCRUB_READONLY,
  			      0);
475f63874   Jan Schmidt   btrfs: new ioctls...
4165
4166
4167
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
b8e95489b   Miao Xie   Btrfs: get write ...
4168
4169
4170
  	if (!(sa->flags & BTRFS_SCRUB_READONLY))
  		mnt_drop_write_file(file);
  out:
475f63874   Jan Schmidt   btrfs: new ioctls...
4171
4172
4173
  	kfree(sa);
  	return ret;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4174
  static long btrfs_ioctl_scrub_cancel(struct btrfs_fs_info *fs_info)
475f63874   Jan Schmidt   btrfs: new ioctls...
4175
4176
4177
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4178
  	return btrfs_scrub_cancel(fs_info);
475f63874   Jan Schmidt   btrfs: new ioctls...
4179
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4180
  static long btrfs_ioctl_scrub_progress(struct btrfs_fs_info *fs_info,
475f63874   Jan Schmidt   btrfs: new ioctls...
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
  				       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);
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4192
  	ret = btrfs_scrub_progress(fs_info, sa->devid, &sa->progress);
475f63874   Jan Schmidt   btrfs: new ioctls...
4193
4194
4195
4196
4197
4198
4199
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
  
  	kfree(sa);
  	return ret;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4200
  static long btrfs_ioctl_get_dev_stats(struct btrfs_fs_info *fs_info,
b27f7c0c1   David Sterba   btrfs: join DEV_S...
4201
  				      void __user *arg)
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
4202
4203
4204
  {
  	struct btrfs_ioctl_get_dev_stats *sa;
  	int ret;
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
4205
4206
4207
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
b27f7c0c1   David Sterba   btrfs: join DEV_S...
4208
4209
4210
4211
  	if ((sa->flags & BTRFS_DEV_STATS_RESET) && !capable(CAP_SYS_ADMIN)) {
  		kfree(sa);
  		return -EPERM;
  	}
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4212
  	ret = btrfs_get_dev_stats(fs_info, sa);
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
4213
4214
4215
4216
4217
4218
4219
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
  
  	kfree(sa);
  	return ret;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4220
4221
  static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info,
  				    void __user *arg)
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
  {
  	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:
bc98a42c1   David Howells   VFS: Convert sb->...
4235
  		if (sb_rdonly(fs_info->sb)) {
adfa97cbd   Ilya Dryomov   Btrfs: don't leak...
4236
4237
4238
  			ret = -EROFS;
  			goto out;
  		}
171938e52   David Sterba   btrfs: track excl...
4239
  		if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
e57138b3e   Anand Jain   btrfs: return btr...
4240
  			ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4241
  		} else {
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4242
  			ret = btrfs_dev_replace_by_ioctl(fs_info, p);
171938e52   David Sterba   btrfs: track excl...
4243
  			clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4244
4245
4246
  		}
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4247
  		btrfs_dev_replace_status(fs_info, p);
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4248
4249
4250
  		ret = 0;
  		break;
  	case BTRFS_IOCTL_DEV_REPLACE_CMD_CANCEL:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4251
  		ret = btrfs_dev_replace_cancel(fs_info, p);
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4252
4253
4254
4255
4256
4257
4258
4259
  		break;
  	default:
  		ret = -EINVAL;
  		break;
  	}
  
  	if (copy_to_user(arg, p, sizeof(*p)))
  		ret = -EFAULT;
adfa97cbd   Ilya Dryomov   Btrfs: don't leak...
4260
  out:
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
4261
4262
4263
  	kfree(p);
  	return ret;
  }
d7728c960   Jan Schmidt   btrfs: new ioctls...
4264
4265
4266
4267
  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...
4268
  	u64 rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4269
  	int size;
806468f8b   Chris Mason   Merge git://git.j...
4270
  	struct btrfs_ioctl_ino_path_args *ipa = NULL;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4271
4272
  	struct inode_fs_paths *ipath = NULL;
  	struct btrfs_path *path;
82b22ac8f   Kusanagi Kouichi   Btrfs: Check CAP_...
4273
  	if (!capable(CAP_DAC_READ_SEARCH))
d7728c960   Jan Schmidt   btrfs: new ioctls...
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
  		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/...
4302
4303
  		rel_ptr = ipath->fspath->val[i] -
  			  (u64)(unsigned long)ipath->fspath->val;
740c3d226   Chris Mason   Btrfs: fix the ne...
4304
  		ipath->fspath->val[i] = rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4305
  	}
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
4306
4307
  	ret = copy_to_user((void *)(unsigned long)ipa->fspath,
  			   (void *)(unsigned long)ipath->fspath, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
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
4333
4334
4335
4336
4337
4338
4339
  	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;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4340
  static long btrfs_ioctl_logical_to_ino(struct btrfs_fs_info *fs_info,
d7728c960   Jan Schmidt   btrfs: new ioctls...
4341
4342
4343
4344
  					void __user *arg)
  {
  	int ret = 0;
  	int size;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4345
4346
4347
  	struct btrfs_ioctl_logical_ino_args *loi;
  	struct btrfs_data_container *inodes = NULL;
  	struct btrfs_path *path = NULL;
d7728c960   Jan Schmidt   btrfs: new ioctls...
4348
4349
4350
4351
4352
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	loi = memdup_user(arg, sizeof(*loi));
7b9ea6279   Shailendra Verma   btrfs: return ear...
4353
4354
  	if (IS_ERR(loi))
  		return PTR_ERR(loi);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4355
4356
4357
4358
4359
4360
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
ee22184b5   Byongho Lee   Btrfs: use linux/...
4361
  	size = min_t(u32, loi->size, SZ_64K);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4362
4363
4364
4365
4366
4367
  	inodes = init_data_container(size);
  	if (IS_ERR(inodes)) {
  		ret = PTR_ERR(inodes);
  		inodes = NULL;
  		goto out;
  	}
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4368
  	ret = iterate_inodes_from_logical(loi->logical, fs_info, path,
df031f075   Liu Bo   Btrfs: use helper...
4369
4370
  					  build_ino_list, inodes);
  	if (ret == -EINVAL)
d7728c960   Jan Schmidt   btrfs: new ioctls...
4371
4372
4373
  		ret = -ENOENT;
  	if (ret < 0)
  		goto out;
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
4374
4375
  	ret = copy_to_user((void *)(unsigned long)loi->inodes,
  			   (void *)(unsigned long)inodes, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4376
4377
4378
4379
4380
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	btrfs_free_path(path);
f54de068d   David Sterba   btrfs: use GFP_KE...
4381
  	kvfree(inodes);
d7728c960   Jan Schmidt   btrfs: new ioctls...
4382
4383
4384
4385
  	kfree(loi);
  
  	return ret;
  }
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4386
  void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4387
4388
4389
4390
4391
  			       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 ...
4392
4393
4394
4395
  	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 ...
4396
4397
  	if (atomic_read(&fs_info->balance_cancel_req))
  		bargs->state |= BTRFS_BALANCE_STATE_CANCEL_REQ;
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4398

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

c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4534
4535
4536
4537
  	if (arg) {
  		if (copy_to_user(arg, bargs, sizeof(*bargs)))
  			ret = -EFAULT;
  	}
0f89abf56   Christian Engelmayer   btrfs: fix possib...
4538
4539
  out_bctl:
  	kfree(bctl);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4540
4541
  out_bargs:
  	kfree(bargs);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4542
  out_unlock:
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4543
4544
  	mutex_unlock(&fs_info->balance_mutex);
  	mutex_unlock(&fs_info->volume_mutex);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4545
  	if (need_unlock)
171938e52   David Sterba   btrfs: track excl...
4546
  		clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
ed0fb78fb   Ilya Dryomov   Btrfs: bring back...
4547
  out:
e54bfa310   Liu Bo   Btrfs: use mnt_wa...
4548
  	mnt_drop_write_file(file);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
4549
4550
  	return ret;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4551
  static long btrfs_ioctl_balance_ctl(struct btrfs_fs_info *fs_info, int cmd)
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4552
4553
4554
4555
4556
4557
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	switch (cmd) {
  	case BTRFS_BALANCE_CTL_PAUSE:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4558
  		return btrfs_pause_balance(fs_info);
a7e99c691   Ilya Dryomov   Btrfs: allow for ...
4559
  	case BTRFS_BALANCE_CTL_CANCEL:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4560
  		return btrfs_cancel_balance(fs_info);
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
4561
4562
4563
4564
  	}
  
  	return -EINVAL;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
4565
  static long btrfs_ioctl_balance_progress(struct btrfs_fs_info *fs_info,
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4566
4567
  					 void __user *arg)
  {
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
  	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...
4579
  	bargs = kzalloc(sizeof(*bargs), GFP_KERNEL);
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
  	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 ...
4595
  static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4596
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4597
4598
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4599
4600
4601
4602
4603
4604
4605
  	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 ...
4606
4607
4608
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4609
4610
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4611
4612
4613
4614
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4615

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4616
4617
  	down_write(&fs_info->subvol_sem);
  	trans = btrfs_start_transaction(fs_info->tree_root, 2);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4618
4619
4620
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4621
4622
4623
4624
  	}
  
  	switch (sa->cmd) {
  	case BTRFS_QUOTA_CTL_ENABLE:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4625
  		ret = btrfs_quota_enable(trans, fs_info);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4626
4627
  		break;
  	case BTRFS_QUOTA_CTL_DISABLE:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4628
  		ret = btrfs_quota_disable(trans, fs_info);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4629
  		break;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4630
4631
4632
4633
  	default:
  		ret = -EINVAL;
  		break;
  	}
3a45bb207   Jeff Mahoney   btrfs: remove roo...
4634
  	err = btrfs_commit_transaction(trans);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4635
4636
  	if (err && !ret)
  		ret = err;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4637
4638
  out:
  	kfree(sa);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4639
  	up_write(&fs_info->subvol_sem);
905b0dda0   Miao Xie   Btrfs: get write ...
4640
4641
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4642
4643
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4644
  static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4645
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4646
4647
4648
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_root *root = BTRFS_I(inode)->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4649
4650
4651
4652
4653
4654
4655
  	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 ...
4656
4657
4658
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4659
4660
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4661
4662
4663
4664
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4665
4666
4667
4668
4669
4670
  
  	trans = btrfs_join_transaction(root);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4671
  	if (sa->assign) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4672
  		ret = btrfs_add_qgroup_relation(trans, fs_info,
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4673
4674
  						sa->src, sa->dst);
  	} else {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4675
  		ret = btrfs_del_qgroup_relation(trans, fs_info,
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4676
4677
  						sa->src, sa->dst);
  	}
e082f5631   Qu Wenruo   btrfs: quota: Upd...
4678
  	/* update qgroup status and info */
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4679
  	err = btrfs_run_qgroups(trans, fs_info);
e082f5631   Qu Wenruo   btrfs: quota: Upd...
4680
  	if (err < 0)
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4681
4682
  		btrfs_handle_fs_error(fs_info, err,
  				      "failed to update qgroup status and info");
3a45bb207   Jeff Mahoney   btrfs: remove roo...
4683
  	err = btrfs_end_transaction(trans);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4684
4685
4686
4687
4688
  	if (err && !ret)
  		ret = err;
  
  out:
  	kfree(sa);
905b0dda0   Miao Xie   Btrfs: get write ...
4689
4690
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4691
4692
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4693
  static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4694
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4695
4696
4697
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_root *root = BTRFS_I(inode)->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4698
4699
4700
4701
4702
4703
4704
  	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 ...
4705
4706
4707
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4708
4709
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4710
4711
4712
4713
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4714

d86e56cf7   Miao Xie   Btrfs: disable qg...
4715
4716
4717
4718
  	if (!sa->qgroupid) {
  		ret = -EINVAL;
  		goto out;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4719
4720
4721
4722
4723
  	trans = btrfs_join_transaction(root);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4724
  	if (sa->create) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4725
  		ret = btrfs_create_qgroup(trans, fs_info, sa->qgroupid);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4726
  	} else {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4727
  		ret = btrfs_remove_qgroup(trans, fs_info, sa->qgroupid);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4728
  	}
3a45bb207   Jeff Mahoney   btrfs: remove roo...
4729
  	err = btrfs_end_transaction(trans);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4730
4731
4732
4733
4734
  	if (err && !ret)
  		ret = err;
  
  out:
  	kfree(sa);
905b0dda0   Miao Xie   Btrfs: get write ...
4735
4736
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4737
4738
  	return ret;
  }
905b0dda0   Miao Xie   Btrfs: get write ...
4739
  static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg)
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4740
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4741
4742
4743
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_root *root = BTRFS_I(inode)->root;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4744
4745
4746
4747
4748
4749
4750
4751
  	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 ...
4752
4753
4754
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4755
4756
  
  	sa = memdup_user(arg, sizeof(*sa));
905b0dda0   Miao Xie   Btrfs: get write ...
4757
4758
4759
4760
  	if (IS_ERR(sa)) {
  		ret = PTR_ERR(sa);
  		goto drop_write;
  	}
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
  
  	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;
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4773
  	ret = btrfs_limit_qgroup(trans, fs_info, qgroupid, &sa->lim);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4774

3a45bb207   Jeff Mahoney   btrfs: remove roo...
4775
  	err = btrfs_end_transaction(trans);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4776
4777
4778
4779
4780
  	if (err && !ret)
  		ret = err;
  
  out:
  	kfree(sa);
905b0dda0   Miao Xie   Btrfs: get write ...
4781
4782
  drop_write:
  	mnt_drop_write_file(file);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
4783
4784
  	return ret;
  }
2f2320360   Jan Schmidt   Btrfs: rescan for...
4785
4786
  static long btrfs_ioctl_quota_rescan(struct file *file, void __user *arg)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4787
4788
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
  	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;
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4809
  	ret = btrfs_qgroup_rescan(fs_info);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
  
  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)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4820
4821
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4822
4823
4824
4825
4826
  	struct btrfs_ioctl_quota_rescan_args *qsa;
  	int ret = 0;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
8d2db7855   David Sterba   btrfs: use GFP_KE...
4827
  	qsa = kzalloc(sizeof(*qsa), GFP_KERNEL);
2f2320360   Jan Schmidt   Btrfs: rescan for...
4828
4829
  	if (!qsa)
  		return -ENOMEM;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4830
  	if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN) {
2f2320360   Jan Schmidt   Btrfs: rescan for...
4831
  		qsa->flags = 1;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4832
  		qsa->progress = fs_info->qgroup_rescan_progress.objectid;
2f2320360   Jan Schmidt   Btrfs: rescan for...
4833
4834
4835
4836
4837
4838
4839
4840
  	}
  
  	if (copy_to_user(arg, qsa, sizeof(*qsa)))
  		ret = -EFAULT;
  
  	kfree(qsa);
  	return ret;
  }
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4841
4842
  static long btrfs_ioctl_quota_rescan_wait(struct file *file, void __user *arg)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4843
4844
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4845
4846
4847
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4848
  	return btrfs_qgroup_wait_for_completion(fs_info, true);
57254b6eb   Jan Schmidt   Btrfs: add ioctl ...
4849
  }
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4850
4851
  static long _btrfs_ioctl_set_received_subvol(struct file *file,
  					    struct btrfs_ioctl_received_subvol_args *sa)
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4852
  {
496ad9aa8   Al Viro   new helper: file_...
4853
  	struct inode *inode = file_inode(file);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4854
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4855
4856
4857
  	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...
4858
  	struct timespec ct = current_time(inode);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4859
  	int ret = 0;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4860
  	int received_uuid_changed;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4861

bd60ea0fe   David Sterba   btrfs: call permi...
4862
4863
  	if (!inode_owner_or_capable(inode))
  		return -EPERM;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4864
4865
4866
  	ret = mnt_want_write_file(file);
  	if (ret < 0)
  		return ret;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4867
  	down_write(&fs_info->subvol_sem);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4868

4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
4869
  	if (btrfs_ino(BTRFS_I(inode)) != BTRFS_FIRST_FREE_OBJECTID) {
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4870
4871
4872
4873
4874
4875
4876
4877
  		ret = -EINVAL;
  		goto out;
  	}
  
  	if (btrfs_root_readonly(root)) {
  		ret = -EROFS;
  		goto out;
  	}
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4878
4879
4880
4881
4882
  	/*
  	 * 1 - root item
  	 * 2 - uuid items (received uuid + subvol uuid)
  	 */
  	trans = btrfs_start_transaction(root, 3);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4883
4884
4885
4886
4887
4888
4889
4890
4891
  	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...
4892
4893
4894
4895
  	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))
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4896
  		btrfs_uuid_tree_rem(trans, fs_info, root_item->received_uuid,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4897
4898
  				    BTRFS_UUID_KEY_RECEIVED_SUBVOL,
  				    root->root_key.objectid);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4899
4900
4901
  	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...
4902
4903
4904
4905
  	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 ...
4906

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4907
  	ret = btrfs_update_root(trans, fs_info->tree_root,
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4908
4909
  				&root->root_key, &root->root_item);
  	if (ret < 0) {
3a45bb207   Jeff Mahoney   btrfs: remove roo...
4910
  		btrfs_end_transaction(trans);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4911
  		goto out;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4912
4913
  	}
  	if (received_uuid_changed && !btrfs_is_empty_uuid(sa->uuid)) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4914
  		ret = btrfs_uuid_tree_add(trans, fs_info, sa->uuid,
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4915
4916
4917
  					  BTRFS_UUID_KEY_RECEIVED_SUBVOL,
  					  root->root_key.objectid);
  		if (ret < 0 && ret != -EEXIST) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
4918
  			btrfs_abort_transaction(trans, ret);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4919
  			goto out;
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4920
4921
  		}
  	}
3a45bb207   Jeff Mahoney   btrfs: remove roo...
4922
  	ret = btrfs_commit_transaction(trans);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4923
  	if (ret < 0) {
66642832f   Jeff Mahoney   btrfs: btrfs_abor...
4924
  		btrfs_abort_transaction(trans, ret);
dd5f9615f   Stefan Behrens   Btrfs: maintain s...
4925
  		goto out;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4926
  	}
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4927
  out:
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
4928
  	up_write(&fs_info->subvol_sem);
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
  	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));
7b9ea6279   Shailendra Verma   btrfs: return ear...
4942
4943
  	if (IS_ERR(args32))
  		return PTR_ERR(args32);
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4944

8d2db7855   David Sterba   btrfs: use GFP_KE...
4945
  	args64 = kmalloc(sizeof(*args64), GFP_KERNEL);
84dbeb87d   Dan Carpenter   Btrfs: kmalloc() ...
4946
4947
  	if (!args64) {
  		ret = -ENOMEM;
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
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
  		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));
7b9ea6279   Shailendra Verma   btrfs: return ear...
4991
4992
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
4993
4994
4995
4996
4997
  
  	ret = _btrfs_ioctl_set_received_subvol(file, sa);
  
  	if (ret)
  		goto out;
8ea05e3a4   Alexander Block   Btrfs: introduce ...
4998
4999
5000
5001
5002
5003
  	ret = copy_to_user(arg, sa, sizeof(*sa));
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	kfree(sa);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
5004
5005
  	return ret;
  }
867ab667e   jeff.liu   Btrfs: Add a new ...
5006
5007
  static int btrfs_ioctl_get_fslabel(struct file *file, void __user *arg)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5008
5009
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
a1b83ac52   Anand Jain   btrfs: fix get se...
5010
  	size_t len;
867ab667e   jeff.liu   Btrfs: Add a new ...
5011
  	int ret;
a1b83ac52   Anand Jain   btrfs: fix get se...
5012
  	char label[BTRFS_LABEL_SIZE];
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5013
5014
5015
  	spin_lock(&fs_info->super_lock);
  	memcpy(label, fs_info->super_copy->label, BTRFS_LABEL_SIZE);
  	spin_unlock(&fs_info->super_lock);
a1b83ac52   Anand Jain   btrfs: fix get se...
5016
5017
  
  	len = strnlen(label, BTRFS_LABEL_SIZE);
867ab667e   jeff.liu   Btrfs: Add a new ...
5018
5019
  
  	if (len == BTRFS_LABEL_SIZE) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5020
5021
5022
  		btrfs_warn(fs_info,
  			   "label is too long, return the first %zu bytes",
  			   --len);
867ab667e   jeff.liu   Btrfs: Add a new ...
5023
  	}
867ab667e   jeff.liu   Btrfs: Add a new ...
5024
  	ret = copy_to_user(arg, label, len);
867ab667e   jeff.liu   Btrfs: Add a new ...
5025
5026
5027
  
  	return ret ? -EFAULT : 0;
  }
a8bfd4abe   jeff.liu   Btrfs: set/change...
5028
5029
  static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5030
5031
5032
5033
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_super_block *super_block = fs_info->super_copy;
a8bfd4abe   jeff.liu   Btrfs: set/change...
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
  	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) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5045
  		btrfs_err(fs_info,
5d163e0e6   Jeff Mahoney   btrfs: unsplit pr...
5046
5047
  			  "unable to set label with more than %d bytes",
  			  BTRFS_LABEL_SIZE - 1);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5048
5049
5050
5051
5052
5053
  		return -EINVAL;
  	}
  
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
a8bfd4abe   jeff.liu   Btrfs: set/change...
5054
5055
5056
5057
5058
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_unlock;
  	}
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5059
  	spin_lock(&fs_info->super_lock);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5060
  	strcpy(super_block->label, label);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5061
  	spin_unlock(&fs_info->super_lock);
3a45bb207   Jeff Mahoney   btrfs: remove roo...
5062
  	ret = btrfs_commit_transaction(trans);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5063
5064
  
  out_unlock:
a8bfd4abe   jeff.liu   Btrfs: set/change...
5065
5066
5067
  	mnt_drop_write_file(file);
  	return ret;
  }
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5068
5069
5070
5071
  #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...
5072
  int btrfs_ioctl_get_supported_features(void __user *arg)
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5073
  {
4d4ab6d6b   David Sterba   btrfs: constify s...
5074
  	static const struct btrfs_ioctl_feature_flags features[3] = {
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
  		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)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5088
5089
5090
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_super_block *super_block = fs_info->super_copy;
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
  	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;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5102
  static int check_feature_bits(struct btrfs_fs_info *fs_info,
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5103
  			      enum btrfs_feature_set set,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5104
5105
5106
  			      u64 change_mask, u64 flags, u64 supported_flags,
  			      u64 safe_set, u64 safe_clear)
  {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5107
5108
  	const char *type = btrfs_feature_set_names[set];
  	char *names;
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5109
5110
5111
5112
5113
5114
  	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...
5115
5116
  		names = btrfs_printable_features(set, unsupported);
  		if (names) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5117
5118
5119
  			btrfs_warn(fs_info,
  				   "this kernel does not support the %s feature bit%s",
  				   names, strchr(names, ',') ? "s" : "");
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5120
5121
  			kfree(names);
  		} else
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5122
5123
5124
  			btrfs_warn(fs_info,
  				   "this kernel does not support %s bits 0x%llx",
  				   type, unsupported);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5125
5126
5127
5128
5129
  		return -EOPNOTSUPP;
  	}
  
  	disallowed = set_mask & ~safe_set;
  	if (disallowed) {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5130
5131
  		names = btrfs_printable_features(set, disallowed);
  		if (names) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5132
5133
5134
  			btrfs_warn(fs_info,
  				   "can't set the %s feature bit%s while mounted",
  				   names, strchr(names, ',') ? "s" : "");
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5135
5136
  			kfree(names);
  		} else
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5137
5138
5139
  			btrfs_warn(fs_info,
  				   "can't set %s bits 0x%llx while mounted",
  				   type, disallowed);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5140
5141
5142
5143
5144
  		return -EPERM;
  	}
  
  	disallowed = clear_mask & ~safe_clear;
  	if (disallowed) {
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5145
5146
  		names = btrfs_printable_features(set, disallowed);
  		if (names) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5147
5148
5149
  			btrfs_warn(fs_info,
  				   "can't clear the %s feature bit%s while mounted",
  				   names, strchr(names, ',') ? "s" : "");
3b02a68a6   Jeff Mahoney   btrfs: use featur...
5150
5151
  			kfree(names);
  		} else
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5152
5153
5154
  			btrfs_warn(fs_info,
  				   "can't clear %s bits 0x%llx while mounted",
  				   type, disallowed);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5155
5156
5157
5158
5159
  		return -EPERM;
  	}
  
  	return 0;
  }
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5160
5161
  #define check_feature(fs_info, change_mask, flags, mask_base)	\
  check_feature_bits(fs_info, FEAT_##mask_base, change_mask, flags,	\
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5162
5163
5164
5165
5166
5167
  		   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)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5168
5169
5170
5171
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_super_block *super_block = fs_info->super_copy;
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
  	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;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5187
  	ret = check_feature(fs_info, flags[0].compat_flags,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5188
5189
5190
  			    flags[1].compat_flags, COMPAT);
  	if (ret)
  		return ret;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5191
  	ret = check_feature(fs_info, flags[0].compat_ro_flags,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5192
5193
5194
  			    flags[1].compat_ro_flags, COMPAT_RO);
  	if (ret)
  		return ret;
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5195
  	ret = check_feature(fs_info, flags[0].incompat_flags,
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5196
5197
5198
  			    flags[1].incompat_flags, INCOMPAT);
  	if (ret)
  		return ret;
7ab19625a   David Sterba   btrfs: add write ...
5199
5200
5201
  	ret = mnt_want_write_file(file);
  	if (ret)
  		return ret;
8051aa1a3   David Sterba   btrfs: reserve no...
5202
  	trans = btrfs_start_transaction(root, 0);
7ab19625a   David Sterba   btrfs: add write ...
5203
5204
5205
5206
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_drop_write;
  	}
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5207

0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5208
  	spin_lock(&fs_info->super_lock);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
  	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);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5223
  	spin_unlock(&fs_info->super_lock);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5224

3a45bb207   Jeff Mahoney   btrfs: remove roo...
5225
  	ret = btrfs_commit_transaction(trans);
7ab19625a   David Sterba   btrfs: add write ...
5226
5227
5228
5229
  out_drop_write:
  	mnt_drop_write_file(file);
  
  	return ret;
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5230
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5231
5232
5233
  long btrfs_ioctl(struct file *file, unsigned int
  		cmd, unsigned long arg)
  {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5234
5235
5236
  	struct inode *inode = file_inode(file);
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
  	struct btrfs_root *root = BTRFS_I(inode)->root;
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
5237
  	void __user *argp = (void __user *)arg;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5238
5239
  
  	switch (cmd) {
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
5240
5241
5242
5243
5244
5245
  	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_...
5246
5247
  	case FITRIM:
  		return btrfs_ioctl_fitrim(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5248
  	case BTRFS_IOC_SNAP_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
5249
  		return btrfs_ioctl_snap_create(file, argp, 0);
fdfb1e4f6   Li Zefan   Btrfs: Make async...
5250
  	case BTRFS_IOC_SNAP_CREATE_V2:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
5251
  		return btrfs_ioctl_snap_create_v2(file, argp, 0);
3de4586c5   Chris Mason   Btrfs: Allow subv...
5252
  	case BTRFS_IOC_SUBVOL_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
5253
  		return btrfs_ioctl_snap_create(file, argp, 1);
6f72c7e20   Arne Jansen   Btrfs: add qgroup...
5254
5255
  	case BTRFS_IOC_SUBVOL_CREATE_V2:
  		return btrfs_ioctl_snap_create_v2(file, argp, 1);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
5256
5257
  	case BTRFS_IOC_SNAP_DESTROY:
  		return btrfs_ioctl_snap_destroy(file, argp);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
5258
5259
5260
5261
  	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 ...
5262
5263
  	case BTRFS_IOC_DEFAULT_SUBVOL:
  		return btrfs_ioctl_default_subvol(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5264
  	case BTRFS_IOC_DEFRAG:
1e701a329   Chris Mason   Btrfs: add new de...
5265
5266
5267
  		return btrfs_ioctl_defrag(file, NULL);
  	case BTRFS_IOC_DEFRAG_RANGE:
  		return btrfs_ioctl_defrag(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5268
  	case BTRFS_IOC_RESIZE:
198605a8e   Miao Xie   Btrfs: get write ...
5269
  		return btrfs_ioctl_resize(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5270
  	case BTRFS_IOC_ADD_DEV:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5271
  		return btrfs_ioctl_add_dev(fs_info, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5272
  	case BTRFS_IOC_RM_DEV:
da24927b1   Miao Xie   Btrfs: get write ...
5273
  		return btrfs_ioctl_rm_dev(file, argp);
6b526ed70   Anand Jain   btrfs: introduce ...
5274
5275
  	case BTRFS_IOC_RM_DEV_V2:
  		return btrfs_ioctl_rm_dev_v2(file, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
5276
  	case BTRFS_IOC_FS_INFO:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5277
  		return btrfs_ioctl_fs_info(fs_info, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
5278
  	case BTRFS_IOC_DEV_INFO:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5279
  		return btrfs_ioctl_dev_info(fs_info, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5280
  	case BTRFS_IOC_BALANCE:
9ba1f6e44   Liu Bo   Btrfs: do not do ...
5281
  		return btrfs_ioctl_balance(file, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
5282
5283
5284
5285
  	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...
5286
5287
  	case BTRFS_IOC_TREE_SEARCH:
  		return btrfs_ioctl_tree_search(file, argp);
cc68a8a5a   Gerhard Heift   btrfs: new ioctl ...
5288
5289
  	case BTRFS_IOC_TREE_SEARCH_V2:
  		return btrfs_ioctl_tree_search_v2(file, argp);
ac8e9819d   Chris Mason   Btrfs: add search...
5290
5291
  	case BTRFS_IOC_INO_LOOKUP:
  		return btrfs_ioctl_ino_lookup(file, argp);
d7728c960   Jan Schmidt   btrfs: new ioctls...
5292
5293
5294
  	case BTRFS_IOC_INO_PATHS:
  		return btrfs_ioctl_ino_to_path(root, argp);
  	case BTRFS_IOC_LOGICAL_INO:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5295
  		return btrfs_ioctl_logical_to_ino(fs_info, argp);
1406e4327   Josef Bacik   Btrfs: add a "df"...
5296
  	case BTRFS_IOC_SPACE_INFO:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5297
  		return btrfs_ioctl_space_info(fs_info, argp);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
5298
5299
  	case BTRFS_IOC_SYNC: {
  		int ret;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5300
  		ret = btrfs_start_delalloc_roots(fs_info, 0, -1);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
5301
5302
  		if (ret)
  			return ret;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5303
  		ret = btrfs_sync_fs(inode->i_sb, 1);
2fad4e83e   David Sterba   btrfs: wake up tr...
5304
5305
  		/*
  		 * The transaction thread may want to do more work,
013276101   Nicholas D Steeves   btrfs: fix string...
5306
  		 * namely it pokes the cleaner kthread that will start
2fad4e83e   David Sterba   btrfs: wake up tr...
5307
5308
  		 * processing uncleaned subvols.
  		 */
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
5309
  		wake_up_process(fs_info->transaction_kthread);
9b1998598   Filipe David Borba Manana   Btrfs: fix sync f...
5310
5311
  		return ret;
  	}
462045928   Sage Weil   Btrfs: add START_...
5312
  	case BTRFS_IOC_START_SYNC:
9a8c28bec   Miao Xie   Btrfs: pass root ...
5313
  		return btrfs_ioctl_start_sync(root, argp);
462045928   Sage Weil   Btrfs: add START_...
5314
  	case BTRFS_IOC_WAIT_SYNC:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5315
  		return btrfs_ioctl_wait_sync(fs_info, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
5316
  	case BTRFS_IOC_SCRUB:
b8e95489b   Miao Xie   Btrfs: get write ...
5317
  		return btrfs_ioctl_scrub(file, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
5318
  	case BTRFS_IOC_SCRUB_CANCEL:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5319
  		return btrfs_ioctl_scrub_cancel(fs_info);
475f63874   Jan Schmidt   btrfs: new ioctls...
5320
  	case BTRFS_IOC_SCRUB_PROGRESS:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5321
  		return btrfs_ioctl_scrub_progress(fs_info, argp);
c9e9f97bd   Ilya Dryomov   Btrfs: add basic ...
5322
  	case BTRFS_IOC_BALANCE_V2:
9ba1f6e44   Liu Bo   Btrfs: do not do ...
5323
  		return btrfs_ioctl_balance(file, argp);
837d5b6e4   Ilya Dryomov   Btrfs: allow for ...
5324
  	case BTRFS_IOC_BALANCE_CTL:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5325
  		return btrfs_ioctl_balance_ctl(fs_info, arg);
19a39dce3   Ilya Dryomov   Btrfs: add balanc...
5326
  	case BTRFS_IOC_BALANCE_PROGRESS:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5327
  		return btrfs_ioctl_balance_progress(fs_info, argp);
8ea05e3a4   Alexander Block   Btrfs: introduce ...
5328
5329
  	case BTRFS_IOC_SET_RECEIVED_SUBVOL:
  		return btrfs_ioctl_set_received_subvol(file, argp);
abccd00f8   Hugo Mills   btrfs: Fix 32/64-...
5330
5331
5332
5333
  #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 ...
5334
5335
  	case BTRFS_IOC_SEND:
  		return btrfs_ioctl_send(file, argp);
c11d2c236   Stefan Behrens   Btrfs: add ioctl ...
5336
  	case BTRFS_IOC_GET_DEV_STATS:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5337
  		return btrfs_ioctl_get_dev_stats(fs_info, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5338
  	case BTRFS_IOC_QUOTA_CTL:
905b0dda0   Miao Xie   Btrfs: get write ...
5339
  		return btrfs_ioctl_quota_ctl(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5340
  	case BTRFS_IOC_QGROUP_ASSIGN:
905b0dda0   Miao Xie   Btrfs: get write ...
5341
  		return btrfs_ioctl_qgroup_assign(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5342
  	case BTRFS_IOC_QGROUP_CREATE:
905b0dda0   Miao Xie   Btrfs: get write ...
5343
  		return btrfs_ioctl_qgroup_create(file, argp);
5d13a37bd   Arne Jansen   Btrfs: add qgroup...
5344
  	case BTRFS_IOC_QGROUP_LIMIT:
905b0dda0   Miao Xie   Btrfs: get write ...
5345
  		return btrfs_ioctl_qgroup_limit(file, argp);
2f2320360   Jan Schmidt   Btrfs: rescan for...
5346
5347
5348
5349
  	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 ...
5350
5351
  	case BTRFS_IOC_QUOTA_RESCAN_WAIT:
  		return btrfs_ioctl_quota_rescan_wait(file, argp);
3f6bcfbd4   Stefan Behrens   Btrfs: add suppor...
5352
  	case BTRFS_IOC_DEV_REPLACE:
2ff7e61e0   Jeff Mahoney   btrfs: take an fs...
5353
  		return btrfs_ioctl_dev_replace(fs_info, argp);
867ab667e   jeff.liu   Btrfs: Add a new ...
5354
5355
  	case BTRFS_IOC_GET_FSLABEL:
  		return btrfs_ioctl_get_fslabel(file, argp);
a8bfd4abe   jeff.liu   Btrfs: set/change...
5356
5357
  	case BTRFS_IOC_SET_FSLABEL:
  		return btrfs_ioctl_set_fslabel(file, argp);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5358
  	case BTRFS_IOC_GET_SUPPORTED_FEATURES:
d5131b658   David Sterba   btrfs: drop unuse...
5359
  		return btrfs_ioctl_get_supported_features(argp);
2eaa055fa   Jeff Mahoney   btrfs: add ioctls...
5360
5361
5362
5363
  	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 ...
5364
5365
5366
5367
  	}
  
  	return -ENOTTY;
  }
4c63c2454   Luke Dashjr   btrfs: bugfix: ha...
5368
5369
5370
5371
  
  #ifdef CONFIG_COMPAT
  long btrfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  {
2a3622491   Jeff Mahoney   btrfs: fix btrfs_...
5372
5373
5374
5375
  	/*
  	 * These all access 32-bit values anyway so no further
  	 * handling is necessary.
  	 */
4c63c2454   Luke Dashjr   btrfs: bugfix: ha...
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
  	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...
5386
5387
5388
5389
5390
  	}
  
  	return btrfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
  }
  #endif