Blame view

fs/btrfs/ioctl.c 74.4 KB
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  /*
   * Copyright (C) 2007 Oracle.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License v2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
  
  #include <linux/kernel.h>
  #include <linux/bio.h>
  #include <linux/buffer_head.h>
  #include <linux/file.h>
  #include <linux/fs.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
24
  #include <linux/fsnotify.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
25
26
27
28
29
  #include <linux/pagemap.h>
  #include <linux/highmem.h>
  #include <linux/time.h>
  #include <linux/init.h>
  #include <linux/string.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
30
  #include <linux/backing-dev.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
31
  #include <linux/mount.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
32
  #include <linux/mpage.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
33
  #include <linux/namei.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
34
35
36
37
38
  #include <linux/swap.h>
  #include <linux/writeback.h>
  #include <linux/statfs.h>
  #include <linux/compat.h>
  #include <linux/bit_spinlock.h>
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
39
  #include <linux/security.h>
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
40
  #include <linux/xattr.h>
7ea394f11   Yan Zheng   Btrfs: Fix nodata...
41
  #include <linux/vmalloc.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
42
  #include <linux/slab.h>
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
43
  #include <linux/blkdev.h>
4b4e25f2a   Chris Mason   Btrfs: compat cod...
44
  #include "compat.h"
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
45
46
47
48
49
50
51
  #include "ctree.h"
  #include "disk-io.h"
  #include "transaction.h"
  #include "btrfs_inode.h"
  #include "ioctl.h"
  #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"
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
55

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  /* 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...
86
87
88
89
90
91
92
  	if (flags & BTRFS_INODE_NODATACOW)
  		iflags |= FS_NOCOW_FL;
  
  	if ((flags & BTRFS_INODE_COMPRESS) && !(flags & BTRFS_INODE_NOCOMPRESS))
  		iflags |= FS_COMPR_FL;
  	else if (flags & BTRFS_INODE_NOCOMPRESS)
  		iflags |= FS_NOCOMP_FL;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
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
  
  	return iflags;
  }
  
  /*
   * Update inode->i_flags based on the btrfs internal flags.
   */
  void btrfs_update_iflags(struct inode *inode)
  {
  	struct btrfs_inode *ip = BTRFS_I(inode);
  
  	inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC);
  
  	if (ip->flags & BTRFS_INODE_SYNC)
  		inode->i_flags |= S_SYNC;
  	if (ip->flags & BTRFS_INODE_IMMUTABLE)
  		inode->i_flags |= S_IMMUTABLE;
  	if (ip->flags & BTRFS_INODE_APPEND)
  		inode->i_flags |= S_APPEND;
  	if (ip->flags & BTRFS_INODE_NOATIME)
  		inode->i_flags |= S_NOATIME;
  	if (ip->flags & BTRFS_INODE_DIRSYNC)
  		inode->i_flags |= S_DIRSYNC;
  }
  
  /*
   * Inherit flags from the parent inode.
   *
e27425d61   Josef Bacik   Btrfs: only inher...
121
   * Currently only the compression flags and the cow flags are inherited.
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
122
123
124
   */
  void btrfs_inherit_iflags(struct inode *inode, struct inode *dir)
  {
0b4dcea57   Chris Mason   Btrfs: fix oops w...
125
126
127
128
129
130
  	unsigned int flags;
  
  	if (!dir)
  		return;
  
  	flags = BTRFS_I(dir)->flags;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
131

e27425d61   Josef Bacik   Btrfs: only inher...
132
133
134
135
136
137
138
139
140
141
  	if (flags & BTRFS_INODE_NOCOMPRESS) {
  		BTRFS_I(inode)->flags &= ~BTRFS_INODE_COMPRESS;
  		BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
  	} else if (flags & BTRFS_INODE_COMPRESS) {
  		BTRFS_I(inode)->flags &= ~BTRFS_INODE_NOCOMPRESS;
  		BTRFS_I(inode)->flags |= BTRFS_INODE_COMPRESS;
  	}
  
  	if (flags & BTRFS_INODE_NODATACOW)
  		BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
142

6cbff00f4   Christoph Hellwig   Btrfs: implement ...
143
144
145
146
147
148
149
150
151
152
153
154
  	btrfs_update_iflags(inode);
  }
  
  static int btrfs_ioctl_getflags(struct file *file, void __user *arg)
  {
  	struct btrfs_inode *ip = BTRFS_I(file->f_path.dentry->d_inode);
  	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...
155
156
157
158
159
  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
160
161
  		      FS_NOCOMP_FL | FS_COMPR_FL |
  		      FS_NOCOW_FL))
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
162
163
164
165
  		return -EOPNOTSUPP;
  
  	if ((flags & FS_NOCOMP_FL) && (flags & FS_COMPR_FL))
  		return -EINVAL;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
166
167
  	return 0;
  }
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
168
169
170
171
172
173
174
175
  static int btrfs_ioctl_setflags(struct file *file, void __user *arg)
  {
  	struct inode *inode = file->f_path.dentry->d_inode;
  	struct btrfs_inode *ip = BTRFS_I(inode);
  	struct btrfs_root *root = ip->root;
  	struct btrfs_trans_handle *trans;
  	unsigned int flags, oldflags;
  	int ret;
b83cc9693   Li Zefan   Btrfs: Add readon...
176
177
  	if (btrfs_root_readonly(root))
  		return -EROFS;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
178
179
  	if (copy_from_user(&flags, arg, sizeof(flags)))
  		return -EFAULT;
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
180
181
182
  	ret = check_flags(flags);
  	if (ret)
  		return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
183

2e1496707   Serge E. Hallyn   userns: rename is...
184
  	if (!inode_owner_or_capable(inode))
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
185
186
187
188
189
190
191
192
193
194
195
196
  		return -EACCES;
  
  	mutex_lock(&inode->i_mutex);
  
  	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;
  		}
  	}
a561be710   Al Viro   switch a bunch of...
197
  	ret = mnt_want_write_file(file);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  	if (ret)
  		goto out_unlock;
  
  	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;
e1e8fb6a1   Li Zefan   fs: remove FS_COW_FL
225
226
227
228
  	if (flags & FS_NOCOW_FL)
  		ip->flags |= BTRFS_INODE_NODATACOW;
  	else
  		ip->flags &= ~BTRFS_INODE_NODATACOW;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
229

75e7cb7fe   Liu Bo   Btrfs: Per file/d...
230
231
232
233
234
235
236
237
238
239
240
  	/*
  	 * 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;
  	} else if (flags & FS_COMPR_FL) {
  		ip->flags |= BTRFS_INODE_COMPRESS;
  		ip->flags &= ~BTRFS_INODE_NOCOMPRESS;
ebcb904df   Li Zefan   Btrfs: fix FS_IOC...
241
242
  	} else {
  		ip->flags &= ~(BTRFS_INODE_COMPRESS | BTRFS_INODE_NOCOMPRESS);
75e7cb7fe   Liu Bo   Btrfs: Per file/d...
243
  	}
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
244

7a7eaa40a   Josef Bacik   Btrfs: take away ...
245
  	trans = btrfs_join_transaction(root);
3612b4959   Tsutomu Itoh   btrfs: fix return...
246
  	BUG_ON(IS_ERR(trans));
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
247

306424cc8   Li Zefan   Btrfs: fix ctime ...
248
249
  	btrfs_update_iflags(inode);
  	inode->i_ctime = CURRENT_TIME;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
250
251
  	ret = btrfs_update_inode(trans, root, inode);
  	BUG_ON(ret);
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
252
  	btrfs_end_transaction(trans, root);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
253
  	mnt_drop_write_file(file);
2d4e6f6ad   liubo   Btrfs: fix return...
254
255
  
  	ret = 0;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
256
257
   out_unlock:
  	mutex_unlock(&inode->i_mutex);
2d4e6f6ad   liubo   Btrfs: fix return...
258
  	return ret;
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
259
260
261
262
263
264
265
266
  }
  
  static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
  {
  	struct inode *inode = file->f_path.dentry->d_inode;
  
  	return put_user(inode->i_generation, arg);
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
267

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
268
269
270
271
272
273
274
275
276
  static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
  {
  	struct btrfs_root *root = fdentry(file)->d_sb->s_fs_info;
  	struct btrfs_fs_info *fs_info = root->fs_info;
  	struct btrfs_device *device;
  	struct request_queue *q;
  	struct fstrim_range range;
  	u64 minlen = ULLONG_MAX;
  	u64 num_devices = 0;
6c41761fc   David Sterba   btrfs: separate s...
277
  	u64 total_bytes = btrfs_super_total_bytes(root->fs_info->super_copy);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
278
279
280
281
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
1f78160ce   Xiao Guangrong   Btrfs: using rcu ...
282
283
284
  	rcu_read_lock();
  	list_for_each_entry_rcu(device, &fs_info->fs_devices->devices,
  				dev_list) {
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
285
286
287
288
289
290
291
292
293
  		if (!device->bdev)
  			continue;
  		q = bdev_get_queue(device->bdev);
  		if (blk_queue_discard(q)) {
  			num_devices++;
  			minlen = min((u64)q->limits.discard_granularity,
  				     minlen);
  		}
  	}
1f78160ce   Xiao Guangrong   Btrfs: using rcu ...
294
  	rcu_read_unlock();
f4c697e64   Lukas Czerner   btrfs: return EIN...
295

f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
296
297
  	if (!num_devices)
  		return -EOPNOTSUPP;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
298
299
  	if (copy_from_user(&range, arg, sizeof(range)))
  		return -EFAULT;
f4c697e64   Lukas Czerner   btrfs: return EIN...
300
301
  	if (range.start > total_bytes)
  		return -EINVAL;
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
302

f4c697e64   Lukas Czerner   btrfs: return EIN...
303
  	range.len = min(range.len, total_bytes - range.start);
f7039b1d5   Li Dongyang   Btrfs: add btrfs_...
304
305
306
307
308
309
310
311
312
313
  	range.minlen = max(range.minlen, minlen);
  	ret = btrfs_trim_fs(root, &range);
  	if (ret < 0)
  		return ret;
  
  	if (copy_to_user(arg, &range, sizeof(range)))
  		return -EFAULT;
  
  	return 0;
  }
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
314
315
  static noinline int create_subvol(struct btrfs_root *root,
  				  struct dentry *dentry,
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
316
317
  				  char *name, int namelen,
  				  u64 *async_transid)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
318
319
320
321
322
323
  {
  	struct btrfs_trans_handle *trans;
  	struct btrfs_key key;
  	struct btrfs_root_item root_item;
  	struct btrfs_inode_item *inode_item;
  	struct extent_buffer *leaf;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
324
  	struct btrfs_root *new_root;
2fbe8c8ad   Al Viro   get rid of useles...
325
  	struct dentry *parent = dentry->d_parent;
6a9122130   Josef Bacik   Btrfs: use dget_p...
326
  	struct inode *dir;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
327
328
329
330
  	int ret;
  	int err;
  	u64 objectid;
  	u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID;
3de4586c5   Chris Mason   Btrfs: Allow subv...
331
  	u64 index = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
332

581bb0509   Li Zefan   Btrfs: Cache free...
333
  	ret = btrfs_find_free_objectid(root->fs_info->tree_root, &objectid);
2fbe8c8ad   Al Viro   get rid of useles...
334
  	if (ret)
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
335
  		return ret;
6a9122130   Josef Bacik   Btrfs: use dget_p...
336
337
  
  	dir = parent->d_inode;
9ed74f2db   Josef Bacik   Btrfs: proper -EN...
338
339
340
341
342
343
  	/*
  	 * 1 - inode item
  	 * 2 - refs
  	 * 1 - root item
  	 * 2 - dir items
  	 */
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
344
  	trans = btrfs_start_transaction(root, 6);
2fbe8c8ad   Al Viro   get rid of useles...
345
  	if (IS_ERR(trans))
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
346
  		return PTR_ERR(trans);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
347

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
348
349
  	leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
  				      0, objectid, NULL, 0, 0, 0);
8e8a1e31f   Josef Bacik   Btrfs: Fix a few ...
350
351
352
353
  	if (IS_ERR(leaf)) {
  		ret = PTR_ERR(leaf);
  		goto fail;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
354

5d4f98a28   Yan Zheng   Btrfs: Mixed back...
355
  	memset_extent_buffer(leaf, 0, 0, sizeof(struct btrfs_header));
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
356
357
  	btrfs_set_header_bytenr(leaf, leaf->start);
  	btrfs_set_header_generation(leaf, trans->transid);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
358
  	btrfs_set_header_backref_rev(leaf, BTRFS_MIXED_BACKREF_REV);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
359
360
361
362
363
  	btrfs_set_header_owner(leaf, objectid);
  
  	write_extent_buffer(leaf, root->fs_info->fsid,
  			    (unsigned long)btrfs_header_fsid(leaf),
  			    BTRFS_FSID_SIZE);
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
364
365
366
  	write_extent_buffer(leaf, root->fs_info->chunk_tree_uuid,
  			    (unsigned long)btrfs_header_chunk_tree_uuid(leaf),
  			    BTRFS_UUID_SIZE);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
367
368
369
370
371
372
373
  	btrfs_mark_buffer_dirty(leaf);
  
  	inode_item = &root_item.inode;
  	memset(inode_item, 0, sizeof(*inode_item));
  	inode_item->generation = cpu_to_le64(1);
  	inode_item->size = cpu_to_le64(3);
  	inode_item->nlink = cpu_to_le32(1);
a76a3cd40   Yan Zheng   Btrfs: Count spac...
374
  	inode_item->nbytes = cpu_to_le64(root->leafsize);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
375
  	inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
08fe4db17   Li Zefan   Btrfs: Fix uninit...
376
377
378
  	root_item.flags = 0;
  	root_item.byte_limit = 0;
  	inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
379
  	btrfs_set_root_bytenr(&root_item, leaf->start);
84234f3a1   Yan Zheng   Btrfs: Add root t...
380
  	btrfs_set_root_generation(&root_item, trans->transid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
381
382
  	btrfs_set_root_level(&root_item, 0);
  	btrfs_set_root_refs(&root_item, 1);
86b9f2eca   Yan, Zheng   Btrfs: Fix per ro...
383
  	btrfs_set_root_used(&root_item, leaf->len);
80ff38566   Yan Zheng   Btrfs: update nod...
384
  	btrfs_set_root_last_snapshot(&root_item, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
385
386
387
  
  	memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
  	root_item.drop_level = 0;
925baeddc   Chris Mason   Btrfs: Start btre...
388
  	btrfs_tree_unlock(leaf);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
389
390
391
392
393
394
  	free_extent_buffer(leaf);
  	leaf = NULL;
  
  	btrfs_set_root_dirid(&root_item, new_dirid);
  
  	key.objectid = objectid;
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
395
  	key.offset = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
396
397
398
399
400
  	btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
  	ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
  				&root_item);
  	if (ret)
  		goto fail;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
401
402
403
404
405
  	key.offset = (u64)-1;
  	new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
  	BUG_ON(IS_ERR(new_root));
  
  	btrfs_record_root_in_trans(trans, new_root);
d82a6f1d7   Josef Bacik   Btrfs: kill BTRFS...
406
  	ret = btrfs_create_subvol_root(trans, new_root, new_dirid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
407
408
409
  	/*
  	 * insert the directory item
  	 */
3de4586c5   Chris Mason   Btrfs: Allow subv...
410
411
412
413
  	ret = btrfs_set_inode_index(dir, &index);
  	BUG_ON(ret);
  
  	ret = btrfs_insert_dir_item(trans, root,
16cdcec73   Miao Xie   btrfs: implement ...
414
  				    name, namelen, dir, &key,
3de4586c5   Chris Mason   Btrfs: Allow subv...
415
  				    BTRFS_FT_DIR, index);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
416
417
  	if (ret)
  		goto fail;
0660b5af3   Chris Mason   Btrfs: Add backre...
418

52c261799   Yan Zheng   Btrfs: update dir...
419
420
421
  	btrfs_i_size_write(dir, dir->i_size + namelen * 2);
  	ret = btrfs_update_inode(trans, root, dir);
  	BUG_ON(ret);
0660b5af3   Chris Mason   Btrfs: Add backre...
422
  	ret = btrfs_add_root_ref(trans, root->fs_info->tree_root,
4df27c4d5   Yan, Zheng   Btrfs: change how...
423
  				 objectid, root->root_key.objectid,
33345d015   Li Zefan   Btrfs: Always use...
424
  				 btrfs_ino(dir), index, name, namelen);
0660b5af3   Chris Mason   Btrfs: Add backre...
425

76dda93c6   Yan, Zheng   Btrfs: add snapsh...
426
  	BUG_ON(ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
427

76dda93c6   Yan, Zheng   Btrfs: add snapsh...
428
  	d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry));
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
429
  fail:
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
430
431
432
433
434
435
  	if (async_transid) {
  		*async_transid = trans->transid;
  		err = btrfs_commit_transaction_async(trans, root, 1);
  	} else {
  		err = btrfs_commit_transaction(trans, root);
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
436
437
  	if (err && !ret)
  		ret = err;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
438
439
  	return ret;
  }
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
440
  static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
b83cc9693   Li Zefan   Btrfs: Add readon...
441
442
  			   char *name, int namelen, u64 *async_transid,
  			   bool readonly)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
443
  {
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
444
  	struct inode *inode;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
445
446
  	struct btrfs_pending_snapshot *pending_snapshot;
  	struct btrfs_trans_handle *trans;
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
447
  	int ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
448
449
450
  
  	if (!root->ref_cows)
  		return -EINVAL;
3de4586c5   Chris Mason   Btrfs: Allow subv...
451
  	pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
452
453
454
455
  	if (!pending_snapshot)
  		return -ENOMEM;
  
  	btrfs_init_block_rsv(&pending_snapshot->block_rsv);
3de4586c5   Chris Mason   Btrfs: Allow subv...
456
  	pending_snapshot->dentry = dentry;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
457
  	pending_snapshot->root = root;
b83cc9693   Li Zefan   Btrfs: Add readon...
458
  	pending_snapshot->readonly = readonly;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
459
460
461
462
463
464
465
466
467
  
  	trans = btrfs_start_transaction(root->fs_info->extent_root, 5);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto fail;
  	}
  
  	ret = btrfs_snap_reserve_metadata(trans, pending_snapshot);
  	BUG_ON(ret);
8351583e3   Josef Bacik   Btrfs: protect th...
468
  	spin_lock(&root->fs_info->trans_lock);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
469
470
  	list_add(&pending_snapshot->list,
  		 &trans->transaction->pending_snapshots);
8351583e3   Josef Bacik   Btrfs: protect th...
471
  	spin_unlock(&root->fs_info->trans_lock);
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
472
473
474
475
476
477
478
479
  	if (async_transid) {
  		*async_transid = trans->transid;
  		ret = btrfs_commit_transaction_async(trans,
  				     root->fs_info->extent_root, 1);
  	} else {
  		ret = btrfs_commit_transaction(trans,
  					       root->fs_info->extent_root);
  	}
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
480
  	BUG_ON(ret);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
481
482
483
484
  
  	ret = pending_snapshot->error;
  	if (ret)
  		goto fail;
66b4ffd11   Josef Bacik   Btrfs: handle err...
485
486
487
  	ret = btrfs_orphan_cleanup(pending_snapshot->snap);
  	if (ret)
  		goto fail;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
488

2fbe8c8ad   Al Viro   get rid of useles...
489
  	inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
2e4bfab97   Yan, Zheng   Btrfs: Avoid orph...
490
491
492
493
494
495
496
497
  	if (IS_ERR(inode)) {
  		ret = PTR_ERR(inode);
  		goto fail;
  	}
  	BUG_ON(!inode);
  	d_instantiate(dentry, inode);
  	ret = 0;
  fail:
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
498
  	kfree(pending_snapshot);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
499
500
  	return ret;
  }
4260f7c75   Sage Weil   Btrfs: allow subv...
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
  /*  copy of check_sticky in fs/namei.c()
  * It's inline, so penalty for filesystems that don't use sticky bit is
  * minimal.
  */
  static inline int btrfs_check_sticky(struct inode *dir, struct inode *inode)
  {
  	uid_t fsuid = current_fsuid();
  
  	if (!(dir->i_mode & S_ISVTX))
  		return 0;
  	if (inode->i_uid == fsuid)
  		return 0;
  	if (dir->i_uid == fsuid)
  		return 0;
  	return !capable(CAP_FOWNER);
  }
  
  /*  copy of may_delete in fs/namei.c()
   *	Check whether we can remove a link victim from directory dir, check
   *  whether the type of victim is right.
   *  1. We can't do it if dir is read-only (done in permission())
   *  2. We should have write and exec permissions on dir
   *  3. We can't remove anything from append-only dir
   *  4. We can't do anything with immutable dir (done in permission())
   *  5. If the sticky bit on dir is set we should either
   *	a. be owner of dir, or
   *	b. be owner of victim, or
   *	c. have CAP_FOWNER capability
   *  6. If the victim is append-only or immutable we can't do antyhing with
   *     links pointing to it.
   *  7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
   *  8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
   *  9. We can't remove a root or mountpoint.
   * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
   *     nfs_async_unlink().
   */
  
  static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir)
  {
  	int error;
  
  	if (!victim->d_inode)
  		return -ENOENT;
  
  	BUG_ON(victim->d_parent->d_inode != dir);
  	audit_inode_child(victim, dir);
  
  	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
  	if (error)
  		return error;
  	if (IS_APPEND(dir))
  		return -EPERM;
  	if (btrfs_check_sticky(dir, victim->d_inode)||
  		IS_APPEND(victim->d_inode)||
  	    IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
  		return -EPERM;
  	if (isdir) {
  		if (!S_ISDIR(victim->d_inode->i_mode))
  			return -ENOTDIR;
  		if (IS_ROOT(victim))
  			return -EBUSY;
  	} else if (S_ISDIR(victim->d_inode->i_mode))
  		return -EISDIR;
  	if (IS_DEADDIR(dir))
  		return -ENOENT;
  	if (victim->d_flags & DCACHE_NFSFS_RENAMED)
  		return -EBUSY;
  	return 0;
  }
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
  /* copy of may_create in fs/namei.c() */
  static inline int btrfs_may_create(struct inode *dir, struct dentry *child)
  {
  	if (child->d_inode)
  		return -EEXIST;
  	if (IS_DEADDIR(dir))
  		return -ENOENT;
  	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
  }
  
  /*
   * Create a new subvolume below @parent.  This is largely modeled after
   * sys_mkdirat and vfs_mkdir, but we only do a single component lookup
   * inside this filesystem so it's quite a bit simpler.
   */
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
585
586
  static noinline int btrfs_mksubvol(struct path *parent,
  				   char *name, int namelen,
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
587
  				   struct btrfs_root *snap_src,
b83cc9693   Li Zefan   Btrfs: Add readon...
588
  				   u64 *async_transid, bool readonly)
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
589
  {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
590
  	struct inode *dir  = parent->dentry->d_inode;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
591
592
  	struct dentry *dentry;
  	int error;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
593
  	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
594
595
596
597
598
599
600
601
602
  
  	dentry = lookup_one_len(name, parent->dentry, namelen);
  	error = PTR_ERR(dentry);
  	if (IS_ERR(dentry))
  		goto out_unlock;
  
  	error = -EEXIST;
  	if (dentry->d_inode)
  		goto out_dput;
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
603
604
605
  	error = mnt_want_write(parent->mnt);
  	if (error)
  		goto out_dput;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
606
  	error = btrfs_may_create(dir, dentry);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
607
608
  	if (error)
  		goto out_drop_write;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
609
610
611
612
  	down_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
  
  	if (btrfs_root_refs(&BTRFS_I(dir)->root->root_item) == 0)
  		goto out_up_read;
3de4586c5   Chris Mason   Btrfs: Allow subv...
613
  	if (snap_src) {
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
614
  		error = create_snapshot(snap_src, dentry,
b83cc9693   Li Zefan   Btrfs: Add readon...
615
  					name, namelen, async_transid, readonly);
3de4586c5   Chris Mason   Btrfs: Allow subv...
616
  	} else {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
617
  		error = create_subvol(BTRFS_I(dir)->root, dentry,
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
618
  				      name, namelen, async_transid);
3de4586c5   Chris Mason   Btrfs: Allow subv...
619
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
620
621
622
623
  	if (!error)
  		fsnotify_mkdir(dir, dentry);
  out_up_read:
  	up_read(&BTRFS_I(dir)->root->fs_info->subvol_sem);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
624
625
626
627
628
  out_drop_write:
  	mnt_drop_write(parent->mnt);
  out_dput:
  	dput(dentry);
  out_unlock:
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
629
  	mutex_unlock(&dir->i_mutex);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
630
631
  	return error;
  }
4cb5300bc   Chris Mason   Btrfs: add mount ...
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
  /*
   * When we're defragging a range, we don't want to kick it off again
   * if it is really just waiting for delalloc to send it down.
   * If we find a nice big extent or delalloc range for the bytes in the
   * file you want to defrag, we return 0 to let you know to skip this
   * part of the file
   */
  static int check_defrag_in_cache(struct inode *inode, u64 offset, int thresh)
  {
  	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
  	struct extent_map *em = NULL;
  	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
  	u64 end;
  
  	read_lock(&em_tree->lock);
  	em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE);
  	read_unlock(&em_tree->lock);
  
  	if (em) {
  		end = extent_map_end(em);
  		free_extent_map(em);
  		if (end - offset > thresh)
  			return 0;
  	}
  	/* if we already have a nice delalloc here, just stop */
  	thresh /= 2;
  	end = count_range_bits(io_tree, &offset, offset + thresh,
  			       thresh, EXTENT_DELALLOC, 1);
  	if (end >= thresh)
  		return 0;
  	return 1;
  }
  
  /*
   * helper function to walk through a file and find extents
   * newer than a specific transid, and smaller than thresh.
   *
   * This is used by the defragging code to find new and small
   * extents
   */
  static int find_new_extents(struct btrfs_root *root,
  			    struct inode *inode, u64 newer_than,
  			    u64 *off, int thresh)
  {
  	struct btrfs_path *path;
  	struct btrfs_key min_key;
  	struct btrfs_key max_key;
  	struct extent_buffer *leaf;
  	struct btrfs_file_extent_item *extent;
  	int type;
  	int ret;
a4689d2bd   David Sterba   btrfs: use btrfs_...
683
  	u64 ino = btrfs_ino(inode);
4cb5300bc   Chris Mason   Btrfs: add mount ...
684
685
686
687
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
a4689d2bd   David Sterba   btrfs: use btrfs_...
688
  	min_key.objectid = ino;
4cb5300bc   Chris Mason   Btrfs: add mount ...
689
690
  	min_key.type = BTRFS_EXTENT_DATA_KEY;
  	min_key.offset = *off;
a4689d2bd   David Sterba   btrfs: use btrfs_...
691
  	max_key.objectid = ino;
4cb5300bc   Chris Mason   Btrfs: add mount ...
692
693
694
695
696
697
698
699
700
701
  	max_key.type = (u8)-1;
  	max_key.offset = (u64)-1;
  
  	path->keep_locks = 1;
  
  	while(1) {
  		ret = btrfs_search_forward(root, &min_key, &max_key,
  					   path, 0, newer_than);
  		if (ret != 0)
  			goto none;
a4689d2bd   David Sterba   btrfs: use btrfs_...
702
  		if (min_key.objectid != ino)
4cb5300bc   Chris Mason   Btrfs: add mount ...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
  			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;
  		}
  
  		if (min_key.offset == (u64)-1)
  			goto none;
  
  		min_key.offset++;
  		btrfs_release_path(path);
  	}
  none:
  	btrfs_free_path(path);
  	return -ENOENT;
  }
940100a4a   Chris Mason   Btrfs: be more se...
730
  static int should_defrag_range(struct inode *inode, u64 start, u64 len,
1e701a329   Chris Mason   Btrfs: add new de...
731
732
  			       int thresh, u64 *last_len, u64 *skip,
  			       u64 *defrag_end)
940100a4a   Chris Mason   Btrfs: be more se...
733
734
735
736
737
738
739
  {
  	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;
  	int ret = 1;
  
  	/*
008873eaf   Li Zefan   Btrfs: honor exte...
740
  	 * make sure that once we start defragging an extent, we keep on
940100a4a   Chris Mason   Btrfs: be more se...
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
  	 * defragging it
  	 */
  	if (start < *defrag_end)
  		return 1;
  
  	*skip = 0;
  
  	/*
  	 * hopefully we have this extent in the tree already, try without
  	 * the full extent lock
  	 */
  	read_lock(&em_tree->lock);
  	em = lookup_extent_mapping(em_tree, start, len);
  	read_unlock(&em_tree->lock);
  
  	if (!em) {
  		/* get the big lock and read metadata off disk */
  		lock_extent(io_tree, start, start + len - 1, GFP_NOFS);
  		em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
  		unlock_extent(io_tree, start, start + len - 1, GFP_NOFS);
6cf8bfbf5   Dan Carpenter   Btrfs: check btrf...
761
  		if (IS_ERR(em))
940100a4a   Chris Mason   Btrfs: be more se...
762
763
764
765
766
767
768
769
770
771
  			return 0;
  	}
  
  	/* this will cover holes, and inline extents */
  	if (em->block_start >= EXTENT_MAP_LAST_BYTE)
  		ret = 0;
  
  	/*
  	 * we hit a real extent, if it is big don't bother defragging it again
  	 */
1e701a329   Chris Mason   Btrfs: add new de...
772
  	if ((*last_len == 0 || *last_len >= thresh) && em->len >= thresh)
940100a4a   Chris Mason   Btrfs: be more se...
773
774
775
776
777
778
779
780
781
782
783
  		ret = 0;
  
  	/*
  	 * 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...
784
785
786
787
788
789
790
791
792
793
  		*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 ...
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
  /*
   * 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,
  				    int num_pages)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
810
  {
4cb5300bc   Chris Mason   Btrfs: add mount ...
811
812
813
814
815
816
817
  	unsigned long file_end;
  	u64 isize = i_size_read(inode);
  	u64 page_start;
  	u64 page_end;
  	int ret;
  	int i;
  	int i_done;
3eaa28852   Chris Mason   Btrfs: Fix the de...
818
  	struct btrfs_ordered_extent *ordered;
4cb5300bc   Chris Mason   Btrfs: add mount ...
819
  	struct extent_state *cached_state = NULL;
3b16a4e3c   Josef Bacik   Btrfs: use the in...
820
  	gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
4cb5300bc   Chris Mason   Btrfs: add mount ...
821
822
823
824
  
  	if (isize == 0)
  		return 0;
  	file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
660d3f6cd   Josef Bacik   Btrfs: fix how we...
825
  	mutex_lock(&inode->i_mutex);
4cb5300bc   Chris Mason   Btrfs: add mount ...
826
827
  	ret = btrfs_delalloc_reserve_space(inode,
  					   num_pages << PAGE_CACHE_SHIFT);
660d3f6cd   Josef Bacik   Btrfs: fix how we...
828
  	mutex_unlock(&inode->i_mutex);
4cb5300bc   Chris Mason   Btrfs: add mount ...
829
830
831
832
833
834
835
836
837
  	if (ret)
  		return ret;
  again:
  	ret = 0;
  	i_done = 0;
  
  	/* step one, lock all the pages */
  	for (i = 0; i < num_pages; i++) {
  		struct page *page;
a94733d0b   Josef Bacik   Btrfs: use find_o...
838
  		page = find_or_create_page(inode->i_mapping,
3b16a4e3c   Josef Bacik   Btrfs: use the in...
839
  					    start_index + i, mask);
4cb5300bc   Chris Mason   Btrfs: add mount ...
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
  		if (!page)
  			break;
  
  		if (!PageUptodate(page)) {
  			btrfs_readpage(NULL, page);
  			lock_page(page);
  			if (!PageUptodate(page)) {
  				unlock_page(page);
  				page_cache_release(page);
  				ret = -EIO;
  				break;
  			}
  		}
  		isize = i_size_read(inode);
  		file_end = (isize - 1) >> PAGE_CACHE_SHIFT;
  		if (!isize || page->index > file_end ||
  		    page->mapping != inode->i_mapping) {
  			/* whoops, we blew past eof, skip this page */
  			unlock_page(page);
  			page_cache_release(page);
  			break;
  		}
  		pages[i] = page;
  		i_done++;
  	}
  	if (!i_done || ret)
  		goto out;
  
  	if (!(inode->i_sb->s_flags & MS_ACTIVE))
  		goto out;
  
  	/*
  	 * so now we have a nice long stream of locked
  	 * and up to date pages, lets wait on them
  	 */
  	for (i = 0; i < i_done; i++)
  		wait_on_page_writeback(pages[i]);
  
  	page_start = page_offset(pages[0]);
  	page_end = page_offset(pages[i_done - 1]) + PAGE_CACHE_SIZE;
  
  	lock_extent_bits(&BTRFS_I(inode)->io_tree,
  			 page_start, page_end - 1, 0, &cached_state,
  			 GFP_NOFS);
  	ordered = btrfs_lookup_first_ordered_extent(inode, page_end - 1);
  	if (ordered &&
  	    ordered->file_offset + ordered->len > page_start &&
  	    ordered->file_offset < page_end) {
  		btrfs_put_ordered_extent(ordered);
  		unlock_extent_cached(&BTRFS_I(inode)->io_tree,
  				     page_start, page_end - 1,
  				     &cached_state, GFP_NOFS);
  		for (i = 0; i < i_done; i++) {
  			unlock_page(pages[i]);
  			page_cache_release(pages[i]);
  		}
  		btrfs_wait_ordered_range(inode, page_start,
  					 page_end - page_start);
  		goto again;
  	}
  	if (ordered)
  		btrfs_put_ordered_extent(ordered);
  
  	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
  			  page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
  			  EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
  			  GFP_NOFS);
  
  	if (i_done != num_pages) {
9e0baf60d   Josef Bacik   Btrfs: fix enospc...
909
910
911
  		spin_lock(&BTRFS_I(inode)->lock);
  		BTRFS_I(inode)->outstanding_extents++;
  		spin_unlock(&BTRFS_I(inode)->lock);
4cb5300bc   Chris Mason   Btrfs: add mount ...
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
  		btrfs_delalloc_release_space(inode,
  				     (num_pages - i_done) << PAGE_CACHE_SHIFT);
  	}
  
  
  	btrfs_set_extent_delalloc(inode, page_start, page_end - 1,
  				  &cached_state);
  
  	unlock_extent_cached(&BTRFS_I(inode)->io_tree,
  			     page_start, page_end - 1, &cached_state,
  			     GFP_NOFS);
  
  	for (i = 0; i < i_done; i++) {
  		clear_page_dirty_for_io(pages[i]);
  		ClearPageChecked(pages[i]);
  		set_page_extent_mapped(pages[i]);
  		set_page_dirty(pages[i]);
  		unlock_page(pages[i]);
  		page_cache_release(pages[i]);
  	}
  	return i_done;
  out:
  	for (i = 0; i < i_done; i++) {
  		unlock_page(pages[i]);
  		page_cache_release(pages[i]);
  	}
  	btrfs_delalloc_release_space(inode, num_pages << PAGE_CACHE_SHIFT);
  	return ret;
  
  }
  
  int btrfs_defrag_file(struct inode *inode, struct file *file,
  		      struct btrfs_ioctl_defrag_range_args *range,
  		      u64 newer_than, unsigned long max_to_defrag)
  {
  	struct btrfs_root *root = BTRFS_I(inode)->root;
1a419d85a   Li Zefan   btrfs: Allow to s...
948
  	struct btrfs_super_block *disk_super;
4cb5300bc   Chris Mason   Btrfs: add mount ...
949
  	struct file_ra_state *ra = NULL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
950
  	unsigned long last_index;
151a31b25   Li Zefan   Btrfs: use i_size...
951
  	u64 isize = i_size_read(inode);
1a419d85a   Li Zefan   btrfs: Allow to s...
952
  	u64 features;
940100a4a   Chris Mason   Btrfs: be more se...
953
954
955
  	u64 last_len = 0;
  	u64 skip = 0;
  	u64 defrag_end = 0;
4cb5300bc   Chris Mason   Btrfs: add mount ...
956
  	u64 newer_off = range->start;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
957
  	unsigned long i;
008873eaf   Li Zefan   Btrfs: honor exte...
958
  	unsigned long ra_index = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
959
  	int ret;
4cb5300bc   Chris Mason   Btrfs: add mount ...
960
  	int defrag_count = 0;
1a419d85a   Li Zefan   btrfs: Allow to s...
961
  	int compress_type = BTRFS_COMPRESS_ZLIB;
4cb5300bc   Chris Mason   Btrfs: add mount ...
962
  	int extent_thresh = range->extent_thresh;
008873eaf   Li Zefan   Btrfs: honor exte...
963
964
  	int max_cluster = (256 * 1024) >> PAGE_CACHE_SHIFT;
  	int cluster = max_cluster;
4cb5300bc   Chris Mason   Btrfs: add mount ...
965
966
967
968
969
  	u64 new_align = ~((u64)128 * 1024 - 1);
  	struct page **pages = NULL;
  
  	if (extent_thresh == 0)
  		extent_thresh = 256 * 1024;
1a419d85a   Li Zefan   btrfs: Allow to s...
970
971
972
973
974
975
976
  
  	if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS) {
  		if (range->compress_type > BTRFS_COMPRESS_TYPES)
  			return -EINVAL;
  		if (range->compress_type)
  			compress_type = range->compress_type;
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
977

151a31b25   Li Zefan   Btrfs: use i_size...
978
  	if (isize == 0)
940100a4a   Chris Mason   Btrfs: be more se...
979
  		return 0;
4cb5300bc   Chris Mason   Btrfs: add mount ...
980
981
982
983
984
985
986
987
988
989
990
991
  	/*
  	 * if we were not given a file, allocate a readahead
  	 * context
  	 */
  	if (!file) {
  		ra = kzalloc(sizeof(*ra), GFP_NOFS);
  		if (!ra)
  			return -ENOMEM;
  		file_ra_state_init(ra, inode->i_mapping);
  	} else {
  		ra = &file->f_ra;
  	}
008873eaf   Li Zefan   Btrfs: honor exte...
992
  	pages = kmalloc(sizeof(struct page *) * max_cluster,
4cb5300bc   Chris Mason   Btrfs: add mount ...
993
994
995
996
997
998
999
  			GFP_NOFS);
  	if (!pages) {
  		ret = -ENOMEM;
  		goto out_ra;
  	}
  
  	/* find the last page to defrag */
1e701a329   Chris Mason   Btrfs: add new de...
1000
  	if (range->start + range->len > range->start) {
151a31b25   Li Zefan   Btrfs: use i_size...
1001
  		last_index = min_t(u64, isize - 1,
1e701a329   Chris Mason   Btrfs: add new de...
1002
1003
  			 range->start + range->len - 1) >> PAGE_CACHE_SHIFT;
  	} else {
151a31b25   Li Zefan   Btrfs: use i_size...
1004
  		last_index = (isize - 1) >> PAGE_CACHE_SHIFT;
1e701a329   Chris Mason   Btrfs: add new de...
1005
  	}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
  	if (newer_than) {
  		ret = find_new_extents(root, inode, newer_than,
  				       &newer_off, 64 * 1024);
  		if (!ret) {
  			range->start = newer_off;
  			/*
  			 * we always align our defrag to help keep
  			 * the extents in the file evenly spaced
  			 */
  			i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1016
1017
1018
1019
1020
1021
  		} else
  			goto out_ra;
  	} else {
  		i = range->start >> PAGE_CACHE_SHIFT;
  	}
  	if (!max_to_defrag)
5ca496604   Li Zefan   Btrfs: fix wrong ...
1022
  		max_to_defrag = last_index;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1023

2a0f7f576   Li Zefan   Btrfs: fix recurs...
1024
1025
1026
1027
1028
1029
  	/*
  	 * 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 ...
1030
1031
1032
  	while (i <= last_index && defrag_count < max_to_defrag &&
  	       (i < (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
  		PAGE_CACHE_SHIFT)) {
4cb5300bc   Chris Mason   Btrfs: add mount ...
1033
1034
1035
1036
1037
1038
1039
1040
1041
  		/*
  		 * make sure we stop running if someone unmounts
  		 * the FS
  		 */
  		if (!(inode->i_sb->s_flags & MS_ACTIVE))
  			break;
  
  		if (!newer_than &&
  		    !should_defrag_range(inode, (u64)i << PAGE_CACHE_SHIFT,
1e701a329   Chris Mason   Btrfs: add new de...
1042
  					PAGE_CACHE_SIZE,
4cb5300bc   Chris Mason   Btrfs: add mount ...
1043
  					extent_thresh,
1e701a329   Chris Mason   Btrfs: add new de...
1044
  					&last_len, &skip,
940100a4a   Chris Mason   Btrfs: be more se...
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
  					&defrag_end)) {
  			unsigned long next;
  			/*
  			 * the should_defrag function tells us how much to skip
  			 * bump our counter by the suggested amount
  			 */
  			next = (skip + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
  			i = max(i + 1, next);
  			continue;
  		}
008873eaf   Li Zefan   Btrfs: honor exte...
1055
1056
1057
1058
1059
1060
1061
1062
  
  		if (!newer_than) {
  			cluster = (PAGE_CACHE_ALIGN(defrag_end) >>
  				   PAGE_CACHE_SHIFT) - i;
  			cluster = min(cluster, max_cluster);
  		} else {
  			cluster = max_cluster;
  		}
1e701a329   Chris Mason   Btrfs: add new de...
1063
  		if (range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)
1a419d85a   Li Zefan   btrfs: Allow to s...
1064
  			BTRFS_I(inode)->force_compress = compress_type;
940100a4a   Chris Mason   Btrfs: be more se...
1065

008873eaf   Li Zefan   Btrfs: honor exte...
1066
1067
1068
1069
1070
1071
  		if (i + cluster > ra_index) {
  			ra_index = max(i, ra_index);
  			btrfs_force_ra(inode->i_mapping, ra, file, ra_index,
  				       cluster);
  			ra_index += max_cluster;
  		}
940100a4a   Chris Mason   Btrfs: be more se...
1072

008873eaf   Li Zefan   Btrfs: honor exte...
1073
  		ret = cluster_pages_for_defrag(inode, pages, i, cluster);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1074
1075
1076
1077
1078
  		if (ret < 0)
  			goto out_ra;
  
  		defrag_count += ret;
  		balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret);
4cb5300bc   Chris Mason   Btrfs: add mount ...
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
  
  		if (newer_than) {
  			if (newer_off == (u64)-1)
  				break;
  
  			newer_off = max(newer_off + 1,
  					(u64)i << PAGE_CACHE_SHIFT);
  
  			ret = find_new_extents(root, inode,
  					       newer_than, &newer_off,
  					       64 * 1024);
  			if (!ret) {
  				range->start = newer_off;
  				i = (newer_off & new_align) >> PAGE_CACHE_SHIFT;
4cb5300bc   Chris Mason   Btrfs: add mount ...
1093
1094
  			} else {
  				break;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1095
  			}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1096
  		} else {
008873eaf   Li Zefan   Btrfs: honor exte...
1097
  			if (ret > 0) {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1098
  				i += ret;
008873eaf   Li Zefan   Btrfs: honor exte...
1099
1100
  				last_len += ret << PAGE_CACHE_SHIFT;
  			} else {
cbcc83265   Li Zefan   Btrfs: fix defrag...
1101
  				i++;
008873eaf   Li Zefan   Btrfs: honor exte...
1102
1103
  				last_len = 0;
  			}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1104
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1105
  	}
1e701a329   Chris Mason   Btrfs: add new de...
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
  	if ((range->flags & BTRFS_DEFRAG_RANGE_START_IO))
  		filemap_flush(inode->i_mapping);
  
  	if ((range->flags & BTRFS_DEFRAG_RANGE_COMPRESS)) {
  		/* the filemap_flush will queue IO into the worker threads, but
  		 * we have to make sure the IO is actually started and that
  		 * ordered extents get created before we return
  		 */
  		atomic_inc(&root->fs_info->async_submit_draining);
  		while (atomic_read(&root->fs_info->nr_async_submits) ||
  		      atomic_read(&root->fs_info->async_delalloc_pages)) {
  			wait_event(root->fs_info->async_submit_wait,
  			   (atomic_read(&root->fs_info->nr_async_submits) == 0 &&
  			    atomic_read(&root->fs_info->async_delalloc_pages) == 0));
  		}
  		atomic_dec(&root->fs_info->async_submit_draining);
  
  		mutex_lock(&inode->i_mutex);
261507a02   Li Zefan   btrfs: Allow to a...
1124
  		BTRFS_I(inode)->force_compress = BTRFS_COMPRESS_NONE;
1e701a329   Chris Mason   Btrfs: add new de...
1125
1126
  		mutex_unlock(&inode->i_mutex);
  	}
6c41761fc   David Sterba   btrfs: separate s...
1127
  	disk_super = root->fs_info->super_copy;
1a419d85a   Li Zefan   btrfs: Allow to s...
1128
1129
1130
1131
1132
  	features = btrfs_super_incompat_flags(disk_super);
  	if (range->compress_type == BTRFS_COMPRESS_LZO) {
  		features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO;
  		btrfs_set_super_incompat_flags(disk_super, features);
  	}
60ccf82f5   Diego Calleja   btrfs: fix memory...
1133
  	ret = defrag_count;
940100a4a   Chris Mason   Btrfs: be more se...
1134

4cb5300bc   Chris Mason   Btrfs: add mount ...
1135
1136
1137
1138
  out_ra:
  	if (!file)
  		kfree(ra);
  	kfree(pages);
940100a4a   Chris Mason   Btrfs: be more se...
1139
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1140
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1141
1142
  static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
  					void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
  {
  	u64 new_size;
  	u64 old_size;
  	u64 devid = 1;
  	struct btrfs_ioctl_vol_args *vol_args;
  	struct btrfs_trans_handle *trans;
  	struct btrfs_device *device = NULL;
  	char *sizestr;
  	char *devstr = NULL;
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1153
  	int mod = 0;
c146afad2   Yan Zheng   Btrfs: mount ro a...
1154
1155
  	if (root->fs_info->sb->s_flags & MS_RDONLY)
  		return -EROFS;
e441d54de   Chris Mason   Btrfs: add permis...
1156
1157
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
dae7b665c   Li Zefan   btrfs: use memdup...
1158
1159
1160
  	vol_args = memdup_user(arg, sizeof(*vol_args));
  	if (IS_ERR(vol_args))
  		return PTR_ERR(vol_args);
5516e5957   Mark Fasheh   Btrfs: Null termi...
1161
1162
  
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1163

7d9eb12c8   Chris Mason   Btrfs: Add lockin...
1164
  	mutex_lock(&root->fs_info->volume_mutex);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1165
1166
1167
1168
1169
1170
1171
1172
  	sizestr = vol_args->name;
  	devstr = strchr(sizestr, ':');
  	if (devstr) {
  		char *end;
  		sizestr = devstr + 1;
  		*devstr = '\0';
  		devstr = vol_args->name;
  		devid = simple_strtoull(devstr, &end, 10);
5bb146823   Arnd Hannemann   Btrfs: prefix res...
1173
1174
  		printk(KERN_INFO "btrfs: resizing devid %llu
  ",
21380931e   Joel Becker   Btrfs: Fix a bunc...
1175
  		       (unsigned long long)devid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1176
  	}
2b82032c3   Yan Zheng   Btrfs: Seed devic...
1177
  	device = btrfs_find_device(root, devid, NULL, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1178
  	if (!device) {
5bb146823   Arnd Hannemann   Btrfs: prefix res...
1179
1180
  		printk(KERN_INFO "btrfs: resizer unable to find device %llu
  ",
21380931e   Joel Becker   Btrfs: Fix a bunc...
1181
  		       (unsigned long long)devid);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
  		ret = -EINVAL;
  		goto out_unlock;
  	}
  	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++;
  		}
91748467a   Akinobu Mita   btrfs: use memparse
1195
  		new_size = memparse(sizestr, NULL);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
  		if (new_size == 0) {
  			ret = -EINVAL;
  			goto out_unlock;
  		}
  	}
  
  	old_size = device->total_bytes;
  
  	if (mod < 0) {
  		if (new_size > old_size) {
  			ret = -EINVAL;
  			goto out_unlock;
  		}
  		new_size = old_size - new_size;
  	} else if (mod > 0) {
  		new_size = old_size + new_size;
  	}
  
  	if (new_size < 256 * 1024 * 1024) {
  		ret = -EINVAL;
  		goto out_unlock;
  	}
  	if (new_size > device->bdev->bd_inode->i_size) {
  		ret = -EFBIG;
  		goto out_unlock;
  	}
  
  	do_div(new_size, root->sectorsize);
  	new_size *= root->sectorsize;
5bb146823   Arnd Hannemann   Btrfs: prefix res...
1225
1226
  	printk(KERN_INFO "btrfs: new size for %s is %llu
  ",
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1227
1228
1229
  		device->name, (unsigned long long)new_size);
  
  	if (new_size > old_size) {
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
1230
  		trans = btrfs_start_transaction(root, 0);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
1231
1232
1233
1234
  		if (IS_ERR(trans)) {
  			ret = PTR_ERR(trans);
  			goto out_unlock;
  		}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1235
1236
  		ret = btrfs_grow_device(trans, device, new_size);
  		btrfs_commit_transaction(trans, root);
ece7d20e8   Mike Fleetwood   Btrfs: Don't erro...
1237
  	} else if (new_size < old_size) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1238
1239
1240
1241
  		ret = btrfs_shrink_device(device, new_size);
  	}
  
  out_unlock:
7d9eb12c8   Chris Mason   Btrfs: Add lockin...
1242
  	mutex_unlock(&root->fs_info->volume_mutex);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1243
1244
1245
  	kfree(vol_args);
  	return ret;
  }
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1246
1247
1248
1249
  static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
  						    char *name,
  						    unsigned long fd,
  						    int subvol,
b83cc9693   Li Zefan   Btrfs: Add readon...
1250
1251
  						    u64 *transid,
  						    bool readonly)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1252
  {
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
1253
  	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
3de4586c5   Chris Mason   Btrfs: Allow subv...
1254
  	struct file *src_file;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1255
  	int namelen;
3de4586c5   Chris Mason   Btrfs: Allow subv...
1256
  	int ret = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1257

c146afad2   Yan Zheng   Btrfs: mount ro a...
1258
1259
  	if (root->fs_info->sb->s_flags & MS_RDONLY)
  		return -EROFS;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1260
1261
  	namelen = strlen(name);
  	if (strchr(name, '/')) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1262
1263
1264
  		ret = -EINVAL;
  		goto out;
  	}
3de4586c5   Chris Mason   Btrfs: Allow subv...
1265
  	if (subvol) {
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1266
  		ret = btrfs_mksubvol(&file->f_path, name, namelen,
b83cc9693   Li Zefan   Btrfs: Add readon...
1267
  				     NULL, transid, readonly);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
1268
  	} else {
3de4586c5   Chris Mason   Btrfs: Allow subv...
1269
  		struct inode *src_inode;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1270
  		src_file = fget(fd);
3de4586c5   Chris Mason   Btrfs: Allow subv...
1271
1272
1273
1274
1275
1276
1277
  		if (!src_file) {
  			ret = -EINVAL;
  			goto out;
  		}
  
  		src_inode = src_file->f_path.dentry->d_inode;
  		if (src_inode->i_sb != file->f_path.dentry->d_inode->i_sb) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
1278
1279
1280
  			printk(KERN_INFO "btrfs: Snapshot src from "
  			       "another FS
  ");
3de4586c5   Chris Mason   Btrfs: Allow subv...
1281
1282
1283
1284
  			ret = -EINVAL;
  			fput(src_file);
  			goto out;
  		}
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1285
1286
  		ret = btrfs_mksubvol(&file->f_path, name, namelen,
  				     BTRFS_I(src_inode)->root,
b83cc9693   Li Zefan   Btrfs: Add readon...
1287
  				     transid, readonly);
3de4586c5   Chris Mason   Btrfs: Allow subv...
1288
  		fput(src_file);
cb8e70901   Christoph Hellwig   Btrfs: Fix subvol...
1289
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1290
  out:
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1291
1292
1293
1294
  	return ret;
  }
  
  static noinline int btrfs_ioctl_snap_create(struct file *file,
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1295
  					    void __user *arg, int subvol)
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1296
  {
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1297
  	struct btrfs_ioctl_vol_args *vol_args;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1298
  	int ret;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1299
1300
1301
1302
  	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...
1303

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1304
  	ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
b83cc9693   Li Zefan   Btrfs: Add readon...
1305
1306
  					      vol_args->fd, subvol,
  					      NULL, false);
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1307

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1308
1309
1310
  	kfree(vol_args);
  	return ret;
  }
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1311

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1312
1313
1314
1315
1316
1317
1318
  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...
1319
  	bool readonly = false;
75eaa0e22   Sage Weil   Btrfs: fix sync s...
1320

fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1321
1322
1323
1324
  	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...
1325

b83cc9693   Li Zefan   Btrfs: Add readon...
1326
1327
1328
  	if (vol_args->flags &
  	    ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY)) {
  		ret = -EOPNOTSUPP;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1329
  		goto out;
72fd032e9   Sage Weil   Btrfs: add SNAP_C...
1330
  	}
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1331
1332
1333
  
  	if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
  		ptr = &transid;
b83cc9693   Li Zefan   Btrfs: Add readon...
1334
1335
  	if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
  		readonly = true;
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1336
1337
  
  	ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
b83cc9693   Li Zefan   Btrfs: Add readon...
1338
1339
  					      vol_args->fd, subvol,
  					      ptr, readonly);
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
1340
1341
1342
1343
1344
1345
  
  	if (ret == 0 && ptr &&
  	    copy_to_user(arg +
  			 offsetof(struct btrfs_ioctl_vol_args_v2,
  				  transid), ptr, sizeof(*ptr)))
  		ret = -EFAULT;
fdfb1e4f6   Li Zefan   Btrfs: Make async...
1346
  out:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1347
1348
1349
  	kfree(vol_args);
  	return ret;
  }
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1350
1351
1352
1353
1354
1355
1356
  static noinline int btrfs_ioctl_subvol_getflags(struct file *file,
  						void __user *arg)
  {
  	struct inode *inode = fdentry(file)->d_inode;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	int ret = 0;
  	u64 flags = 0;
33345d015   Li Zefan   Btrfs: Always use...
1357
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID)
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
  		return -EINVAL;
  
  	down_read(&root->fs_info->subvol_sem);
  	if (btrfs_root_readonly(root))
  		flags |= BTRFS_SUBVOL_RDONLY;
  	up_read(&root->fs_info->subvol_sem);
  
  	if (copy_to_user(arg, &flags, sizeof(flags)))
  		ret = -EFAULT;
  
  	return ret;
  }
  
  static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
  					      void __user *arg)
  {
  	struct inode *inode = fdentry(file)->d_inode;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
  	u64 root_flags;
  	u64 flags;
  	int ret = 0;
  
  	if (root->fs_info->sb->s_flags & MS_RDONLY)
  		return -EROFS;
33345d015   Li Zefan   Btrfs: Always use...
1383
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID)
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1384
1385
1386
1387
  		return -EINVAL;
  
  	if (copy_from_user(&flags, arg, sizeof(flags)))
  		return -EFAULT;
b4dc2b8c6   Li Zefan   Btrfs: Fix BTRFS_...
1388
  	if (flags & BTRFS_SUBVOL_CREATE_ASYNC)
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1389
1390
1391
1392
  		return -EINVAL;
  
  	if (flags & ~BTRFS_SUBVOL_RDONLY)
  		return -EOPNOTSUPP;
2e1496707   Serge E. Hallyn   userns: rename is...
1393
  	if (!inode_owner_or_capable(inode))
b4dc2b8c6   Li Zefan   Btrfs: Fix BTRFS_...
1394
  		return -EACCES;
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
  	down_write(&root->fs_info->subvol_sem);
  
  	/* nothing to do */
  	if (!!(flags & BTRFS_SUBVOL_RDONLY) == btrfs_root_readonly(root))
  		goto out;
  
  	root_flags = btrfs_root_flags(&root->root_item);
  	if (flags & BTRFS_SUBVOL_RDONLY)
  		btrfs_set_root_flags(&root->root_item,
  				     root_flags | BTRFS_ROOT_SUBVOL_RDONLY);
  	else
  		btrfs_set_root_flags(&root->root_item,
  				     root_flags & ~BTRFS_ROOT_SUBVOL_RDONLY);
  
  	trans = btrfs_start_transaction(root, 1);
  	if (IS_ERR(trans)) {
  		ret = PTR_ERR(trans);
  		goto out_reset;
  	}
b4dc2b8c6   Li Zefan   Btrfs: Fix BTRFS_...
1414
  	ret = btrfs_update_root(trans, root->fs_info->tree_root,
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
  				&root->root_key, &root->root_item);
  
  	btrfs_commit_transaction(trans, root);
  out_reset:
  	if (ret)
  		btrfs_set_root_flags(&root->root_item, root_flags);
  out:
  	up_write(&root->fs_info->subvol_sem);
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
  /*
   * helper to check if the subvolume references other subvolumes
   */
  static noinline int may_destroy_subvol(struct btrfs_root *root)
  {
  	struct btrfs_path *path;
  	struct btrfs_key key;
  	int ret;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  
  	key.objectid = root->root_key.objectid;
  	key.type = BTRFS_ROOT_REF_KEY;
  	key.offset = (u64)-1;
  
  	ret = btrfs_search_slot(NULL, root->fs_info->tree_root,
  				&key, path, 0, 0);
  	if (ret < 0)
  		goto out;
  	BUG_ON(ret == 0);
  
  	ret = 0;
  	if (path->slots[0] > 0) {
  		path->slots[0]--;
  		btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
  		if (key.objectid == root->root_key.objectid &&
  		    key.type == BTRFS_ROOT_REF_KEY)
  			ret = -ENOTEMPTY;
  	}
  out:
  	btrfs_free_path(path);
  	return ret;
  }
ac8e9819d   Chris Mason   Btrfs: add search...
1460
1461
1462
  static noinline int key_in_sk(struct btrfs_key *key,
  			      struct btrfs_ioctl_search_key *sk)
  {
abc6e1341   Chris Mason   Btrfs: fix key ch...
1463
1464
1465
1466
1467
1468
1469
1470
1471
  	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...
1472
  		return 0;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1473
1474
1475
1476
1477
1478
1479
  
  	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...
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
  		return 0;
  	return 1;
  }
  
  static noinline int copy_to_sk(struct btrfs_root *root,
  			       struct btrfs_path *path,
  			       struct btrfs_key *key,
  			       struct btrfs_ioctl_search_key *sk,
  			       char *buf,
  			       unsigned long *sk_offset,
  			       int *num_found)
  {
  	u64 found_transid;
  	struct extent_buffer *leaf;
  	struct btrfs_ioctl_search_header sh;
  	unsigned long item_off;
  	unsigned long item_len;
  	int nritems;
  	int i;
  	int slot;
ac8e9819d   Chris Mason   Btrfs: add search...
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
  	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);
  
  		if (item_len > BTRFS_SEARCH_ARGS_BUFSIZE)
  			item_len = 0;
  
  		if (sizeof(sh) + item_len + *sk_offset >
  		    BTRFS_SEARCH_ARGS_BUFSIZE) {
  			ret = 1;
  			goto overflow;
  		}
  
  		btrfs_item_key_to_cpu(leaf, key, i);
  		if (!key_in_sk(key, sk))
  			continue;
  
  		sh.objectid = key->objectid;
  		sh.offset = key->offset;
  		sh.type = key->type;
  		sh.len = item_len;
  		sh.transid = found_transid;
  
  		/* copy search result header */
  		memcpy(buf + *sk_offset, &sh, sizeof(sh));
  		*sk_offset += sizeof(sh);
  
  		if (item_len) {
  			char *p = buf + *sk_offset;
  			/* copy the item */
  			read_extent_buffer(leaf, p,
  					   item_off, item_len);
  			*sk_offset += item_len;
ac8e9819d   Chris Mason   Btrfs: add search...
1545
  		}
e21568671   Hugo Mills   btrfs: Ensure the...
1546
  		(*num_found)++;
ac8e9819d   Chris Mason   Btrfs: add search...
1547
1548
1549
1550
1551
  
  		if (*num_found >= sk->nr_items)
  			break;
  	}
  advance_key:
abc6e1341   Chris Mason   Btrfs: fix key ch...
1552
1553
  	ret = 0;
  	if (key->offset < (u64)-1 && key->offset < sk->max_offset)
ac8e9819d   Chris Mason   Btrfs: add search...
1554
  		key->offset++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1555
1556
  	else if (key->type < (u8)-1 && key->type < sk->max_type) {
  		key->offset = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1557
  		key->type++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1558
1559
1560
  	} else if (key->objectid < (u64)-1 && key->objectid < sk->max_objectid) {
  		key->offset = 0;
  		key->type = 0;
ac8e9819d   Chris Mason   Btrfs: add search...
1561
  		key->objectid++;
abc6e1341   Chris Mason   Btrfs: fix key ch...
1562
1563
  	} else
  		ret = 1;
ac8e9819d   Chris Mason   Btrfs: add search...
1564
  overflow:
ac8e9819d   Chris Mason   Btrfs: add search...
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
  	return ret;
  }
  
  static noinline int search_ioctl(struct inode *inode,
  				 struct btrfs_ioctl_search_args *args)
  {
  	struct btrfs_root *root;
  	struct btrfs_key key;
  	struct btrfs_key max_key;
  	struct btrfs_path *path;
  	struct btrfs_ioctl_search_key *sk = &args->key;
  	struct btrfs_fs_info *info = BTRFS_I(inode)->root->fs_info;
  	int ret;
  	int num_found = 0;
  	unsigned long sk_offset = 0;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  
  	if (sk->tree_id == 0) {
  		/* search the root of the inode that was passed */
  		root = BTRFS_I(inode)->root;
  	} else {
  		key.objectid = sk->tree_id;
  		key.type = BTRFS_ROOT_ITEM_KEY;
  		key.offset = (u64)-1;
  		root = btrfs_read_fs_root_no_name(info, &key);
  		if (IS_ERR(root)) {
  			printk(KERN_ERR "could not find root %llu
  ",
  			       sk->tree_id);
  			btrfs_free_path(path);
  			return -ENOENT;
  		}
  	}
  
  	key.objectid = sk->min_objectid;
  	key.type = sk->min_type;
  	key.offset = sk->min_offset;
  
  	max_key.objectid = sk->max_objectid;
  	max_key.type = sk->max_type;
  	max_key.offset = sk->max_offset;
  
  	path->keep_locks = 1;
  
  	while(1) {
  		ret = btrfs_search_forward(root, &key, &max_key, path, 0,
  					   sk->min_transid);
  		if (ret != 0) {
  			if (ret > 0)
  				ret = 0;
  			goto err;
  		}
  		ret = copy_to_sk(root, path, &key, sk, args->buf,
  				 &sk_offset, &num_found);
b3b4aa74b   David Sterba   btrfs: drop unuse...
1622
  		btrfs_release_path(path);
ac8e9819d   Chris Mason   Btrfs: add search...
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
  		if (ret || num_found >= sk->nr_items)
  			break;
  
  	}
  	ret = 0;
  err:
  	sk->nr_items = num_found;
  	btrfs_free_path(path);
  	return ret;
  }
  
  static noinline int btrfs_ioctl_tree_search(struct file *file,
  					   void __user *argp)
  {
  	 struct btrfs_ioctl_search_args *args;
  	 struct inode *inode;
  	 int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
2354d08fe   Julia Lawall   Btrfs: use memdup...
1643
1644
1645
  	args = memdup_user(argp, sizeof(*args));
  	if (IS_ERR(args))
  		return PTR_ERR(args);
ac8e9819d   Chris Mason   Btrfs: add search...
1646

ac8e9819d   Chris Mason   Btrfs: add search...
1647
1648
1649
1650
1651
1652
1653
  	inode = fdentry(file)->d_inode;
  	ret = search_ioctl(inode, args);
  	if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
  		ret = -EFAULT;
  	kfree(args);
  	return ret;
  }
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1654
  /*
ac8e9819d   Chris Mason   Btrfs: add search...
1655
1656
1657
   * 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...
1658
1659
1660
1661
1662
  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...
1663
  	char *ptr;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
  	int ret = -1;
  	int slot;
  	int len;
  	int total_len = 0;
  	struct btrfs_inode_ref *iref;
  	struct extent_buffer *l;
  	struct btrfs_path *path;
  
  	if (dirid == BTRFS_FIRST_FREE_OBJECTID) {
  		name[0]='\0';
  		return 0;
  	}
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
ac8e9819d   Chris Mason   Btrfs: add search...
1680
  	ptr = &name[BTRFS_INO_LOOKUP_PATH_MAX];
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1681
1682
1683
1684
1685
1686
1687
1688
  
  	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)) {
  		printk(KERN_ERR "could not find root %llu
  ", tree_id);
8ad6fcab5   Chris Mason   Btrfs: fix the in...
1689
1690
  		ret = -ENOENT;
  		goto out;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1691
1692
1693
1694
  	}
  
  	key.objectid = dirid;
  	key.type = BTRFS_INODE_REF_KEY;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
1695
  	key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1696
1697
1698
1699
1700
1701
1702
1703
  
  	while(1) {
  		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
  		if (ret < 0)
  			goto out;
  
  		l = path->nodes[0];
  		slot = path->slots[0];
8ad6fcab5   Chris Mason   Btrfs: fix the in...
1704
1705
  		if (ret > 0 && slot > 0)
  			slot--;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1706
1707
1708
  		btrfs_item_key_to_cpu(l, &key, slot);
  
  		if (ret > 0 && (key.objectid != dirid ||
ac8e9819d   Chris Mason   Btrfs: add search...
1709
1710
  				key.type != BTRFS_INODE_REF_KEY)) {
  			ret = -ENOENT;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1711
  			goto out;
ac8e9819d   Chris Mason   Btrfs: add search...
1712
  		}
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1713
1714
1715
1716
1717
  
  		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;
ac8e9819d   Chris Mason   Btrfs: add search...
1718
  		if (ptr < name)
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1719
1720
1721
1722
1723
1724
1725
  			goto out;
  
  		*(ptr + len) = '/';
  		read_extent_buffer(l, ptr,(unsigned long)(iref + 1), len);
  
  		if (key.offset == BTRFS_FIRST_FREE_OBJECTID)
  			break;
b3b4aa74b   David Sterba   btrfs: drop unuse...
1726
  		btrfs_release_path(path);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1727
  		key.objectid = key.offset;
8ad6fcab5   Chris Mason   Btrfs: fix the in...
1728
  		key.offset = (u64)-1;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1729
  		dirid = key.objectid;
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1730
  	}
ac8e9819d   Chris Mason   Btrfs: add search...
1731
  	if (ptr < name)
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1732
  		goto out;
77906a507   Li Zefan   Btrfs: copy strin...
1733
  	memmove(name, ptr, total_len);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1734
1735
1736
1737
  	name[total_len]='\0';
  	ret = 0;
  out:
  	btrfs_free_path(path);
ac8e9819d   Chris Mason   Btrfs: add search...
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
  	return ret;
  }
  
  static noinline int btrfs_ioctl_ino_lookup(struct file *file,
  					   void __user *argp)
  {
  	 struct btrfs_ioctl_ino_lookup_args *args;
  	 struct inode *inode;
  	 int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
2354d08fe   Julia Lawall   Btrfs: use memdup...
1750
1751
1752
  	args = memdup_user(argp, sizeof(*args));
  	if (IS_ERR(args))
  		return PTR_ERR(args);
c2b96929e   Dan Carpenter   Btrfs: handle kma...
1753

ac8e9819d   Chris Mason   Btrfs: add search...
1754
  	inode = fdentry(file)->d_inode;
1b53ac4d1   Chris Mason   Btrfs: allow tree...
1755
1756
  	if (args->treeid == 0)
  		args->treeid = BTRFS_I(inode)->root->root_key.objectid;
ac8e9819d   Chris Mason   Btrfs: add search...
1757
1758
1759
1760
1761
1762
1763
1764
  	ret = btrfs_search_path_in_tree(BTRFS_I(inode)->root->fs_info,
  					args->treeid, args->objectid,
  					args->name);
  
  	if (ret == 0 && copy_to_user(argp, args, sizeof(*args)))
  		ret = -EFAULT;
  
  	kfree(args);
98d377a08   TARUISI Hiroaki   Btrfs: add a func...
1765
1766
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
  static noinline int btrfs_ioctl_snap_destroy(struct file *file,
  					     void __user *arg)
  {
  	struct dentry *parent = fdentry(file);
  	struct dentry *dentry;
  	struct inode *dir = parent->d_inode;
  	struct inode *inode;
  	struct btrfs_root *root = BTRFS_I(dir)->root;
  	struct btrfs_root *dest = NULL;
  	struct btrfs_ioctl_vol_args *vol_args;
  	struct btrfs_trans_handle *trans;
  	int namelen;
  	int ret;
  	int err = 0;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
  	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...
1792
  	err = mnt_want_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
  	if (err)
  		goto out;
  
  	mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
  	dentry = lookup_one_len(vol_args->name, parent, namelen);
  	if (IS_ERR(dentry)) {
  		err = PTR_ERR(dentry);
  		goto out_unlock_dir;
  	}
  
  	if (!dentry->d_inode) {
  		err = -ENOENT;
  		goto out_dput;
  	}
  
  	inode = dentry->d_inode;
4260f7c75   Sage Weil   Btrfs: allow subv...
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
  	dest = BTRFS_I(inode)->root;
  	if (!capable(CAP_SYS_ADMIN)){
  		/*
  		 * Regular user.  Only allow this with a special mount
  		 * option, when the user has write+exec access to the
  		 * subvol root, and when rmdir(2) would have been
  		 * allowed.
  		 *
  		 * Note that this is _not_ check that the subvol is
  		 * empty or doesn't contain data that we wouldn't
  		 * otherwise be able to delete.
  		 *
  		 * Users who want to delete empty subvols should try
  		 * rmdir(2).
  		 */
  		err = -EPERM;
  		if (!btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED))
  			goto out_dput;
  
  		/*
  		 * Do not allow deletion if the parent dir is the same
  		 * as the dir to be deleted.  That means the ioctl
  		 * must be called on the dentry referencing the root
  		 * of the subvol, not a random directory contained
  		 * within it.
  		 */
  		err = -EINVAL;
  		if (root == dest)
  			goto out_dput;
  
  		err = inode_permission(inode, MAY_WRITE | MAY_EXEC);
  		if (err)
  			goto out_dput;
  
  		/* check if subvolume may be deleted by a non-root user */
  		err = btrfs_may_delete(dir, dentry, 1);
  		if (err)
  			goto out_dput;
  	}
33345d015   Li Zefan   Btrfs: Always use...
1848
  	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1849
1850
1851
  		err = -EINVAL;
  		goto out_dput;
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
  	mutex_lock(&inode->i_mutex);
  	err = d_invalidate(dentry);
  	if (err)
  		goto out_unlock;
  
  	down_write(&root->fs_info->subvol_sem);
  
  	err = may_destroy_subvol(dest);
  	if (err)
  		goto out_up_write;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
1862
1863
1864
  	trans = btrfs_start_transaction(root, 0);
  	if (IS_ERR(trans)) {
  		err = PTR_ERR(trans);
d327099a2   Dan Carpenter   Btrfs: unwind aft...
1865
  		goto out_up_write;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
1866
1867
  	}
  	trans->block_rsv = &root->fs_info->global_block_rsv;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
  	ret = btrfs_unlink_subvol(trans, root, dir,
  				dest->root_key.objectid,
  				dentry->d_name.name,
  				dentry->d_name.len);
  	BUG_ON(ret);
  
  	btrfs_record_root_in_trans(trans, dest);
  
  	memset(&dest->root_item.drop_progress, 0,
  		sizeof(dest->root_item.drop_progress));
  	dest->root_item.drop_level = 0;
  	btrfs_set_root_refs(&dest->root_item, 0);
d68fc57b7   Yan, Zheng   Btrfs: Metadata r...
1880
1881
1882
1883
1884
1885
  	if (!xchg(&dest->orphan_item_inserted, 1)) {
  		ret = btrfs_insert_orphan_item(trans,
  					root->fs_info->tree_root,
  					dest->root_key.objectid);
  		BUG_ON(ret);
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1886

531cb13f1   Sage Weil   Btrfs: make SNAP_...
1887
  	ret = btrfs_end_transaction(trans, root);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1888
1889
1890
1891
1892
1893
1894
  	BUG_ON(ret);
  	inode->i_flags |= S_DEAD;
  out_up_write:
  	up_write(&root->fs_info->subvol_sem);
  out_unlock:
  	mutex_unlock(&inode->i_mutex);
  	if (!err) {
efefb1438   Yan, Zheng   Btrfs: remove neg...
1895
  		shrink_dcache_sb(root->fs_info->sb);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1896
1897
1898
1899
1900
1901
1902
  		btrfs_invalidate_inodes(dest);
  		d_delete(dentry);
  	}
  out_dput:
  	dput(dentry);
  out_unlock_dir:
  	mutex_unlock(&dir->i_mutex);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
1903
  	mnt_drop_write_file(file);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
1904
1905
1906
1907
  out:
  	kfree(vol_args);
  	return err;
  }
1e701a329   Chris Mason   Btrfs: add new de...
1908
  static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1909
1910
1911
  {
  	struct inode *inode = fdentry(file)->d_inode;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
1e701a329   Chris Mason   Btrfs: add new de...
1912
  	struct btrfs_ioctl_defrag_range_args *range;
c146afad2   Yan Zheng   Btrfs: mount ro a...
1913
  	int ret;
b83cc9693   Li Zefan   Btrfs: Add readon...
1914
1915
  	if (btrfs_root_readonly(root))
  		return -EROFS;
a561be710   Al Viro   switch a bunch of...
1916
  	ret = mnt_want_write_file(file);
c146afad2   Yan Zheng   Btrfs: mount ro a...
1917
1918
  	if (ret)
  		return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1919
1920
1921
  
  	switch (inode->i_mode & S_IFMT) {
  	case S_IFDIR:
e441d54de   Chris Mason   Btrfs: add permis...
1922
1923
1924
1925
  		if (!capable(CAP_SYS_ADMIN)) {
  			ret = -EPERM;
  			goto out;
  		}
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
1926
1927
1928
1929
  		ret = btrfs_defrag_root(root, 0);
  		if (ret)
  			goto out;
  		ret = btrfs_defrag_root(root->fs_info->extent_root, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1930
1931
  		break;
  	case S_IFREG:
e441d54de   Chris Mason   Btrfs: add permis...
1932
1933
1934
1935
  		if (!(file->f_mode & FMODE_WRITE)) {
  			ret = -EINVAL;
  			goto out;
  		}
1e701a329   Chris Mason   Btrfs: add new de...
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
  
  		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...
1948
  				goto out;
1e701a329   Chris Mason   Btrfs: add new de...
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
  			}
  			/* 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;
  		}
4cb5300bc   Chris Mason   Btrfs: add mount ...
1959
1960
1961
1962
  		ret = btrfs_defrag_file(fdentry(file)->d_inode, file,
  					range, 0, 0);
  		if (ret > 0)
  			ret = 0;
1e701a329   Chris Mason   Btrfs: add new de...
1963
  		kfree(range);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1964
  		break;
8929ecfa5   Yan, Zheng   Btrfs: Introduce ...
1965
1966
  	default:
  		ret = -EINVAL;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1967
  	}
e441d54de   Chris Mason   Btrfs: add permis...
1968
  out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
1969
  	mnt_drop_write_file(file);
e441d54de   Chris Mason   Btrfs: add permis...
1970
  	return ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1971
  }
b2950863c   Christoph Hellwig   Btrfs: make thing...
1972
  static long btrfs_ioctl_add_dev(struct btrfs_root *root, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1973
1974
1975
  {
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
1976
1977
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
dae7b665c   Li Zefan   btrfs: use memdup...
1978
1979
1980
  	vol_args = memdup_user(arg, sizeof(*vol_args));
  	if (IS_ERR(vol_args))
  		return PTR_ERR(vol_args);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1981

5516e5957   Mark Fasheh   Btrfs: Null termi...
1982
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1983
  	ret = btrfs_init_new_device(root, vol_args->name);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1984
1985
1986
  	kfree(vol_args);
  	return ret;
  }
b2950863c   Christoph Hellwig   Btrfs: make thing...
1987
  static long btrfs_ioctl_rm_dev(struct btrfs_root *root, void __user *arg)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1988
1989
1990
  {
  	struct btrfs_ioctl_vol_args *vol_args;
  	int ret;
e441d54de   Chris Mason   Btrfs: add permis...
1991
1992
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
c146afad2   Yan Zheng   Btrfs: mount ro a...
1993
1994
  	if (root->fs_info->sb->s_flags & MS_RDONLY)
  		return -EROFS;
dae7b665c   Li Zefan   btrfs: use memdup...
1995
1996
1997
  	vol_args = memdup_user(arg, sizeof(*vol_args));
  	if (IS_ERR(vol_args))
  		return PTR_ERR(vol_args);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
1998

5516e5957   Mark Fasheh   Btrfs: Null termi...
1999
  	vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2000
  	ret = btrfs_rm_device(root, vol_args->name);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2001
2002
2003
  	kfree(vol_args);
  	return ret;
  }
475f63874   Jan Schmidt   btrfs: new ioctls...
2004
2005
  static long btrfs_ioctl_fs_info(struct btrfs_root *root, void __user *arg)
  {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2006
  	struct btrfs_ioctl_fs_info_args *fi_args;
475f63874   Jan Schmidt   btrfs: new ioctls...
2007
2008
2009
  	struct btrfs_device *device;
  	struct btrfs_device *next;
  	struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
027ed2f00   Li Zefan   Btrfs: avoid stac...
2010
  	int ret = 0;
475f63874   Jan Schmidt   btrfs: new ioctls...
2011
2012
2013
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
027ed2f00   Li Zefan   Btrfs: avoid stac...
2014
2015
2016
2017
2018
2019
  	fi_args = kzalloc(sizeof(*fi_args), GFP_KERNEL);
  	if (!fi_args)
  		return -ENOMEM;
  
  	fi_args->num_devices = fs_devices->num_devices;
  	memcpy(&fi_args->fsid, root->fs_info->fsid, sizeof(fi_args->fsid));
475f63874   Jan Schmidt   btrfs: new ioctls...
2020
2021
2022
  
  	mutex_lock(&fs_devices->device_list_mutex);
  	list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) {
027ed2f00   Li Zefan   Btrfs: avoid stac...
2023
2024
  		if (device->devid > fi_args->max_id)
  			fi_args->max_id = device->devid;
475f63874   Jan Schmidt   btrfs: new ioctls...
2025
2026
  	}
  	mutex_unlock(&fs_devices->device_list_mutex);
027ed2f00   Li Zefan   Btrfs: avoid stac...
2027
2028
  	if (copy_to_user(arg, fi_args, sizeof(*fi_args)))
  		ret = -EFAULT;
475f63874   Jan Schmidt   btrfs: new ioctls...
2029

027ed2f00   Li Zefan   Btrfs: avoid stac...
2030
2031
  	kfree(fi_args);
  	return ret;
475f63874   Jan Schmidt   btrfs: new ioctls...
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
  }
  
  static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg)
  {
  	struct btrfs_ioctl_dev_info_args *di_args;
  	struct btrfs_device *dev;
  	struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
  	int ret = 0;
  	char *s_uuid = NULL;
  	char empty_uuid[BTRFS_UUID_SIZE] = {0};
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	di_args = memdup_user(arg, sizeof(*di_args));
  	if (IS_ERR(di_args))
  		return PTR_ERR(di_args);
  
  	if (memcmp(empty_uuid, di_args->uuid, BTRFS_UUID_SIZE) != 0)
  		s_uuid = di_args->uuid;
  
  	mutex_lock(&fs_devices->device_list_mutex);
  	dev = btrfs_find_device(root, di_args->devid, s_uuid, NULL);
  	mutex_unlock(&fs_devices->device_list_mutex);
  
  	if (!dev) {
  		ret = -ENODEV;
  		goto out;
  	}
  
  	di_args->devid = dev->devid;
  	di_args->bytes_used = dev->bytes_used;
  	di_args->total_bytes = dev->total_bytes;
  	memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
  	strncpy(di_args->path, dev->name, sizeof(di_args->path));
  
  out:
  	if (ret == 0 && copy_to_user(arg, di_args, sizeof(*di_args)))
  		ret = -EFAULT;
  
  	kfree(di_args);
  	return ret;
  }
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2075
2076
  static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
  				       u64 off, u64 olen, u64 destoff)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2077
2078
2079
2080
2081
2082
  {
  	struct inode *inode = fdentry(file)->d_inode;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct file *src_file;
  	struct inode *src;
  	struct btrfs_trans_handle *trans;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2083
  	struct btrfs_path *path;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2084
  	struct extent_buffer *leaf;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2085
2086
  	char *buf;
  	struct btrfs_key key;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2087
2088
  	u32 nritems;
  	int slot;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2089
  	int ret;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2090
2091
2092
  	u64 len = olen;
  	u64 bs = root->fs_info->sb->s_blocksize;
  	u64 hint_byte;
d20f7043f   Chris Mason   Btrfs: move data ...
2093

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2094
2095
2096
2097
2098
2099
2100
2101
2102
  	/*
  	 * 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.
  	 * - allow ranges within the same file to be cloned (provided
  	 *   they don't overlap)?
  	 */
e441d54de   Chris Mason   Btrfs: add permis...
2103
  	/* the destination must be opened for writing */
2ebc34647   Dan Rosenberg   Btrfs: fix checks...
2104
  	if (!(file->f_mode & FMODE_WRITE) || (file->f_flags & O_APPEND))
e441d54de   Chris Mason   Btrfs: add permis...
2105
  		return -EINVAL;
b83cc9693   Li Zefan   Btrfs: Add readon...
2106
2107
  	if (btrfs_root_readonly(root))
  		return -EROFS;
a561be710   Al Viro   switch a bunch of...
2108
  	ret = mnt_want_write_file(file);
c146afad2   Yan Zheng   Btrfs: mount ro a...
2109
2110
  	if (ret)
  		return ret;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2111
  	src_file = fget(srcfd);
ab67b7c1f   Yan Zheng   Btrfs: Add missin...
2112
2113
2114
2115
  	if (!src_file) {
  		ret = -EBADF;
  		goto out_drop_write;
  	}
5dc641641   Dan Rosenberg   Btrfs: check for ...
2116

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2117
  	src = src_file->f_dentry->d_inode;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2118
2119
2120
  	ret = -EINVAL;
  	if (src == inode)
  		goto out_fput;
5dc641641   Dan Rosenberg   Btrfs: check for ...
2121
2122
2123
  	/* the src must be open for reading */
  	if (!(src_file->f_mode & FMODE_READ))
  		goto out_fput;
0e7b824c4   Li Zefan   Btrfs: don't make...
2124
2125
2126
2127
  	/* don't make the dst file partly checksummed */
  	if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) !=
  	    (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM))
  		goto out_fput;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2128
2129
2130
  	ret = -EISDIR;
  	if (S_ISDIR(src->i_mode) || S_ISDIR(inode->i_mode))
  		goto out_fput;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2131
  	ret = -EXDEV;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
  	if (src->i_sb != inode->i_sb || BTRFS_I(src)->root != root)
  		goto out_fput;
  
  	ret = -ENOMEM;
  	buf = vmalloc(btrfs_level_size(root, 0));
  	if (!buf)
  		goto out_fput;
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		vfree(buf);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2143
  		goto out_fput;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2144
2145
  	}
  	path->reada = 2;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2146
2147
  
  	if (inode < src) {
fccdae435   Sage Weil   Btrfs: fix lockde...
2148
2149
  		mutex_lock_nested(&inode->i_mutex, I_MUTEX_PARENT);
  		mutex_lock_nested(&src->i_mutex, I_MUTEX_CHILD);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2150
  	} else {
fccdae435   Sage Weil   Btrfs: fix lockde...
2151
2152
  		mutex_lock_nested(&src->i_mutex, I_MUTEX_PARENT);
  		mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2153
  	}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2154
2155
  	/* determine range to clone */
  	ret = -EINVAL;
2ebc34647   Dan Rosenberg   Btrfs: fix checks...
2156
  	if (off + len > src->i_size || off + len < off)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2157
  		goto out_unlock;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2158
2159
2160
2161
  	if (len == 0)
  		olen = len = src->i_size - off;
  	/* if we extend to eof, continue to block boundary */
  	if (off + len == src->i_size)
2a6b8daed   Li Zefan   btrfs: Check if d...
2162
  		len = ALIGN(src->i_size, bs) - off;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2163
2164
  
  	/* verify the end result is block aligned */
2a6b8daed   Li Zefan   btrfs: Check if d...
2165
2166
  	if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) ||
  	    !IS_ALIGNED(destoff, bs))
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2167
  		goto out_unlock;
d525e8ab0   Li Zefan   Btrfs: add dummy ...
2168
2169
2170
2171
2172
  	if (destoff > inode->i_size) {
  		ret = btrfs_cont_expand(inode, inode->i_size, destoff);
  		if (ret)
  			goto out_unlock;
  	}
71ef07861   Li Zefan   Btrfs: fix pages ...
2173
2174
2175
  	/* truncate page cache pages from target inode range */
  	truncate_inode_pages_range(&inode->i_data, destoff,
  				   PAGE_CACHE_ALIGN(destoff + len) - 1);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2176
2177
2178
  	/* do any pending delalloc/csum calc on src, one way or
  	   another, and lock file content */
  	while (1) {
31840ae1a   Zheng Yan   Btrfs: Full back ...
2179
  		struct btrfs_ordered_extent *ordered;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2180
  		lock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
9a019196e   Sage Weil   Btrfs: fix delall...
2181
2182
2183
2184
  		ordered = btrfs_lookup_first_ordered_extent(src, off+len);
  		if (!ordered &&
  		    !test_range_bit(&BTRFS_I(src)->io_tree, off, off+len,
  				   EXTENT_DELALLOC, 0, NULL))
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2185
  			break;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2186
  		unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2187
2188
  		if (ordered)
  			btrfs_put_ordered_extent(ordered);
9a019196e   Sage Weil   Btrfs: fix delall...
2189
  		btrfs_wait_ordered_range(src, off, len);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2190
  	}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2191
  	/* clone data */
33345d015   Li Zefan   Btrfs: Always use...
2192
  	key.objectid = btrfs_ino(src);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2193
2194
  	key.type = BTRFS_EXTENT_DATA_KEY;
  	key.offset = 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2195
2196
2197
2198
2199
2200
  
  	while (1) {
  		/*
  		 * note the key will change type as we walk through the
  		 * tree.
  		 */
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2201
  		ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2202
2203
  		if (ret < 0)
  			goto out;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2204
2205
  		nritems = btrfs_header_nritems(path->nodes[0]);
  		if (path->slots[0] >= nritems) {
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2206
2207
2208
2209
2210
  			ret = btrfs_next_leaf(root, path);
  			if (ret < 0)
  				goto out;
  			if (ret > 0)
  				break;
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2211
  			nritems = btrfs_header_nritems(path->nodes[0]);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2212
2213
2214
  		}
  		leaf = path->nodes[0];
  		slot = path->slots[0];
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2215

ae01a0abf   Yan Zheng   Btrfs: Update clo...
2216
  		btrfs_item_key_to_cpu(leaf, &key, slot);
d20f7043f   Chris Mason   Btrfs: move data ...
2217
  		if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY ||
33345d015   Li Zefan   Btrfs: Always use...
2218
  		    key.objectid != btrfs_ino(src))
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2219
  			break;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2220
2221
2222
  		if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
  			struct btrfs_file_extent_item *extent;
  			int type;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2223
2224
  			u32 size;
  			struct btrfs_key new_key;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2225
2226
2227
  			u64 disko = 0, diskl = 0;
  			u64 datao = 0, datal = 0;
  			u8 comp;
b5384d48f   Sage Weil   Btrfs: fix CLONE ...
2228
  			u64 endoff;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2229
2230
2231
2232
2233
  
  			size = btrfs_item_size_nr(leaf, slot);
  			read_extent_buffer(leaf, buf,
  					   btrfs_item_ptr_offset(leaf, slot),
  					   size);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2234
2235
2236
2237
2238
  
  			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...
2239
2240
  			if (type == BTRFS_FILE_EXTENT_REG ||
  			    type == BTRFS_FILE_EXTENT_PREALLOC) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
2241
2242
2243
2244
  				disko = btrfs_file_extent_disk_bytenr(leaf,
  								      extent);
  				diskl = btrfs_file_extent_disk_num_bytes(leaf,
  								 extent);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2245
  				datao = btrfs_file_extent_offset(leaf, extent);
d397712bc   Chris Mason   Btrfs: Fix checkp...
2246
2247
  				datal = btrfs_file_extent_num_bytes(leaf,
  								    extent);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2248
2249
2250
2251
2252
  			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
  				/* take upper bound, may be compressed */
  				datal = btrfs_file_extent_ram_bytes(leaf,
  								    extent);
  			}
b3b4aa74b   David Sterba   btrfs: drop unuse...
2253
  			btrfs_release_path(path);
31840ae1a   Zheng Yan   Btrfs: Full back ...
2254

050006a75   Sage Weil   Btrfs: fix clone ...
2255
  			if (key.offset + datal <= off ||
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2256
2257
  			    key.offset >= off+len)
  				goto next;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2258
  			memcpy(&new_key, &key, sizeof(new_key));
33345d015   Li Zefan   Btrfs: Always use...
2259
  			new_key.objectid = btrfs_ino(inode);
4d728ec7a   Li Zefan   Btrfs: Fix file c...
2260
2261
2262
2263
  			if (off <= key.offset)
  				new_key.offset = key.offset + destoff - off;
  			else
  				new_key.offset = destoff;
31840ae1a   Zheng Yan   Btrfs: Full back ...
2264

b6f3409b2   Sage Weil   Btrfs: reserve su...
2265
2266
2267
2268
2269
2270
  			/*
  			 * 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 ...
2271
2272
2273
2274
  			if (IS_ERR(trans)) {
  				ret = PTR_ERR(trans);
  				goto out;
  			}
c8a894d77   Chris Mason   Btrfs: fix the fi...
2275
2276
  			if (type == BTRFS_FILE_EXTENT_REG ||
  			    type == BTRFS_FILE_EXTENT_PREALLOC) {
d72c0842f   Li Zefan   Btrfs: calc file ...
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
  				/*
  				 *    a  | --- range to clone ---|  b
  				 * | ------------- extent ------------- |
  				 */
  
  				/* substract range b */
  				if (key.offset + datal > off + len)
  					datal = off + len - key.offset;
  
  				/* substract range a */
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2287
2288
2289
2290
  				if (off > key.offset) {
  					datao += off - key.offset;
  					datal -= off - key.offset;
  				}
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2291
2292
2293
2294
2295
  				ret = btrfs_drop_extents(trans, inode,
  							 new_key.offset,
  							 new_key.offset + datal,
  							 &hint_byte, 1);
  				BUG_ON(ret);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2296
2297
  				ret = btrfs_insert_empty_item(trans, root, path,
  							      &new_key, size);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2298
  				BUG_ON(ret);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2299
2300
2301
2302
  
  				leaf = path->nodes[0];
  				slot = path->slots[0];
  				write_extent_buffer(leaf, buf,
31840ae1a   Zheng Yan   Btrfs: Full back ...
2303
2304
  					    btrfs_item_ptr_offset(leaf, slot),
  					    size);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2305

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

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2309
2310
2311
  				/* disko == 0 means it's a hole */
  				if (!disko)
  					datao = 0;
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2312
2313
2314
2315
2316
2317
2318
  
  				btrfs_set_file_extent_offset(leaf, extent,
  							     datao);
  				btrfs_set_file_extent_num_bytes(leaf, extent,
  								datal);
  				if (disko) {
  					inode_add_bytes(inode, datal);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2319
  					ret = btrfs_inc_extent_ref(trans, root,
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2320
2321
  							disko, diskl, 0,
  							root->root_key.objectid,
33345d015   Li Zefan   Btrfs: Always use...
2322
  							btrfs_ino(inode),
5d4f98a28   Yan Zheng   Btrfs: Mixed back...
2323
  							new_key.offset - datao);
31840ae1a   Zheng Yan   Btrfs: Full back ...
2324
  					BUG_ON(ret);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2325
  				}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2326
2327
2328
2329
2330
2331
2332
  			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
  				u64 skip = 0;
  				u64 trim = 0;
  				if (off > key.offset) {
  					skip = off - key.offset;
  					new_key.offset += skip;
  				}
d397712bc   Chris Mason   Btrfs: Fix checkp...
2333

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2334
2335
  				if (key.offset + datal > off+len)
  					trim = key.offset + datal - (off+len);
d397712bc   Chris Mason   Btrfs: Fix checkp...
2336

c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2337
  				if (comp && (skip || trim)) {
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2338
  					ret = -EINVAL;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2339
  					btrfs_end_transaction(trans, root);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2340
2341
2342
2343
  					goto out;
  				}
  				size -= skip + trim;
  				datal -= skip + trim;
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2344
2345
2346
2347
2348
2349
  
  				ret = btrfs_drop_extents(trans, inode,
  							 new_key.offset,
  							 new_key.offset + datal,
  							 &hint_byte, 1);
  				BUG_ON(ret);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2350
2351
  				ret = btrfs_insert_empty_item(trans, root, path,
  							      &new_key, size);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2352
  				BUG_ON(ret);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2353
2354
  
  				if (skip) {
d397712bc   Chris Mason   Btrfs: Fix checkp...
2355
2356
  					u32 start =
  					  btrfs_file_extent_calc_inline_size(0);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
  					memmove(buf+start, buf+start+skip,
  						datal);
  				}
  
  				leaf = path->nodes[0];
  				slot = path->slots[0];
  				write_extent_buffer(leaf, buf,
  					    btrfs_item_ptr_offset(leaf, slot),
  					    size);
  				inode_add_bytes(inode, datal);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2367
  			}
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2368
2369
  
  			btrfs_mark_buffer_dirty(leaf);
b3b4aa74b   David Sterba   btrfs: drop unuse...
2370
  			btrfs_release_path(path);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2371

a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2372
  			inode->i_mtime = inode->i_ctime = CURRENT_TIME;
b5384d48f   Sage Weil   Btrfs: fix CLONE ...
2373
2374
2375
2376
2377
2378
2379
  
  			/*
  			 * we round up to the block size at eof when
  			 * determining which extents to clone above,
  			 * but shouldn't round up the file size
  			 */
  			endoff = new_key.offset + datal;
5f3888ff6   Li Zefan   btrfs: Set file s...
2380
2381
  			if (endoff > destoff+olen)
  				endoff = destoff+olen;
b5384d48f   Sage Weil   Btrfs: fix CLONE ...
2382
2383
  			if (endoff > inode->i_size)
  				btrfs_i_size_write(inode, endoff);
a22285a6a   Yan, Zheng   Btrfs: Integrate ...
2384
2385
2386
2387
  			ret = btrfs_update_inode(trans, root, inode);
  			BUG_ON(ret);
  			btrfs_end_transaction(trans, root);
  		}
d397712bc   Chris Mason   Btrfs: Fix checkp...
2388
  next:
b3b4aa74b   David Sterba   btrfs: drop unuse...
2389
  		btrfs_release_path(path);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2390
  		key.offset++;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2391
  	}
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2392
2393
  	ret = 0;
  out:
b3b4aa74b   David Sterba   btrfs: drop unuse...
2394
  	btrfs_release_path(path);
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2395
  	unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2396
2397
2398
  out_unlock:
  	mutex_unlock(&src->i_mutex);
  	mutex_unlock(&inode->i_mutex);
ae01a0abf   Yan Zheng   Btrfs: Update clo...
2399
2400
  	vfree(buf);
  	btrfs_free_path(path);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2401
2402
  out_fput:
  	fput(src_file);
ab67b7c1f   Yan Zheng   Btrfs: Add missin...
2403
  out_drop_write:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
2404
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2405
2406
  	return ret;
  }
7a865e8ac   Christoph Hellwig   Btrfs: btrfs: pas...
2407
  static long btrfs_ioctl_clone_range(struct file *file, void __user *argp)
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2408
2409
  {
  	struct btrfs_ioctl_clone_range_args args;
7a865e8ac   Christoph Hellwig   Btrfs: btrfs: pas...
2410
  	if (copy_from_user(&args, argp, sizeof(args)))
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2411
2412
2413
2414
  		return -EFAULT;
  	return btrfs_ioctl_clone(file, args.src_fd, args.src_offset,
  				 args.src_length, args.dest_offset);
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2415
2416
2417
2418
2419
2420
  /*
   * 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...
2421
  static long btrfs_ioctl_trans_start(struct file *file)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2422
2423
2424
2425
  {
  	struct inode *inode = fdentry(file)->d_inode;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
1ab86aedb   Sage Weil   Btrfs: fix error ...
2426
  	int ret;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2427

1ab86aedb   Sage Weil   Btrfs: fix error ...
2428
  	ret = -EPERM;
df5b5520b   Christoph Hellwig   BTRFS_IOC_TRANS_S...
2429
  	if (!capable(CAP_SYS_ADMIN))
1ab86aedb   Sage Weil   Btrfs: fix error ...
2430
  		goto out;
df5b5520b   Christoph Hellwig   BTRFS_IOC_TRANS_S...
2431

1ab86aedb   Sage Weil   Btrfs: fix error ...
2432
2433
  	ret = -EINPROGRESS;
  	if (file->private_data)
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2434
  		goto out;
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
2435

b83cc9693   Li Zefan   Btrfs: Add readon...
2436
2437
2438
  	ret = -EROFS;
  	if (btrfs_root_readonly(root))
  		goto out;
a561be710   Al Viro   switch a bunch of...
2439
  	ret = mnt_want_write_file(file);
c146afad2   Yan Zheng   Btrfs: mount ro a...
2440
2441
  	if (ret)
  		goto out;
a4abeea41   Josef Bacik   Btrfs: kill trans...
2442
  	atomic_inc(&root->fs_info->open_ioctl_trans);
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
2443

1ab86aedb   Sage Weil   Btrfs: fix error ...
2444
  	ret = -ENOMEM;
7a7eaa40a   Josef Bacik   Btrfs: take away ...
2445
  	trans = btrfs_start_ioctl_transaction(root);
abd30bb0a   Tsutomu Itoh   btrfs: check retu...
2446
  	if (IS_ERR(trans))
1ab86aedb   Sage Weil   Btrfs: fix error ...
2447
2448
2449
2450
2451
2452
  		goto out_drop;
  
  	file->private_data = trans;
  	return 0;
  
  out_drop:
a4abeea41   Josef Bacik   Btrfs: kill trans...
2453
  	atomic_dec(&root->fs_info->open_ioctl_trans);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
2454
  	mnt_drop_write_file(file);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2455
  out:
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2456
2457
  	return ret;
  }
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
  static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
  {
  	struct inode *inode = fdentry(file)->d_inode;
  	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;
  	struct btrfs_super_block *disk_super;
  	u64 features;
  	u64 objectid = 0;
  	u64 dir_id;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	if (copy_from_user(&objectid, argp, sizeof(objectid)))
  		return -EFAULT;
  
  	if (!objectid)
  		objectid = root->root_key.objectid;
  
  	location.objectid = objectid;
  	location.type = BTRFS_ROOT_ITEM_KEY;
  	location.offset = (u64)-1;
  
  	new_root = btrfs_read_fs_root_no_name(root->fs_info, &location);
  	if (IS_ERR(new_root))
  		return PTR_ERR(new_root);
  
  	if (btrfs_root_refs(&new_root->root_item) == 0)
  		return -ENOENT;
  
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  	path->leave_spinning = 1;
  
  	trans = btrfs_start_transaction(root, 1);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
2499
  	if (IS_ERR(trans)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
2500
  		btrfs_free_path(path);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
2501
  		return PTR_ERR(trans);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
2502
  	}
6c41761fc   David Sterba   btrfs: separate s...
2503
  	dir_id = btrfs_super_root_dir(root->fs_info->super_copy);
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
2504
2505
  	di = btrfs_lookup_dir_item(trans, root->fs_info->tree_root, path,
  				   dir_id, "default", 7, 1);
cf1e99a4e   Dan Carpenter   Btrfs: btrfs_look...
2506
  	if (IS_ERR_OR_NULL(di)) {
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
  		btrfs_free_path(path);
  		btrfs_end_transaction(trans, root);
  		printk(KERN_ERR "Umm, you don't have the default dir item, "
  		       "this isn't going to work
  ");
  		return -ENOENT;
  	}
  
  	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);
6c41761fc   David Sterba   btrfs: separate s...
2519
  	disk_super = root->fs_info->super_copy;
6ef5ed0d3   Josef Bacik   Btrfs: add ioctl ...
2520
2521
2522
2523
2524
2525
2526
2527
2528
  	features = btrfs_super_incompat_flags(disk_super);
  	if (!(features & BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL)) {
  		features |= BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL;
  		btrfs_set_super_incompat_flags(disk_super, features);
  	}
  	btrfs_end_transaction(trans, root);
  
  	return 0;
  }
bf5fc093c   Josef Bacik   Btrfs: fix the df...
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
  static void get_block_group_info(struct list_head *groups_list,
  				 struct btrfs_ioctl_space_info *space)
  {
  	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);
  	}
  }
1406e4327   Josef Bacik   Btrfs: add a "df"...
2544
2545
2546
2547
2548
  long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
  {
  	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...
2549
  	struct btrfs_ioctl_space_info *dest_orig;
13f2696f1   Daniel J Blueman   fix user annotati...
2550
  	struct btrfs_ioctl_space_info __user *user_dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
2551
  	struct btrfs_space_info *info;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
2552
2553
2554
2555
2556
  	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...
2557
  	int alloc_size;
1406e4327   Josef Bacik   Btrfs: add a "df"...
2558
  	int ret = 0;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
2559
  	u64 slot_count = 0;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
2560
  	int i, c;
1406e4327   Josef Bacik   Btrfs: add a "df"...
2561
2562
2563
2564
2565
  
  	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...
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
  	for (i = 0; i < num_types; i++) {
  		struct btrfs_space_info *tmp;
  
  		info = NULL;
  		rcu_read_lock();
  		list_for_each_entry_rcu(tmp, &root->fs_info->space_info,
  					list) {
  			if (tmp->flags == types[i]) {
  				info = tmp;
  				break;
  			}
  		}
  		rcu_read_unlock();
  
  		if (!info)
  			continue;
  
  		down_read(&info->groups_sem);
  		for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
  			if (!list_empty(&info->block_groups[c]))
  				slot_count++;
  		}
  		up_read(&info->groups_sem);
  	}
7fde62bff   Chris Mason   Btrfs: buffer res...
2590
2591
2592
2593
2594
2595
  
  	/* 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...
2596

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

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

7fde62bff   Chris Mason   Btrfs: buffer res...
2601
2602
2603
2604
2605
  	/* we generally have at most 6 or so space infos, one for each raid
  	 * level.  So, a whole page should be more than enough for everyone
  	 */
  	if (alloc_size > PAGE_CACHE_SIZE)
  		return -ENOMEM;
1406e4327   Josef Bacik   Btrfs: add a "df"...
2606
  	space_args.total_spaces = 0;
7fde62bff   Chris Mason   Btrfs: buffer res...
2607
2608
2609
2610
  	dest = kmalloc(alloc_size, GFP_NOFS);
  	if (!dest)
  		return -ENOMEM;
  	dest_orig = dest;
1406e4327   Josef Bacik   Btrfs: add a "df"...
2611

7fde62bff   Chris Mason   Btrfs: buffer res...
2612
  	/* now we have a buffer to copy into */
bf5fc093c   Josef Bacik   Btrfs: fix the df...
2613
2614
  	for (i = 0; i < num_types; i++) {
  		struct btrfs_space_info *tmp;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
2615
2616
  		if (!slot_count)
  			break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
  		info = NULL;
  		rcu_read_lock();
  		list_for_each_entry_rcu(tmp, &root->fs_info->space_info,
  					list) {
  			if (tmp->flags == types[i]) {
  				info = tmp;
  				break;
  			}
  		}
  		rcu_read_unlock();
7fde62bff   Chris Mason   Btrfs: buffer res...
2627

bf5fc093c   Josef Bacik   Btrfs: fix the df...
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
  		if (!info)
  			continue;
  		down_read(&info->groups_sem);
  		for (c = 0; c < BTRFS_NR_RAID_TYPES; c++) {
  			if (!list_empty(&info->block_groups[c])) {
  				get_block_group_info(&info->block_groups[c],
  						     &space);
  				memcpy(dest, &space, sizeof(space));
  				dest++;
  				space_args.total_spaces++;
51788b1bd   Dan Rosenberg   btrfs: prevent he...
2638
  				slot_count--;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
2639
  			}
51788b1bd   Dan Rosenberg   btrfs: prevent he...
2640
2641
  			if (!slot_count)
  				break;
bf5fc093c   Josef Bacik   Btrfs: fix the df...
2642
2643
  		}
  		up_read(&info->groups_sem);
1406e4327   Josef Bacik   Btrfs: add a "df"...
2644
  	}
1406e4327   Josef Bacik   Btrfs: add a "df"...
2645

7fde62bff   Chris Mason   Btrfs: buffer res...
2646
2647
2648
2649
2650
2651
2652
2653
2654
  	user_dest = (struct btrfs_ioctl_space_info *)
  		(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"...
2655
2656
2657
2658
  		ret = -EFAULT;
  
  	return ret;
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
  /*
   * 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)
  {
  	struct inode *inode = fdentry(file)->d_inode;
  	struct btrfs_root *root = BTRFS_I(inode)->root;
  	struct btrfs_trans_handle *trans;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2670

f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2671
  	trans = file->private_data;
1ab86aedb   Sage Weil   Btrfs: fix error ...
2672
2673
  	if (!trans)
  		return -EINVAL;
b214107ed   Christoph Hellwig   Btrfs: trivial sp...
2674
  	file->private_data = NULL;
9ca9ee09c   Sage Weil   Btrfs: fix ioctl-...
2675

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

2a79f17e4   Al Viro   vfs: mnt_drop_wri...
2679
  	mnt_drop_write_file(file);
1ab86aedb   Sage Weil   Btrfs: fix error ...
2680
  	return 0;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2681
  }
462045928   Sage Weil   Btrfs: add START_...
2682
2683
2684
2685
2686
  static noinline long btrfs_ioctl_start_sync(struct file *file, void __user *argp)
  {
  	struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;
  	struct btrfs_trans_handle *trans;
  	u64 transid;
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
2687
  	int ret;
462045928   Sage Weil   Btrfs: add START_...
2688
2689
  
  	trans = btrfs_start_transaction(root, 0);
98d5dc13e   Tsutomu Itoh   btrfs: fix return...
2690
2691
  	if (IS_ERR(trans))
  		return PTR_ERR(trans);
462045928   Sage Weil   Btrfs: add START_...
2692
  	transid = trans->transid;
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
2693
  	ret = btrfs_commit_transaction_async(trans, root, 0);
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
2694
2695
  	if (ret) {
  		btrfs_end_transaction(trans, root);
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
2696
  		return ret;
8b2b2d3cb   Tsutomu Itoh   Btrfs: fix memory...
2697
  	}
462045928   Sage Weil   Btrfs: add START_...
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
  
  	if (argp)
  		if (copy_to_user(argp, &transid, sizeof(transid)))
  			return -EFAULT;
  	return 0;
  }
  
  static noinline long btrfs_ioctl_wait_sync(struct file *file, void __user *argp)
  {
  	struct btrfs_root *root = BTRFS_I(file->f_dentry->d_inode)->root;
  	u64 transid;
  
  	if (argp) {
  		if (copy_from_user(&transid, argp, sizeof(transid)))
  			return -EFAULT;
  	} else {
  		transid = 0;  /* current trans */
  	}
  	return btrfs_wait_for_commit(root, transid);
  }
475f63874   Jan Schmidt   btrfs: new ioctls...
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
  static long btrfs_ioctl_scrub(struct btrfs_root *root, void __user *arg)
  {
  	int ret;
  	struct btrfs_ioctl_scrub_args *sa;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
  
  	ret = btrfs_scrub_dev(root, sa->devid, sa->start, sa->end,
8628764e1   Arne Jansen   btrfs: add readon...
2731
  			      &sa->progress, sa->flags & BTRFS_SCRUB_READONLY);
475f63874   Jan Schmidt   btrfs: new ioctls...
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
  
  	kfree(sa);
  	return ret;
  }
  
  static long btrfs_ioctl_scrub_cancel(struct btrfs_root *root, void __user *arg)
  {
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	return btrfs_scrub_cancel(root);
  }
  
  static long btrfs_ioctl_scrub_progress(struct btrfs_root *root,
  				       void __user *arg)
  {
  	struct btrfs_ioctl_scrub_args *sa;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	sa = memdup_user(arg, sizeof(*sa));
  	if (IS_ERR(sa))
  		return PTR_ERR(sa);
  
  	ret = btrfs_scrub_progress(root, sa->devid, &sa->progress);
  
  	if (copy_to_user(arg, sa, sizeof(*sa)))
  		ret = -EFAULT;
  
  	kfree(sa);
  	return ret;
  }
d7728c960   Jan Schmidt   btrfs: new ioctls...
2769
2770
2771
2772
  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...
2773
  	u64 rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
2774
  	int size;
806468f8b   Chris Mason   Merge git://git.j...
2775
  	struct btrfs_ioctl_ino_path_args *ipa = NULL;
d7728c960   Jan Schmidt   btrfs: new ioctls...
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
  	struct inode_fs_paths *ipath = NULL;
  	struct btrfs_path *path;
  
  	if (!capable(CAP_SYS_ADMIN))
  		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/...
2808
2809
  		rel_ptr = ipath->fspath->val[i] -
  			  (u64)(unsigned long)ipath->fspath->val;
740c3d226   Chris Mason   Btrfs: fix the ne...
2810
  		ipath->fspath->val[i] = rel_ptr;
d7728c960   Jan Schmidt   btrfs: new ioctls...
2811
  	}
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
2812
2813
  	ret = copy_to_user((void *)(unsigned long)ipa->fspath,
  			   (void *)(unsigned long)ipath->fspath, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
  	if (ret) {
  		ret = -EFAULT;
  		goto out;
  	}
  
  out:
  	btrfs_free_path(path);
  	free_ipath(ipath);
  	kfree(ipa);
  
  	return ret;
  }
  
  static int build_ino_list(u64 inum, u64 offset, u64 root, void *ctx)
  {
  	struct btrfs_data_container *inodes = ctx;
  	const size_t c = 3 * sizeof(u64);
  
  	if (inodes->bytes_left >= c) {
  		inodes->bytes_left -= c;
  		inodes->val[inodes->elem_cnt] = inum;
  		inodes->val[inodes->elem_cnt + 1] = offset;
  		inodes->val[inodes->elem_cnt + 2] = root;
  		inodes->elem_cnt += 3;
  	} else {
  		inodes->bytes_missing += c - inodes->bytes_left;
  		inodes->bytes_left = 0;
  		inodes->elem_missed += 3;
  	}
  
  	return 0;
  }
  
  static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
  					void __user *arg)
  {
  	int ret = 0;
  	int size;
  	u64 extent_offset;
  	struct btrfs_ioctl_logical_ino_args *loi;
  	struct btrfs_data_container *inodes = NULL;
  	struct btrfs_path *path = NULL;
  	struct btrfs_key key;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	loi = memdup_user(arg, sizeof(*loi));
  	if (IS_ERR(loi)) {
  		ret = PTR_ERR(loi);
  		loi = NULL;
  		goto out;
  	}
  
  	path = btrfs_alloc_path();
  	if (!path) {
  		ret = -ENOMEM;
  		goto out;
  	}
  
  	size = min_t(u32, loi->size, 4096);
  	inodes = init_data_container(size);
  	if (IS_ERR(inodes)) {
  		ret = PTR_ERR(inodes);
  		inodes = NULL;
  		goto out;
  	}
  
  	ret = extent_from_logical(root->fs_info, loi->logical, path, &key);
  
  	if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
  		ret = -ENOENT;
  	if (ret < 0)
  		goto out;
  
  	extent_offset = loi->logical - key.objectid;
  	ret = iterate_extent_inodes(root->fs_info, path, key.objectid,
  					extent_offset, build_ino_list, inodes);
  
  	if (ret < 0)
  		goto out;
745c4d8e1   Jeff Mahoney   btrfs: Fix up 32/...
2895
2896
  	ret = copy_to_user((void *)(unsigned long)loi->inodes,
  			   (void *)(unsigned long)inodes, size);
d7728c960   Jan Schmidt   btrfs: new ioctls...
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
  	if (ret)
  		ret = -EFAULT;
  
  out:
  	btrfs_free_path(path);
  	kfree(inodes);
  	kfree(loi);
  
  	return ret;
  }
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2907
2908
2909
2910
  long btrfs_ioctl(struct file *file, unsigned int
  		cmd, unsigned long arg)
  {
  	struct btrfs_root *root = BTRFS_I(fdentry(file)->d_inode)->root;
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
2911
  	void __user *argp = (void __user *)arg;
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2912
2913
  
  	switch (cmd) {
6cbff00f4   Christoph Hellwig   Btrfs: implement ...
2914
2915
2916
2917
2918
2919
  	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_...
2920
2921
  	case FITRIM:
  		return btrfs_ioctl_fitrim(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2922
  	case BTRFS_IOC_SNAP_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
2923
  		return btrfs_ioctl_snap_create(file, argp, 0);
fdfb1e4f6   Li Zefan   Btrfs: Make async...
2924
  	case BTRFS_IOC_SNAP_CREATE_V2:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
2925
  		return btrfs_ioctl_snap_create_v2(file, argp, 0);
3de4586c5   Chris Mason   Btrfs: Allow subv...
2926
  	case BTRFS_IOC_SUBVOL_CREATE:
fa0d2b9bd   Li Zefan   Btrfs: Refactor b...
2927
  		return btrfs_ioctl_snap_create(file, argp, 1);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
2928
2929
  	case BTRFS_IOC_SNAP_DESTROY:
  		return btrfs_ioctl_snap_destroy(file, argp);
0caa102da   Li Zefan   Btrfs: Add BTRFS_...
2930
2931
2932
2933
  	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 ...
2934
2935
  	case BTRFS_IOC_DEFAULT_SUBVOL:
  		return btrfs_ioctl_default_subvol(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2936
  	case BTRFS_IOC_DEFRAG:
1e701a329   Chris Mason   Btrfs: add new de...
2937
2938
2939
  		return btrfs_ioctl_defrag(file, NULL);
  	case BTRFS_IOC_DEFRAG_RANGE:
  		return btrfs_ioctl_defrag(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2940
  	case BTRFS_IOC_RESIZE:
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
2941
  		return btrfs_ioctl_resize(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2942
  	case BTRFS_IOC_ADD_DEV:
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
2943
  		return btrfs_ioctl_add_dev(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2944
  	case BTRFS_IOC_RM_DEV:
4bcabaa30   Christoph Hellwig   Btrfs: clean up b...
2945
  		return btrfs_ioctl_rm_dev(root, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
2946
2947
2948
2949
  	case BTRFS_IOC_FS_INFO:
  		return btrfs_ioctl_fs_info(root, argp);
  	case BTRFS_IOC_DEV_INFO:
  		return btrfs_ioctl_dev_info(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2950
2951
2952
  	case BTRFS_IOC_BALANCE:
  		return btrfs_balance(root->fs_info->dev_root);
  	case BTRFS_IOC_CLONE:
c5c9cd4d1   Sage Weil   Btrfs: allow clon...
2953
2954
  		return btrfs_ioctl_clone(file, arg, 0, 0, 0);
  	case BTRFS_IOC_CLONE_RANGE:
7a865e8ac   Christoph Hellwig   Btrfs: btrfs: pas...
2955
  		return btrfs_ioctl_clone_range(file, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2956
2957
2958
2959
  	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...
2960
2961
2962
2963
  	case BTRFS_IOC_TREE_SEARCH:
  		return btrfs_ioctl_tree_search(file, argp);
  	case BTRFS_IOC_INO_LOOKUP:
  		return btrfs_ioctl_ino_lookup(file, argp);
d7728c960   Jan Schmidt   btrfs: new ioctls...
2964
2965
2966
2967
  	case BTRFS_IOC_INO_PATHS:
  		return btrfs_ioctl_ino_to_path(root, argp);
  	case BTRFS_IOC_LOGICAL_INO:
  		return btrfs_ioctl_logical_to_ino(root, argp);
1406e4327   Josef Bacik   Btrfs: add a "df"...
2968
2969
  	case BTRFS_IOC_SPACE_INFO:
  		return btrfs_ioctl_space_info(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2970
2971
2972
  	case BTRFS_IOC_SYNC:
  		btrfs_sync_fs(file->f_dentry->d_sb, 1);
  		return 0;
462045928   Sage Weil   Btrfs: add START_...
2973
2974
2975
2976
  	case BTRFS_IOC_START_SYNC:
  		return btrfs_ioctl_start_sync(file, argp);
  	case BTRFS_IOC_WAIT_SYNC:
  		return btrfs_ioctl_wait_sync(file, argp);
475f63874   Jan Schmidt   btrfs: new ioctls...
2977
2978
2979
2980
2981
2982
  	case BTRFS_IOC_SCRUB:
  		return btrfs_ioctl_scrub(root, argp);
  	case BTRFS_IOC_SCRUB_CANCEL:
  		return btrfs_ioctl_scrub_cancel(root, argp);
  	case BTRFS_IOC_SCRUB_PROGRESS:
  		return btrfs_ioctl_scrub_progress(root, argp);
f46b5a66b   Christoph Hellwig   Btrfs: split out ...
2983
2984
2985
2986
  	}
  
  	return -ENOTTY;
  }