Blame view

fs/nilfs2/ioctl.c 21 KB
7942b919f   Koji Sato   nilfs2: ioctl ope...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  /*
   * ioctl.c - NILFS ioctl operations.
   *
   * Copyright (C) 2007, 2008 Nippon Telegraph and Telephone Corporation.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   *
   * Written by Koji Sato <koji@osrg.net>.
   */
  
  #include <linux/fs.h>
  #include <linux/wait.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
25
  #include <linux/slab.h>
7942b919f   Koji Sato   nilfs2: ioctl ope...
26
27
  #include <linux/capability.h>	/* capable() */
  #include <linux/uaccess.h>	/* copy_from_user(), copy_to_user() */
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
28
  #include <linux/vmalloc.h>
828b1c50a   Ryusuke Konishi   nilfs2: add compa...
29
  #include <linux/compat.h>	/* compat_ptr() */
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
30
  #include <linux/mount.h>	/* mnt_want_write_file(), mnt_drop_write_file() */
ae191838b   Ryusuke Konishi   nilfs2: optimize ...
31
  #include <linux/buffer_head.h>
7942b919f   Koji Sato   nilfs2: ioctl ope...
32
33
34
35
36
37
38
  #include <linux/nilfs2_fs.h>
  #include "nilfs.h"
  #include "segment.h"
  #include "bmap.h"
  #include "cpfile.h"
  #include "sufile.h"
  #include "dat.h"
7942b919f   Koji Sato   nilfs2: ioctl ope...
39
40
41
  static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
  				 struct nilfs_argv *argv, int dir,
  				 ssize_t (*dofunc)(struct the_nilfs *,
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
42
  						   __u64 *, int,
7942b919f   Koji Sato   nilfs2: ioctl ope...
43
44
45
  						   void *, size_t, size_t))
  {
  	void *buf;
dc498d09b   Ryusuke Konishi   nilfs2: use fixed...
46
  	void __user *base = (void __user *)(unsigned long)argv->v_base;
3358b4aaa   Ryusuke Konishi   nilfs2: fix probl...
47
  	size_t maxmembs, total, n;
7942b919f   Koji Sato   nilfs2: ioctl ope...
48
49
  	ssize_t nr;
  	int ret, i;
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
50
  	__u64 pos, ppos;
7942b919f   Koji Sato   nilfs2: ioctl ope...
51
52
53
  
  	if (argv->v_nmembs == 0)
  		return 0;
3358b4aaa   Ryusuke Konishi   nilfs2: fix probl...
54
55
56
57
58
  	if (argv->v_size > PAGE_SIZE)
  		return -EINVAL;
  
  	buf = (void *)__get_free_pages(GFP_NOFS, 0);
  	if (unlikely(!buf))
7942b919f   Koji Sato   nilfs2: ioctl ope...
59
  		return -ENOMEM;
3358b4aaa   Ryusuke Konishi   nilfs2: fix probl...
60
  	maxmembs = PAGE_SIZE / argv->v_size;
7942b919f   Koji Sato   nilfs2: ioctl ope...
61
62
63
  
  	ret = 0;
  	total = 0;
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
64
  	pos = argv->v_index;
7942b919f   Koji Sato   nilfs2: ioctl ope...
65
66
67
68
  	for (i = 0; i < argv->v_nmembs; i += n) {
  		n = (argv->v_nmembs - i < maxmembs) ?
  			argv->v_nmembs - i : maxmembs;
  		if ((dir & _IOC_WRITE) &&
dc498d09b   Ryusuke Konishi   nilfs2: use fixed...
69
70
  		    copy_from_user(buf, base + argv->v_size * i,
  				   argv->v_size * n)) {
7942b919f   Koji Sato   nilfs2: ioctl ope...
71
72
73
  			ret = -EFAULT;
  			break;
  		}
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
74
  		ppos = pos;
8acfbf093   Pekka Enberg   nilfs2: clean up ...
75
  		nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size,
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
76
  			       n);
7942b919f   Koji Sato   nilfs2: ioctl ope...
77
78
79
80
81
  		if (nr < 0) {
  			ret = nr;
  			break;
  		}
  		if ((dir & _IOC_READ) &&
dc498d09b   Ryusuke Konishi   nilfs2: use fixed...
82
83
  		    copy_to_user(base + argv->v_size * i, buf,
  				 argv->v_size * nr)) {
7942b919f   Koji Sato   nilfs2: ioctl ope...
84
85
86
87
  			ret = -EFAULT;
  			break;
  		}
  		total += nr;
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
88
89
90
91
  		if ((size_t)nr < n)
  			break;
  		if (pos == ppos)
  			pos += n;
7942b919f   Koji Sato   nilfs2: ioctl ope...
92
93
  	}
  	argv->v_nmembs = total;
3358b4aaa   Ryusuke Konishi   nilfs2: fix probl...
94
  	free_pages((unsigned long)buf, 0);
7942b919f   Koji Sato   nilfs2: ioctl ope...
95
96
  	return ret;
  }
cde98f0f8   Ryusuke Konishi   nilfs2: implement...
97
98
99
100
101
102
103
104
105
106
107
108
109
  static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
  {
  	unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
  
  	return put_user(flags, (int __user *)argp);
  }
  
  static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
  				void __user *argp)
  {
  	struct nilfs_transaction_info ti;
  	unsigned int flags, oldflags;
  	int ret;
2e1496707   Serge E. Hallyn   userns: rename is...
110
  	if (!inode_owner_or_capable(inode))
cde98f0f8   Ryusuke Konishi   nilfs2: implement...
111
112
113
114
  		return -EACCES;
  
  	if (get_user(flags, (int __user *)argp))
  		return -EFAULT;
a561be710   Al Viro   switch a bunch of...
115
  	ret = mnt_want_write_file(filp);
cde98f0f8   Ryusuke Konishi   nilfs2: implement...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  	if (ret)
  		return ret;
  
  	flags = nilfs_mask_flags(inode->i_mode, flags);
  
  	mutex_lock(&inode->i_mutex);
  
  	oldflags = NILFS_I(inode)->i_flags;
  
  	/*
  	 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
  	 * relevant capability.
  	 */
  	ret = -EPERM;
  	if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
  	    !capable(CAP_LINUX_IMMUTABLE))
  		goto out;
  
  	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
  	if (ret)
  		goto out;
  
  	NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
  		(flags & FS_FL_USER_MODIFIABLE);
  
  	nilfs_set_inode_flags(inode);
  	inode->i_ctime = CURRENT_TIME;
  	if (IS_SYNC(inode))
  		nilfs_set_transaction_flag(NILFS_TI_SYNC);
  
  	nilfs_mark_inode_dirty(inode);
  	ret = nilfs_transaction_commit(inode->i_sb);
  out:
  	mutex_unlock(&inode->i_mutex);
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
150
  	mnt_drop_write_file(filp);
cde98f0f8   Ryusuke Konishi   nilfs2: implement...
151
152
153
154
155
156
157
  	return ret;
  }
  
  static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
  {
  	return put_user(inode->i_generation, (int __user *)argp);
  }
7942b919f   Koji Sato   nilfs2: ioctl ope...
158
159
160
  static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
  				     unsigned int cmd, void __user *argp)
  {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
161
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
162
163
164
165
166
167
  	struct nilfs_transaction_info ti;
  	struct nilfs_cpmode cpmode;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
168

a561be710   Al Viro   switch a bunch of...
169
  	ret = mnt_want_write_file(filp);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
170
171
172
173
  	if (ret)
  		return ret;
  
  	ret = -EFAULT;
7942b919f   Koji Sato   nilfs2: ioctl ope...
174
  	if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
175
  		goto out;
7942b919f   Koji Sato   nilfs2: ioctl ope...
176

348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
177
  	down_read(&inode->i_sb->s_umount);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
178

7942b919f   Koji Sato   nilfs2: ioctl ope...
179
180
  	nilfs_transaction_begin(inode->i_sb, &ti, 0);
  	ret = nilfs_cpfile_change_cpmode(
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
181
  		nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
182
  	if (unlikely(ret < 0))
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
183
  		nilfs_transaction_abort(inode->i_sb);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
184
185
  	else
  		nilfs_transaction_commit(inode->i_sb); /* never fails */
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
186
  	up_read(&inode->i_sb->s_umount);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
187
  out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
188
  	mnt_drop_write_file(filp);
7942b919f   Koji Sato   nilfs2: ioctl ope...
189
190
191
192
193
194
195
  	return ret;
  }
  
  static int
  nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
  			      unsigned int cmd, void __user *argp)
  {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
196
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
197
198
199
200
201
202
  	struct nilfs_transaction_info ti;
  	__u64 cno;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
203

a561be710   Al Viro   switch a bunch of...
204
  	ret = mnt_want_write_file(filp);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
205
206
207
208
  	if (ret)
  		return ret;
  
  	ret = -EFAULT;
7942b919f   Koji Sato   nilfs2: ioctl ope...
209
  	if (copy_from_user(&cno, argp, sizeof(cno)))
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
210
  		goto out;
7942b919f   Koji Sato   nilfs2: ioctl ope...
211
212
  
  	nilfs_transaction_begin(inode->i_sb, &ti, 0);
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
213
  	ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
214
  	if (unlikely(ret < 0))
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
215
  		nilfs_transaction_abort(inode->i_sb);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
216
217
218
  	else
  		nilfs_transaction_commit(inode->i_sb); /* never fails */
  out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
219
  	mnt_drop_write_file(filp);
7942b919f   Koji Sato   nilfs2: ioctl ope...
220
221
222
223
  	return ret;
  }
  
  static ssize_t
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
224
  nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
225
226
  			  void *buf, size_t size, size_t nmembs)
  {
7942b919f   Koji Sato   nilfs2: ioctl ope...
227
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
228
  	down_read(&nilfs->ns_segctor_sem);
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
229
  	ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
003ff182f   Ryusuke Konishi   nilfs2: allow fut...
230
  				      size, nmembs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
231
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
232
233
234
235
236
237
  	return ret;
  }
  
  static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
  				  unsigned int cmd, void __user *argp)
  {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
238
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
239
  	struct nilfs_cpstat cpstat;
7942b919f   Koji Sato   nilfs2: ioctl ope...
240
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
241
242
243
  	down_read(&nilfs->ns_segctor_sem);
  	ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
244
245
246
247
248
249
250
251
252
  	if (ret < 0)
  		return ret;
  
  	if (copy_to_user(argp, &cpstat, sizeof(cpstat)))
  		ret = -EFAULT;
  	return ret;
  }
  
  static ssize_t
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
253
  nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
254
255
  			  void *buf, size_t size, size_t nmembs)
  {
7942b919f   Koji Sato   nilfs2: ioctl ope...
256
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
257
  	down_read(&nilfs->ns_segctor_sem);
003ff182f   Ryusuke Konishi   nilfs2: allow fut...
258
259
  	ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
  				      nmembs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
260
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
261
262
263
264
265
266
  	return ret;
  }
  
  static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
  				  unsigned int cmd, void __user *argp)
  {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
267
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
268
  	struct nilfs_sustat sustat;
7942b919f   Koji Sato   nilfs2: ioctl ope...
269
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
270
271
272
  	down_read(&nilfs->ns_segctor_sem);
  	ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
273
274
275
276
277
278
279
280
281
  	if (ret < 0)
  		return ret;
  
  	if (copy_to_user(argp, &sustat, sizeof(sustat)))
  		ret = -EFAULT;
  	return ret;
  }
  
  static ssize_t
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
282
  nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
283
284
  			 void *buf, size_t size, size_t nmembs)
  {
7942b919f   Koji Sato   nilfs2: ioctl ope...
285
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
286
  	down_read(&nilfs->ns_segctor_sem);
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
287
  	ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
288
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
289
290
291
292
  	return ret;
  }
  
  static ssize_t
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
293
  nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
294
295
  			  void *buf, size_t size, size_t nmembs)
  {
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
296
  	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
7942b919f   Koji Sato   nilfs2: ioctl ope...
297
298
  	struct nilfs_bdesc *bdescs = buf;
  	int ret, i;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
299
  	down_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
300
301
302
303
304
305
  	for (i = 0; i < nmembs; i++) {
  		ret = nilfs_bmap_lookup_at_level(bmap,
  						 bdescs[i].bd_offset,
  						 bdescs[i].bd_level + 1,
  						 &bdescs[i].bd_blocknr);
  		if (ret < 0) {
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
306
307
  			if (ret != -ENOENT) {
  				up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
308
  				return ret;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
309
  			}
7942b919f   Koji Sato   nilfs2: ioctl ope...
310
311
312
  			bdescs[i].bd_blocknr = 0;
  		}
  	}
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
313
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
314
315
316
317
318
319
  	return nmembs;
  }
  
  static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
  				  unsigned int cmd, void __user *argp)
  {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
320
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
321
  	struct nilfs_argv argv;
7942b919f   Koji Sato   nilfs2: ioctl ope...
322
323
324
325
  	int ret;
  
  	if (copy_from_user(&argv, argp, sizeof(argv)))
  		return -EFAULT;
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
326
327
  	if (argv.v_size != sizeof(struct nilfs_bdesc))
  		return -EINVAL;
7942b919f   Koji Sato   nilfs2: ioctl ope...
328
329
  	ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
  				    nilfs_ioctl_do_get_bdescs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
330
331
  	if (ret < 0)
  		return ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
  
  	if (copy_to_user(argp, &argv, sizeof(argv)))
  		ret = -EFAULT;
  	return ret;
  }
  
  static int nilfs_ioctl_move_inode_block(struct inode *inode,
  					struct nilfs_vdesc *vdesc,
  					struct list_head *buffers)
  {
  	struct buffer_head *bh;
  	int ret;
  
  	if (vdesc->vd_flags == 0)
  		ret = nilfs_gccache_submit_read_data(
  			inode, vdesc->vd_offset, vdesc->vd_blocknr,
  			vdesc->vd_vblocknr, &bh);
  	else
  		ret = nilfs_gccache_submit_read_node(
  			inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
  
  	if (unlikely(ret < 0)) {
  		if (ret == -ENOENT)
  			printk(KERN_CRIT
  			       "%s: invalid virtual block address (%s): "
  			       "ino=%llu, cno=%llu, offset=%llu, "
  			       "blocknr=%llu, vblocknr=%llu
  ",
  			       __func__, vdesc->vd_flags ? "node" : "data",
  			       (unsigned long long)vdesc->vd_ino,
  			       (unsigned long long)vdesc->vd_cno,
  			       (unsigned long long)vdesc->vd_offset,
  			       (unsigned long long)vdesc->vd_blocknr,
  			       (unsigned long long)vdesc->vd_vblocknr);
  		return ret;
  	}
5399dd1fc   Ryusuke Konishi   nilfs2: fix kerne...
368
369
370
371
372
373
374
375
376
377
378
379
380
  	if (unlikely(!list_empty(&bh->b_assoc_buffers))) {
  		printk(KERN_CRIT "%s: conflicting %s buffer: ino=%llu, "
  		       "cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu
  ",
  		       __func__, vdesc->vd_flags ? "node" : "data",
  		       (unsigned long long)vdesc->vd_ino,
  		       (unsigned long long)vdesc->vd_cno,
  		       (unsigned long long)vdesc->vd_offset,
  		       (unsigned long long)vdesc->vd_blocknr,
  		       (unsigned long long)vdesc->vd_vblocknr);
  		brelse(bh);
  		return -EEXIST;
  	}
7942b919f   Koji Sato   nilfs2: ioctl ope...
381
382
383
  	list_add_tail(&bh->b_assoc_buffers, buffers);
  	return 0;
  }
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
384
  static int nilfs_ioctl_move_blocks(struct super_block *sb,
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
385
  				   struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
386
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
387
  	size_t nmembs = argv->v_nmembs;
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
388
  	struct the_nilfs *nilfs = sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
389
390
391
392
393
394
395
396
397
398
399
  	struct inode *inode;
  	struct nilfs_vdesc *vdesc;
  	struct buffer_head *bh, *n;
  	LIST_HEAD(buffers);
  	ino_t ino;
  	__u64 cno;
  	int i, ret;
  
  	for (i = 0, vdesc = buf; i < nmembs; ) {
  		ino = vdesc->vd_ino;
  		cno = vdesc->vd_cno;
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
400
  		inode = nilfs_iget_for_gc(sb, ino, cno);
103cfcf52   Dan Carpenter   nilfs2: nilfs_ige...
401
402
  		if (IS_ERR(inode)) {
  			ret = PTR_ERR(inode);
7942b919f   Koji Sato   nilfs2: ioctl ope...
403
404
  			goto failed;
  		}
947b10ae0   Ryusuke Konishi   nilfs2: fix regre...
405
406
407
408
409
410
411
412
413
414
  		if (list_empty(&NILFS_I(inode)->i_dirty)) {
  			/*
  			 * Add the inode to GC inode list. Garbage Collection
  			 * is serialized and no two processes manipulate the
  			 * list simultaneously.
  			 */
  			igrab(inode);
  			list_add(&NILFS_I(inode)->i_dirty,
  				 &nilfs->ns_gc_inodes);
  		}
7942b919f   Koji Sato   nilfs2: ioctl ope...
415
416
417
  		do {
  			ret = nilfs_ioctl_move_inode_block(inode, vdesc,
  							   &buffers);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
418
419
  			if (unlikely(ret < 0)) {
  				iput(inode);
7942b919f   Koji Sato   nilfs2: ioctl ope...
420
  				goto failed;
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
421
  			}
7942b919f   Koji Sato   nilfs2: ioctl ope...
422
423
424
  			vdesc++;
  		} while (++i < nmembs &&
  			 vdesc->vd_ino == ino && vdesc->vd_cno == cno);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
425
426
  
  		iput(inode); /* The inode still remains in GC inode list */
7942b919f   Koji Sato   nilfs2: ioctl ope...
427
428
429
430
431
  	}
  
  	list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
  		ret = nilfs_gccache_wait_and_mark_dirty(bh);
  		if (unlikely(ret < 0)) {
5399dd1fc   Ryusuke Konishi   nilfs2: fix kerne...
432
  			WARN_ON(ret == -EEXIST);
7942b919f   Koji Sato   nilfs2: ioctl ope...
433
434
435
  			goto failed;
  		}
  		list_del_init(&bh->b_assoc_buffers);
7942b919f   Koji Sato   nilfs2: ioctl ope...
436
437
438
439
440
441
442
  		brelse(bh);
  	}
  	return nmembs;
  
   failed:
  	list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
  		list_del_init(&bh->b_assoc_buffers);
7942b919f   Koji Sato   nilfs2: ioctl ope...
443
444
445
446
  		brelse(bh);
  	}
  	return ret;
  }
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
447
448
  static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
  					  struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
449
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
450
  	size_t nmembs = argv->v_nmembs;
7942b919f   Koji Sato   nilfs2: ioctl ope...
451
452
453
454
455
456
457
458
459
460
461
462
  	struct inode *cpfile = nilfs->ns_cpfile;
  	struct nilfs_period *periods = buf;
  	int ret, i;
  
  	for (i = 0; i < nmembs; i++) {
  		ret = nilfs_cpfile_delete_checkpoints(
  			cpfile, periods[i].p_start, periods[i].p_end);
  		if (ret < 0)
  			return ret;
  	}
  	return nmembs;
  }
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
463
464
  static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
  				      struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
465
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
466
467
  	size_t nmembs = argv->v_nmembs;
  	int ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
468

365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
469
  	ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs);
7942b919f   Koji Sato   nilfs2: ioctl ope...
470
471
472
  
  	return (ret < 0) ? ret : nmembs;
  }
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
473
474
  static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
  					 struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
475
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
476
  	size_t nmembs = argv->v_nmembs;
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
477
  	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
7942b919f   Koji Sato   nilfs2: ioctl ope...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
  	struct nilfs_bdesc *bdescs = buf;
  	int ret, i;
  
  	for (i = 0; i < nmembs; i++) {
  		/* XXX: use macro or inline func to check liveness */
  		ret = nilfs_bmap_lookup_at_level(bmap,
  						 bdescs[i].bd_offset,
  						 bdescs[i].bd_level + 1,
  						 &bdescs[i].bd_blocknr);
  		if (ret < 0) {
  			if (ret != -ENOENT)
  				return ret;
  			bdescs[i].bd_blocknr = 0;
  		}
  		if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr)
  			/* skip dead block */
  			continue;
  		if (bdescs[i].bd_level == 0) {
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
496
  			ret = nilfs_mdt_mark_block_dirty(nilfs->ns_dat,
7942b919f   Koji Sato   nilfs2: ioctl ope...
497
498
  							 bdescs[i].bd_offset);
  			if (ret < 0) {
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
499
  				WARN_ON(ret == -ENOENT);
7942b919f   Koji Sato   nilfs2: ioctl ope...
500
501
502
503
504
505
  				return ret;
  			}
  		} else {
  			ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset,
  					      bdescs[i].bd_level);
  			if (ret < 0) {
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
506
  				WARN_ON(ret == -ENOENT);
7942b919f   Koji Sato   nilfs2: ioctl ope...
507
508
509
510
511
512
  				return ret;
  			}
  		}
  	}
  	return nmembs;
  }
7942b919f   Koji Sato   nilfs2: ioctl ope...
513
  int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
514
  				       struct nilfs_argv *argv, void **kbufs)
7942b919f   Koji Sato   nilfs2: ioctl ope...
515
  {
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
516
  	const char *msg;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
517
  	int ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
518

4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
519
  	ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
520
521
522
523
524
525
526
527
  	if (ret < 0) {
  		/*
  		 * can safely abort because checkpoints can be removed
  		 * independently.
  		 */
  		msg = "cannot delete checkpoints";
  		goto failed;
  	}
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
528
  	ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
529
530
531
532
533
534
535
536
  	if (ret < 0) {
  		/*
  		 * can safely abort because DAT file is updated atomically
  		 * using a copy-on-write technique.
  		 */
  		msg = "cannot delete virtual blocks from DAT file";
  		goto failed;
  	}
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
537
  	ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
538
539
540
541
542
543
544
  	if (ret < 0) {
  		/*
  		 * can safely abort because the operation is nondestructive.
  		 */
  		msg = "cannot mark copying blocks dirty";
  		goto failed;
  	}
7942b919f   Koji Sato   nilfs2: ioctl ope...
545
  	return 0;
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
546
   failed:
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
547
548
549
  	printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d
  ",
  	       msg, ret);
7942b919f   Koji Sato   nilfs2: ioctl ope...
550
551
552
553
554
555
  	return ret;
  }
  
  static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
  				      unsigned int cmd, void __user *argp)
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
556
  	struct nilfs_argv argv[5];
33e189bd5   Tobias Klauser   nilfs2: Storage c...
557
  	static const size_t argsz[5] = {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
558
559
560
561
562
563
564
565
566
567
568
  		sizeof(struct nilfs_vdesc),
  		sizeof(struct nilfs_period),
  		sizeof(__u64),
  		sizeof(struct nilfs_bdesc),
  		sizeof(__u64),
  	};
  	void __user *base;
  	void *kbufs[5];
  	struct the_nilfs *nilfs;
  	size_t len, nsegs;
  	int n, ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
569
570
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
571

a561be710   Al Viro   switch a bunch of...
572
  	ret = mnt_want_write_file(filp);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
573
574
575
576
  	if (ret)
  		return ret;
  
  	ret = -EFAULT;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
577
  	if (copy_from_user(argv, argp, sizeof(argv)))
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
578
  		goto out;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
579

7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
580
  	ret = -EINVAL;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
581
582
  	nsegs = argv[4].v_nmembs;
  	if (argv[4].v_size != argsz[4])
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
583
  		goto out;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
584
585
586
587
588
589
590
  	/*
  	 * argv[4] points to segment numbers this ioctl cleans.  We
  	 * use kmalloc() for its buffer because memory used for the
  	 * segment numbers is enough small.
  	 */
  	kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base,
  			       nsegs * sizeof(__u64));
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
591
592
593
594
  	if (IS_ERR(kbufs[4])) {
  		ret = PTR_ERR(kbufs[4]);
  		goto out;
  	}
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
595
  	nilfs = inode->i_sb->s_fs_info;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
596
597
598
599
600
601
602
603
  
  	for (n = 0; n < 4; n++) {
  		ret = -EINVAL;
  		if (argv[n].v_size != argsz[n])
  			goto out_free;
  
  		if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment)
  			goto out_free;
481fe17e9   Haogang Chen   nilfs2: potential...
604
605
  		if (argv[n].v_nmembs >= UINT_MAX / argv[n].v_size)
  			goto out_free;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  		len = argv[n].v_size * argv[n].v_nmembs;
  		base = (void __user *)(unsigned long)argv[n].v_base;
  		if (len == 0) {
  			kbufs[n] = NULL;
  			continue;
  		}
  
  		kbufs[n] = vmalloc(len);
  		if (!kbufs[n]) {
  			ret = -ENOMEM;
  			goto out_free;
  		}
  		if (copy_from_user(kbufs[n], base, len)) {
  			ret = -EFAULT;
  			vfree(kbufs[n]);
  			goto out_free;
  		}
  	}
1cf58fa84   Jiro SEKIBA   nilfs2: shorten f...
624
  	/*
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
625
  	 * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(),
1cf58fa84   Jiro SEKIBA   nilfs2: shorten f...
626
627
628
629
630
631
632
633
  	 * which will operates an inode list without blocking.
  	 * To protect the list from concurrent operations,
  	 * nilfs_ioctl_move_blocks should be atomic operation.
  	 */
  	if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) {
  		ret = -EBUSY;
  		goto out_free;
  	}
5beb6e0b2   Ryusuke Konishi   nilfs2: add bdev ...
634
  	vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
635
  	ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
1cf58fa84   Jiro SEKIBA   nilfs2: shorten f...
636
637
638
639
640
641
  	if (ret < 0)
  		printk(KERN_ERR "NILFS: GC failed during preparation: "
  			"cannot read source blocks: err=%d
  ", ret);
  	else
  		ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
642
  	nilfs_remove_all_gcinodes(nilfs);
1cf58fa84   Jiro SEKIBA   nilfs2: shorten f...
643
  	clear_nilfs_gc_running(nilfs);
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
644

7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
645
  out_free:
d50468536   Ryusuke Konishi   nilfs2: fix memor...
646
  	while (--n >= 0)
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
647
648
  		vfree(kbufs[n]);
  	kfree(kbufs[4]);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
649
  out:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
650
  	mnt_drop_write_file(filp);
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
651
  	return ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
652
653
654
655
656
657
658
  }
  
  static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
  			    unsigned int cmd, void __user *argp)
  {
  	__u64 cno;
  	int ret;
0d561f12b   Jiro SEKIBA   nilfs2: add reade...
659
  	struct the_nilfs *nilfs;
7942b919f   Koji Sato   nilfs2: ioctl ope...
660
661
662
663
664
665
  
  	ret = nilfs_construct_segment(inode->i_sb);
  	if (ret < 0)
  		return ret;
  
  	if (argp != NULL) {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
666
  		nilfs = inode->i_sb->s_fs_info;
0d561f12b   Jiro SEKIBA   nilfs2: add reade...
667
668
669
  		down_read(&nilfs->ns_segctor_sem);
  		cno = nilfs->ns_cno - 1;
  		up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
670
671
672
673
674
  		if (copy_to_user(argp, &cno, sizeof(cno)))
  			return -EFAULT;
  	}
  	return 0;
  }
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
675
676
677
678
679
680
681
682
  static int nilfs_ioctl_resize(struct inode *inode, struct file *filp,
  			      void __user *argp)
  {
  	__u64 newsize;
  	int ret = -EPERM;
  
  	if (!capable(CAP_SYS_ADMIN))
  		goto out;
a561be710   Al Viro   switch a bunch of...
683
  	ret = mnt_want_write_file(filp);
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
684
685
686
687
688
689
690
691
692
693
  	if (ret)
  		goto out;
  
  	ret = -EFAULT;
  	if (copy_from_user(&newsize, argp, sizeof(newsize)))
  		goto out_drop_write;
  
  	ret = nilfs_resize_fs(inode->i_sb, newsize);
  
  out_drop_write:
2a79f17e4   Al Viro   vfs: mnt_drop_wri...
694
  	mnt_drop_write_file(filp);
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
695
696
697
  out:
  	return ret;
  }
619205da5   Ryusuke Konishi   nilfs2: add ioctl...
698
699
700
701
702
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
  static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
  {
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
  	__u64 range[2];
  	__u64 minseg, maxseg;
  	unsigned long segbytes;
  	int ret = -EPERM;
  
  	if (!capable(CAP_SYS_ADMIN))
  		goto out;
  
  	ret = -EFAULT;
  	if (copy_from_user(range, argp, sizeof(__u64[2])))
  		goto out;
  
  	ret = -ERANGE;
  	if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode))
  		goto out;
  
  	segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize;
  
  	minseg = range[0] + segbytes - 1;
  	do_div(minseg, segbytes);
  	maxseg = NILFS_SB2_OFFSET_BYTES(range[1]);
  	do_div(maxseg, segbytes);
  	maxseg--;
  
  	ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg);
  out:
  	return ret;
  }
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
729
730
  static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
  				unsigned int cmd, void __user *argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
731
  				size_t membsz,
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
732
733
734
735
736
  				ssize_t (*dofunc)(struct the_nilfs *,
  						  __u64 *, int,
  						  void *, size_t, size_t))
  
  {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
737
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
738
739
740
741
742
  	struct nilfs_argv argv;
  	int ret;
  
  	if (copy_from_user(&argv, argp, sizeof(argv)))
  		return -EFAULT;
003ff182f   Ryusuke Konishi   nilfs2: allow fut...
743
  	if (argv.v_size < membsz)
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
744
  		return -EINVAL;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
745
746
747
748
749
750
751
752
  	ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
  	if (ret < 0)
  		return ret;
  
  	if (copy_to_user(argp, &argv, sizeof(argv)))
  		ret = -EFAULT;
  	return ret;
  }
7a9461939   Ryusuke Konishi   nilfs2: use unloc...
753
  long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
7942b919f   Koji Sato   nilfs2: ioctl ope...
754
  {
7a9461939   Ryusuke Konishi   nilfs2: use unloc...
755
  	struct inode *inode = filp->f_dentry->d_inode;
753234007   Li Hong   nilfs2: fix a wro...
756
  	void __user *argp = (void __user *)arg;
7942b919f   Koji Sato   nilfs2: ioctl ope...
757
758
  
  	switch (cmd) {
cde98f0f8   Ryusuke Konishi   nilfs2: implement...
759
760
761
762
763
764
  	case FS_IOC_GETFLAGS:
  		return nilfs_ioctl_getflags(inode, argp);
  	case FS_IOC_SETFLAGS:
  		return nilfs_ioctl_setflags(inode, filp, argp);
  	case FS_IOC_GETVERSION:
  		return nilfs_ioctl_getversion(inode, argp);
7942b919f   Koji Sato   nilfs2: ioctl ope...
765
766
767
768
769
  	case NILFS_IOCTL_CHANGE_CPMODE:
  		return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
  	case NILFS_IOCTL_DELETE_CHECKPOINT:
  		return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
  	case NILFS_IOCTL_GET_CPINFO:
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
770
  		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
771
  					    sizeof(struct nilfs_cpinfo),
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
772
  					    nilfs_ioctl_do_get_cpinfo);
7942b919f   Koji Sato   nilfs2: ioctl ope...
773
774
775
  	case NILFS_IOCTL_GET_CPSTAT:
  		return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
  	case NILFS_IOCTL_GET_SUINFO:
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
776
  		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
777
  					    sizeof(struct nilfs_suinfo),
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
778
  					    nilfs_ioctl_do_get_suinfo);
7942b919f   Koji Sato   nilfs2: ioctl ope...
779
780
781
  	case NILFS_IOCTL_GET_SUSTAT:
  		return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
  	case NILFS_IOCTL_GET_VINFO:
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
782
  		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
783
  					    sizeof(struct nilfs_vinfo),
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
784
  					    nilfs_ioctl_do_get_vinfo);
7942b919f   Koji Sato   nilfs2: ioctl ope...
785
786
787
788
  	case NILFS_IOCTL_GET_BDESCS:
  		return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
  	case NILFS_IOCTL_CLEAN_SEGMENTS:
  		return nilfs_ioctl_clean_segments(inode, filp, cmd, argp);
7942b919f   Koji Sato   nilfs2: ioctl ope...
789
790
  	case NILFS_IOCTL_SYNC:
  		return nilfs_ioctl_sync(inode, filp, cmd, argp);
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
791
792
  	case NILFS_IOCTL_RESIZE:
  		return nilfs_ioctl_resize(inode, filp, argp);
619205da5   Ryusuke Konishi   nilfs2: add ioctl...
793
794
  	case NILFS_IOCTL_SET_ALLOC_RANGE:
  		return nilfs_ioctl_set_alloc_range(inode, argp);
7942b919f   Koji Sato   nilfs2: ioctl ope...
795
796
797
798
  	default:
  		return -ENOTTY;
  	}
  }
828b1c50a   Ryusuke Konishi   nilfs2: add compa...
799
800
801
802
803
804
805
806
807
808
809
810
811
812
  
  #ifdef CONFIG_COMPAT
  long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
  {
  	switch (cmd) {
  	case FS_IOC32_GETFLAGS:
  		cmd = FS_IOC_GETFLAGS;
  		break;
  	case FS_IOC32_SETFLAGS:
  		cmd = FS_IOC_SETFLAGS;
  		break;
  	case FS_IOC32_GETVERSION:
  		cmd = FS_IOC_GETVERSION;
  		break;
695c60f21   Thomas Meyer   nilfs2: unbreak c...
813
814
815
816
817
818
819
820
821
822
823
824
825
  	case NILFS_IOCTL_CHANGE_CPMODE:
  	case NILFS_IOCTL_DELETE_CHECKPOINT:
  	case NILFS_IOCTL_GET_CPINFO:
  	case NILFS_IOCTL_GET_CPSTAT:
  	case NILFS_IOCTL_GET_SUINFO:
  	case NILFS_IOCTL_GET_SUSTAT:
  	case NILFS_IOCTL_GET_VINFO:
  	case NILFS_IOCTL_GET_BDESCS:
  	case NILFS_IOCTL_CLEAN_SEGMENTS:
  	case NILFS_IOCTL_SYNC:
  	case NILFS_IOCTL_RESIZE:
  	case NILFS_IOCTL_SET_ALLOC_RANGE:
  		break;
828b1c50a   Ryusuke Konishi   nilfs2: add compa...
826
827
828
829
830
831
  	default:
  		return -ENOIOCTLCMD;
  	}
  	return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
  }
  #endif