Blame view

fs/nilfs2/ioctl.c 20.7 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() */
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
30
  #include <linux/mount.h>	/* mnt_want_write(), mnt_drop_write() */
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
115
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
150
151
152
153
154
155
156
157
158
  		return -EACCES;
  
  	if (get_user(flags, (int __user *)argp))
  		return -EFAULT;
  
  	ret = mnt_want_write(filp->f_path.mnt);
  	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);
  	mnt_drop_write(filp->f_path.mnt);
  	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...
159
160
161
  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...
162
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
163
164
165
166
167
168
  	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...
169
170
171
172
173
174
  
  	ret = mnt_want_write(filp->f_path.mnt);
  	if (ret)
  		return ret;
  
  	ret = -EFAULT;
7942b919f   Koji Sato   nilfs2: ioctl ope...
175
  	if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
176
  		goto out;
7942b919f   Koji Sato   nilfs2: ioctl ope...
177

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

7942b919f   Koji Sato   nilfs2: ioctl ope...
180
181
  	nilfs_transaction_begin(inode->i_sb, &ti, 0);
  	ret = nilfs_cpfile_change_cpmode(
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
182
  		nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
183
  	if (unlikely(ret < 0))
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
184
  		nilfs_transaction_abort(inode->i_sb);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
185
186
  	else
  		nilfs_transaction_commit(inode->i_sb); /* never fails */
348fe8da1   Ryusuke Konishi   nilfs2: simplify ...
187
  	up_read(&inode->i_sb->s_umount);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
188
189
  out:
  	mnt_drop_write(filp->f_path.mnt);
7942b919f   Koji Sato   nilfs2: ioctl ope...
190
191
192
193
194
195
196
  	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...
197
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
198
199
200
201
202
203
  	struct nilfs_transaction_info ti;
  	__u64 cno;
  	int ret;
  
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
204
205
206
207
208
209
  
  	ret = mnt_want_write(filp->f_path.mnt);
  	if (ret)
  		return ret;
  
  	ret = -EFAULT;
7942b919f   Koji Sato   nilfs2: ioctl ope...
210
  	if (copy_from_user(&cno, argp, sizeof(cno)))
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
211
  		goto out;
7942b919f   Koji Sato   nilfs2: ioctl ope...
212
213
  
  	nilfs_transaction_begin(inode->i_sb, &ti, 0);
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
214
  	ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
215
  	if (unlikely(ret < 0))
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
216
  		nilfs_transaction_abort(inode->i_sb);
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
217
218
219
220
  	else
  		nilfs_transaction_commit(inode->i_sb); /* never fails */
  out:
  	mnt_drop_write(filp->f_path.mnt);
7942b919f   Koji Sato   nilfs2: ioctl ope...
221
222
223
224
  	return ret;
  }
  
  static ssize_t
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
225
  nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
226
227
  			  void *buf, size_t size, size_t nmembs)
  {
7942b919f   Koji Sato   nilfs2: ioctl ope...
228
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
229
  	down_read(&nilfs->ns_segctor_sem);
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
230
  	ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
003ff182f   Ryusuke Konishi   nilfs2: allow fut...
231
  				      size, nmembs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
232
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
233
234
235
236
237
238
  	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...
239
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
240
  	struct nilfs_cpstat cpstat;
7942b919f   Koji Sato   nilfs2: ioctl ope...
241
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
242
243
244
  	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...
245
246
247
248
249
250
251
252
253
  	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...
254
  nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
255
256
  			  void *buf, size_t size, size_t nmembs)
  {
7942b919f   Koji Sato   nilfs2: ioctl ope...
257
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
258
  	down_read(&nilfs->ns_segctor_sem);
003ff182f   Ryusuke Konishi   nilfs2: allow fut...
259
260
  	ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
  				      nmembs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
261
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
262
263
264
265
266
267
  	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...
268
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
269
  	struct nilfs_sustat sustat;
7942b919f   Koji Sato   nilfs2: ioctl ope...
270
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
271
272
273
  	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...
274
275
276
277
278
279
280
281
282
  	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...
283
  nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
284
285
  			 void *buf, size_t size, size_t nmembs)
  {
7942b919f   Koji Sato   nilfs2: ioctl ope...
286
  	int ret;
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
287
  	down_read(&nilfs->ns_segctor_sem);
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
288
  	ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
289
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
290
291
292
293
  	return ret;
  }
  
  static ssize_t
b028fcfc4   Ryusuke Konishi   nilfs2: fix gc fa...
294
  nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
7942b919f   Koji Sato   nilfs2: ioctl ope...
295
296
  			  void *buf, size_t size, size_t nmembs)
  {
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
297
  	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
7942b919f   Koji Sato   nilfs2: ioctl ope...
298
299
  	struct nilfs_bdesc *bdescs = buf;
  	int ret, i;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
300
  	down_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
301
302
303
304
305
306
  	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...
307
308
  			if (ret != -ENOENT) {
  				up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
309
  				return ret;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
310
  			}
7942b919f   Koji Sato   nilfs2: ioctl ope...
311
312
313
  			bdescs[i].bd_blocknr = 0;
  		}
  	}
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
314
  	up_read(&nilfs->ns_segctor_sem);
7942b919f   Koji Sato   nilfs2: ioctl ope...
315
316
317
318
319
320
  	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...
321
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
322
  	struct nilfs_argv argv;
7942b919f   Koji Sato   nilfs2: ioctl ope...
323
324
325
326
  	int ret;
  
  	if (copy_from_user(&argv, argp, sizeof(argv)))
  		return -EFAULT;
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
327
328
  	if (argv.v_size != sizeof(struct nilfs_bdesc))
  		return -EINVAL;
7942b919f   Koji Sato   nilfs2: ioctl ope...
329
330
  	ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
  				    nilfs_ioctl_do_get_bdescs);
47420c799   Ryusuke Konishi   nilfs2: avoid dou...
331
332
  	if (ret < 0)
  		return ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
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
368
  
  	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...
369
370
371
372
373
374
375
376
377
378
379
380
381
  	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...
382
383
384
  	list_add_tail(&bh->b_assoc_buffers, buffers);
  	return 0;
  }
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
385
  static int nilfs_ioctl_move_blocks(struct super_block *sb,
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
386
  				   struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
387
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
388
  	size_t nmembs = argv->v_nmembs;
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
389
  	struct the_nilfs *nilfs = sb->s_fs_info;
7942b919f   Koji Sato   nilfs2: ioctl ope...
390
391
392
393
394
395
396
397
398
399
400
  	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...
401
  		inode = nilfs_iget_for_gc(sb, ino, cno);
103cfcf52   Dan Carpenter   nilfs2: nilfs_ige...
402
403
  		if (IS_ERR(inode)) {
  			ret = PTR_ERR(inode);
7942b919f   Koji Sato   nilfs2: ioctl ope...
404
405
  			goto failed;
  		}
947b10ae0   Ryusuke Konishi   nilfs2: fix regre...
406
407
408
409
410
411
412
413
414
415
  		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...
416
417
418
  		do {
  			ret = nilfs_ioctl_move_inode_block(inode, vdesc,
  							   &buffers);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
419
420
  			if (unlikely(ret < 0)) {
  				iput(inode);
7942b919f   Koji Sato   nilfs2: ioctl ope...
421
  				goto failed;
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
422
  			}
7942b919f   Koji Sato   nilfs2: ioctl ope...
423
424
425
  			vdesc++;
  		} while (++i < nmembs &&
  			 vdesc->vd_ino == ino && vdesc->vd_cno == cno);
263d90cef   Ryusuke Konishi   nilfs2: remove ow...
426
427
  
  		iput(inode); /* The inode still remains in GC inode list */
7942b919f   Koji Sato   nilfs2: ioctl ope...
428
429
430
431
432
  	}
  
  	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...
433
  			WARN_ON(ret == -EEXIST);
7942b919f   Koji Sato   nilfs2: ioctl ope...
434
435
436
  			goto failed;
  		}
  		list_del_init(&bh->b_assoc_buffers);
7942b919f   Koji Sato   nilfs2: ioctl ope...
437
438
439
440
441
442
443
  		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...
444
445
446
447
  		brelse(bh);
  	}
  	return ret;
  }
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
448
449
  static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
  					  struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
450
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
451
  	size_t nmembs = argv->v_nmembs;
7942b919f   Koji Sato   nilfs2: ioctl ope...
452
453
454
455
456
457
458
459
460
461
462
463
  	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 ...
464
465
  static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
  				      struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
466
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
467
468
  	size_t nmembs = argv->v_nmembs;
  	int ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
469

365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
470
  	ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs);
7942b919f   Koji Sato   nilfs2: ioctl ope...
471
472
473
  
  	return (ret < 0) ? ret : nmembs;
  }
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
474
475
  static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
  					 struct nilfs_argv *argv, void *buf)
7942b919f   Koji Sato   nilfs2: ioctl ope...
476
  {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
477
  	size_t nmembs = argv->v_nmembs;
365e215ce   Ryusuke Konishi   nilfs2: unfold ni...
478
  	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
7942b919f   Koji Sato   nilfs2: ioctl ope...
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
  	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...
497
  			ret = nilfs_mdt_mark_block_dirty(nilfs->ns_dat,
7942b919f   Koji Sato   nilfs2: ioctl ope...
498
499
  							 bdescs[i].bd_offset);
  			if (ret < 0) {
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
500
  				WARN_ON(ret == -ENOENT);
7942b919f   Koji Sato   nilfs2: ioctl ope...
501
502
503
504
505
506
  				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...
507
  				WARN_ON(ret == -ENOENT);
7942b919f   Koji Sato   nilfs2: ioctl ope...
508
509
510
511
512
513
  				return ret;
  			}
  		}
  	}
  	return nmembs;
  }
7942b919f   Koji Sato   nilfs2: ioctl ope...
514
  int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
515
  				       struct nilfs_argv *argv, void **kbufs)
7942b919f   Koji Sato   nilfs2: ioctl ope...
516
  {
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
517
  	const char *msg;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
518
  	int ret;
7942b919f   Koji Sato   nilfs2: ioctl ope...
519

4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
520
  	ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
521
522
523
524
525
526
527
528
  	if (ret < 0) {
  		/*
  		 * can safely abort because checkpoints can be removed
  		 * independently.
  		 */
  		msg = "cannot delete checkpoints";
  		goto failed;
  	}
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
529
  	ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
530
531
532
533
534
535
536
537
  	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 ...
538
  	ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
539
540
541
542
543
544
545
  	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...
546
  	return 0;
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
547
   failed:
1f5abe7e7   Ryusuke Konishi   nilfs2: replace B...
548
549
550
  	printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d
  ",
  	       msg, ret);
7942b919f   Koji Sato   nilfs2: ioctl ope...
551
552
553
554
555
556
  	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 ...
557
  	struct nilfs_argv argv[5];
33e189bd5   Tobias Klauser   nilfs2: Storage c...
558
  	static const size_t argsz[5] = {
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
559
560
561
562
563
564
565
566
567
568
569
  		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...
570
571
  	if (!capable(CAP_SYS_ADMIN))
  		return -EPERM;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
572

7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
573
574
575
576
577
  	ret = mnt_want_write(filp->f_path.mnt);
  	if (ret)
  		return ret;
  
  	ret = -EFAULT;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
578
  	if (copy_from_user(argv, argp, sizeof(argv)))
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
579
  		goto out;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
580

7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
581
  	ret = -EINVAL;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
582
583
  	nsegs = argv[4].v_nmembs;
  	if (argv[4].v_size != argsz[4])
7512487e6   Ryusuke Konishi   nilfs2: use mnt_w...
584
  		goto out;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
585
586
587
588
589
590
591
  	/*
  	 * 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...
592
593
594
595
  	if (IS_ERR(kbufs[4])) {
  		ret = PTR_ERR(kbufs[4]);
  		goto out;
  	}
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
596
  	nilfs = inode->i_sb->s_fs_info;
4f6b82883   Ryusuke Konishi   nilfs2: fix lock ...
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
  
  	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;
  
  		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
650
  out:
  	mnt_drop_write(filp->f_path.mnt);
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
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
  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;
  
  	ret = mnt_want_write(filp->f_path.mnt);
  	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:
  	mnt_drop_write(filp->f_path.mnt);
  out:
  	return ret;
  }
619205da5   Ryusuke Konishi   nilfs2: add ioctl...
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
729
  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...
730
731
  static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
  				unsigned int cmd, void __user *argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
732
  				size_t membsz,
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
733
734
735
736
737
  				ssize_t (*dofunc)(struct the_nilfs *,
  						  __u64 *, int,
  						  void *, size_t, size_t))
  
  {
e3154e974   Ryusuke Konishi   nilfs2: get rid o...
738
  	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
739
740
741
742
743
  	struct nilfs_argv argv;
  	int ret;
  
  	if (copy_from_user(&argv, argp, sizeof(argv)))
  		return -EFAULT;
003ff182f   Ryusuke Konishi   nilfs2: allow fut...
744
  	if (argv.v_size < membsz)
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
745
  		return -EINVAL;
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
746
747
748
749
750
751
752
753
  	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...
754
  long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
7942b919f   Koji Sato   nilfs2: ioctl ope...
755
  {
7a9461939   Ryusuke Konishi   nilfs2: use unloc...
756
  	struct inode *inode = filp->f_dentry->d_inode;
753234007   Li Hong   nilfs2: fix a wro...
757
  	void __user *argp = (void __user *)arg;
7942b919f   Koji Sato   nilfs2: ioctl ope...
758
759
  
  	switch (cmd) {
cde98f0f8   Ryusuke Konishi   nilfs2: implement...
760
761
762
763
764
765
  	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...
766
767
768
769
770
  	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...
771
  		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
772
  					    sizeof(struct nilfs_cpinfo),
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
773
  					    nilfs_ioctl_do_get_cpinfo);
7942b919f   Koji Sato   nilfs2: ioctl ope...
774
775
776
  	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...
777
  		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
778
  					    sizeof(struct nilfs_suinfo),
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
779
  					    nilfs_ioctl_do_get_suinfo);
7942b919f   Koji Sato   nilfs2: ioctl ope...
780
781
782
  	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...
783
  		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
83aca8f48   Ryusuke Konishi   nilfs2: check siz...
784
  					    sizeof(struct nilfs_vinfo),
47eb6b9c8   Ryusuke Konishi   nilfs2: fix possi...
785
  					    nilfs_ioctl_do_get_vinfo);
7942b919f   Koji Sato   nilfs2: ioctl ope...
786
787
788
789
  	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...
790
791
  	case NILFS_IOCTL_SYNC:
  		return nilfs_ioctl_sync(inode, filp, cmd, argp);
4e33f9eab   Ryusuke Konishi   nilfs2: implement...
792
793
  	case NILFS_IOCTL_RESIZE:
  		return nilfs_ioctl_resize(inode, filp, argp);
619205da5   Ryusuke Konishi   nilfs2: add ioctl...
794
795
  	case NILFS_IOCTL_SET_ALLOC_RANGE:
  		return nilfs_ioctl_set_alloc_range(inode, argp);
7942b919f   Koji Sato   nilfs2: ioctl ope...
796
797
798
799
  	default:
  		return -ENOTTY;
  	}
  }
828b1c50a   Ryusuke Konishi   nilfs2: add compa...
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
  
  #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;
  	default:
  		return -ENOIOCTLCMD;
  	}
  	return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
  }
  #endif