xref: /kernel/linux/linux-5.10/fs/nilfs2/ioctl.c (revision 8c2ecf20)
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * ioctl.c - NILFS ioctl operations.
4 *
5 * Copyright (C) 2007, 2008 Nippon Telegraph and Telephone Corporation.
6 *
7 * Written by Koji Sato.
8 */
9
10#include <linux/fs.h>
11#include <linux/wait.h>
12#include <linux/slab.h>
13#include <linux/capability.h>	/* capable() */
14#include <linux/uaccess.h>	/* copy_from_user(), copy_to_user() */
15#include <linux/vmalloc.h>
16#include <linux/compat.h>	/* compat_ptr() */
17#include <linux/mount.h>	/* mnt_want_write_file(), mnt_drop_write_file() */
18#include <linux/buffer_head.h>
19#include "nilfs.h"
20#include "segment.h"
21#include "bmap.h"
22#include "cpfile.h"
23#include "sufile.h"
24#include "dat.h"
25
26/**
27 * nilfs_ioctl_wrap_copy - wrapping function of get/set metadata info
28 * @nilfs: nilfs object
29 * @argv: vector of arguments from userspace
30 * @dir: set of direction flags
31 * @dofunc: concrete function of get/set metadata info
32 *
33 * Description: nilfs_ioctl_wrap_copy() gets/sets metadata info by means of
34 * calling dofunc() function on the basis of @argv argument.
35 *
36 * Return Value: On success, 0 is returned and requested metadata info
37 * is copied into userspace. On error, one of the following
38 * negative error codes is returned.
39 *
40 * %-EINVAL - Invalid arguments from userspace.
41 *
42 * %-ENOMEM - Insufficient amount of memory available.
43 *
44 * %-EFAULT - Failure during execution of requested operation.
45 */
46static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
47				 struct nilfs_argv *argv, int dir,
48				 ssize_t (*dofunc)(struct the_nilfs *,
49						   __u64 *, int,
50						   void *, size_t, size_t))
51{
52	void *buf;
53	void __user *base = (void __user *)(unsigned long)argv->v_base;
54	size_t maxmembs, total, n;
55	ssize_t nr;
56	int ret, i;
57	__u64 pos, ppos;
58
59	if (argv->v_nmembs == 0)
60		return 0;
61
62	if (argv->v_size > PAGE_SIZE)
63		return -EINVAL;
64
65	/*
66	 * Reject pairs of a start item position (argv->v_index) and a
67	 * total count (argv->v_nmembs) which leads position 'pos' to
68	 * overflow by the increment at the end of the loop.
69	 */
70	if (argv->v_index > ~(__u64)0 - argv->v_nmembs)
71		return -EINVAL;
72
73	buf = (void *)get_zeroed_page(GFP_NOFS);
74	if (unlikely(!buf))
75		return -ENOMEM;
76	maxmembs = PAGE_SIZE / argv->v_size;
77
78	ret = 0;
79	total = 0;
80	pos = argv->v_index;
81	for (i = 0; i < argv->v_nmembs; i += n) {
82		n = (argv->v_nmembs - i < maxmembs) ?
83			argv->v_nmembs - i : maxmembs;
84		if ((dir & _IOC_WRITE) &&
85		    copy_from_user(buf, base + argv->v_size * i,
86				   argv->v_size * n)) {
87			ret = -EFAULT;
88			break;
89		}
90		ppos = pos;
91		nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size,
92			       n);
93		if (nr < 0) {
94			ret = nr;
95			break;
96		}
97		if ((dir & _IOC_READ) &&
98		    copy_to_user(base + argv->v_size * i, buf,
99				 argv->v_size * nr)) {
100			ret = -EFAULT;
101			break;
102		}
103		total += nr;
104		if ((size_t)nr < n)
105			break;
106		if (pos == ppos)
107			pos += n;
108	}
109	argv->v_nmembs = total;
110
111	free_pages((unsigned long)buf, 0);
112	return ret;
113}
114
115/**
116 * nilfs_ioctl_getflags - ioctl to support lsattr
117 */
118static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
119{
120	unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
121
122	return put_user(flags, (int __user *)argp);
123}
124
125/**
126 * nilfs_ioctl_setflags - ioctl to support chattr
127 */
128static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
129				void __user *argp)
130{
131	struct nilfs_transaction_info ti;
132	unsigned int flags, oldflags;
133	int ret;
134
135	if (!inode_owner_or_capable(inode))
136		return -EACCES;
137
138	if (get_user(flags, (int __user *)argp))
139		return -EFAULT;
140
141	ret = mnt_want_write_file(filp);
142	if (ret)
143		return ret;
144
145	flags = nilfs_mask_flags(inode->i_mode, flags);
146
147	inode_lock(inode);
148
149	oldflags = NILFS_I(inode)->i_flags;
150
151	ret = vfs_ioc_setflags_prepare(inode, oldflags, flags);
152	if (ret)
153		goto out;
154
155	ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
156	if (ret)
157		goto out;
158
159	NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
160		(flags & FS_FL_USER_MODIFIABLE);
161
162	nilfs_set_inode_flags(inode);
163	inode->i_ctime = current_time(inode);
164	if (IS_SYNC(inode))
165		nilfs_set_transaction_flag(NILFS_TI_SYNC);
166
167	nilfs_mark_inode_dirty(inode);
168	ret = nilfs_transaction_commit(inode->i_sb);
169out:
170	inode_unlock(inode);
171	mnt_drop_write_file(filp);
172	return ret;
173}
174
175/**
176 * nilfs_ioctl_getversion - get info about a file's version (generation number)
177 */
178static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
179{
180	return put_user(inode->i_generation, (int __user *)argp);
181}
182
183/**
184 * nilfs_ioctl_change_cpmode - change checkpoint mode (checkpoint/snapshot)
185 * @inode: inode object
186 * @filp: file object
187 * @cmd: ioctl's request code
188 * @argp: pointer on argument from userspace
189 *
190 * Description: nilfs_ioctl_change_cpmode() function changes mode of
191 * given checkpoint between checkpoint and snapshot state. This ioctl
192 * is used in chcp and mkcp utilities.
193 *
194 * Return Value: On success, 0 is returned and mode of a checkpoint is
195 * changed. On error, one of the following negative error codes
196 * is returned.
197 *
198 * %-EPERM - Operation not permitted.
199 *
200 * %-EFAULT - Failure during checkpoint mode changing.
201 */
202static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
203				     unsigned int cmd, void __user *argp)
204{
205	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
206	struct nilfs_transaction_info ti;
207	struct nilfs_cpmode cpmode;
208	int ret;
209
210	if (!capable(CAP_SYS_ADMIN))
211		return -EPERM;
212
213	ret = mnt_want_write_file(filp);
214	if (ret)
215		return ret;
216
217	ret = -EFAULT;
218	if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
219		goto out;
220
221	mutex_lock(&nilfs->ns_snapshot_mount_mutex);
222
223	nilfs_transaction_begin(inode->i_sb, &ti, 0);
224	ret = nilfs_cpfile_change_cpmode(
225		nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
226	if (unlikely(ret < 0))
227		nilfs_transaction_abort(inode->i_sb);
228	else
229		nilfs_transaction_commit(inode->i_sb); /* never fails */
230
231	mutex_unlock(&nilfs->ns_snapshot_mount_mutex);
232out:
233	mnt_drop_write_file(filp);
234	return ret;
235}
236
237/**
238 * nilfs_ioctl_delete_checkpoint - remove checkpoint
239 * @inode: inode object
240 * @filp: file object
241 * @cmd: ioctl's request code
242 * @argp: pointer on argument from userspace
243 *
244 * Description: nilfs_ioctl_delete_checkpoint() function removes
245 * checkpoint from NILFS2 file system. This ioctl is used in rmcp
246 * utility.
247 *
248 * Return Value: On success, 0 is returned and a checkpoint is
249 * removed. On error, one of the following negative error codes
250 * is returned.
251 *
252 * %-EPERM - Operation not permitted.
253 *
254 * %-EFAULT - Failure during checkpoint removing.
255 */
256static int
257nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
258			      unsigned int cmd, void __user *argp)
259{
260	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
261	struct nilfs_transaction_info ti;
262	__u64 cno;
263	int ret;
264
265	if (!capable(CAP_SYS_ADMIN))
266		return -EPERM;
267
268	ret = mnt_want_write_file(filp);
269	if (ret)
270		return ret;
271
272	ret = -EFAULT;
273	if (copy_from_user(&cno, argp, sizeof(cno)))
274		goto out;
275
276	nilfs_transaction_begin(inode->i_sb, &ti, 0);
277	ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
278	if (unlikely(ret < 0))
279		nilfs_transaction_abort(inode->i_sb);
280	else
281		nilfs_transaction_commit(inode->i_sb); /* never fails */
282out:
283	mnt_drop_write_file(filp);
284	return ret;
285}
286
287/**
288 * nilfs_ioctl_do_get_cpinfo - callback method getting info about checkpoints
289 * @nilfs: nilfs object
290 * @posp: pointer on array of checkpoint's numbers
291 * @flags: checkpoint mode (checkpoint or snapshot)
292 * @buf: buffer for storing checkponts' info
293 * @size: size in bytes of one checkpoint info item in array
294 * @nmembs: number of checkpoints in array (numbers and infos)
295 *
296 * Description: nilfs_ioctl_do_get_cpinfo() function returns info about
297 * requested checkpoints. The NILFS_IOCTL_GET_CPINFO ioctl is used in
298 * lscp utility and by nilfs_cleanerd daemon.
299 *
300 * Return value: count of nilfs_cpinfo structures in output buffer.
301 */
302static ssize_t
303nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
304			  void *buf, size_t size, size_t nmembs)
305{
306	int ret;
307
308	down_read(&nilfs->ns_segctor_sem);
309	ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
310				      size, nmembs);
311	up_read(&nilfs->ns_segctor_sem);
312	return ret;
313}
314
315/**
316 * nilfs_ioctl_get_cpstat - get checkpoints statistics
317 * @inode: inode object
318 * @filp: file object
319 * @cmd: ioctl's request code
320 * @argp: pointer on argument from userspace
321 *
322 * Description: nilfs_ioctl_get_cpstat() returns information about checkpoints.
323 * The NILFS_IOCTL_GET_CPSTAT ioctl is used by lscp, rmcp utilities
324 * and by nilfs_cleanerd daemon.
325 *
326 * Return Value: On success, 0 is returned, and checkpoints information is
327 * copied into userspace pointer @argp. On error, one of the following
328 * negative error codes is returned.
329 *
330 * %-EIO - I/O error.
331 *
332 * %-ENOMEM - Insufficient amount of memory available.
333 *
334 * %-EFAULT - Failure during getting checkpoints statistics.
335 */
336static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
337				  unsigned int cmd, void __user *argp)
338{
339	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
340	struct nilfs_cpstat cpstat;
341	int ret;
342
343	down_read(&nilfs->ns_segctor_sem);
344	ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
345	up_read(&nilfs->ns_segctor_sem);
346	if (ret < 0)
347		return ret;
348
349	if (copy_to_user(argp, &cpstat, sizeof(cpstat)))
350		ret = -EFAULT;
351	return ret;
352}
353
354/**
355 * nilfs_ioctl_do_get_suinfo - callback method getting segment usage info
356 * @nilfs: nilfs object
357 * @posp: pointer on array of segment numbers
358 * @flags: *not used*
359 * @buf: buffer for storing suinfo array
360 * @size: size in bytes of one suinfo item in array
361 * @nmembs: count of segment numbers and suinfos in array
362 *
363 * Description: nilfs_ioctl_do_get_suinfo() function returns segment usage
364 * info about requested segments. The NILFS_IOCTL_GET_SUINFO ioctl is used
365 * in lssu, nilfs_resize utilities and by nilfs_cleanerd daemon.
366 *
367 * Return value: count of nilfs_suinfo structures in output buffer.
368 */
369static ssize_t
370nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
371			  void *buf, size_t size, size_t nmembs)
372{
373	int ret;
374
375	down_read(&nilfs->ns_segctor_sem);
376	ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
377				      nmembs);
378	up_read(&nilfs->ns_segctor_sem);
379	return ret;
380}
381
382/**
383 * nilfs_ioctl_get_sustat - get segment usage statistics
384 * @inode: inode object
385 * @filp: file object
386 * @cmd: ioctl's request code
387 * @argp: pointer on argument from userspace
388 *
389 * Description: nilfs_ioctl_get_sustat() returns segment usage statistics.
390 * The NILFS_IOCTL_GET_SUSTAT ioctl is used in lssu, nilfs_resize utilities
391 * and by nilfs_cleanerd daemon.
392 *
393 * Return Value: On success, 0 is returned, and segment usage information is
394 * copied into userspace pointer @argp. On error, one of the following
395 * negative error codes is returned.
396 *
397 * %-EIO - I/O error.
398 *
399 * %-ENOMEM - Insufficient amount of memory available.
400 *
401 * %-EFAULT - Failure during getting segment usage statistics.
402 */
403static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
404				  unsigned int cmd, void __user *argp)
405{
406	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
407	struct nilfs_sustat sustat;
408	int ret;
409
410	down_read(&nilfs->ns_segctor_sem);
411	ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
412	up_read(&nilfs->ns_segctor_sem);
413	if (ret < 0)
414		return ret;
415
416	if (copy_to_user(argp, &sustat, sizeof(sustat)))
417		ret = -EFAULT;
418	return ret;
419}
420
421/**
422 * nilfs_ioctl_do_get_vinfo - callback method getting virtual blocks info
423 * @nilfs: nilfs object
424 * @posp: *not used*
425 * @flags: *not used*
426 * @buf: buffer for storing array of nilfs_vinfo structures
427 * @size: size in bytes of one vinfo item in array
428 * @nmembs: count of vinfos in array
429 *
430 * Description: nilfs_ioctl_do_get_vinfo() function returns information
431 * on virtual block addresses. The NILFS_IOCTL_GET_VINFO ioctl is used
432 * by nilfs_cleanerd daemon.
433 *
434 * Return value: count of nilfs_vinfo structures in output buffer.
435 */
436static ssize_t
437nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
438			 void *buf, size_t size, size_t nmembs)
439{
440	int ret;
441
442	down_read(&nilfs->ns_segctor_sem);
443	ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs);
444	up_read(&nilfs->ns_segctor_sem);
445	return ret;
446}
447
448/**
449 * nilfs_ioctl_do_get_bdescs - callback method getting disk block descriptors
450 * @nilfs: nilfs object
451 * @posp: *not used*
452 * @flags: *not used*
453 * @buf: buffer for storing array of nilfs_bdesc structures
454 * @size: size in bytes of one bdesc item in array
455 * @nmembs: count of bdescs in array
456 *
457 * Description: nilfs_ioctl_do_get_bdescs() function returns information
458 * about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl
459 * is used by nilfs_cleanerd daemon.
460 *
461 * Return value: count of nilfs_bdescs structures in output buffer.
462 */
463static ssize_t
464nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
465			  void *buf, size_t size, size_t nmembs)
466{
467	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
468	struct nilfs_bdesc *bdescs = buf;
469	int ret, i;
470
471	down_read(&nilfs->ns_segctor_sem);
472	for (i = 0; i < nmembs; i++) {
473		ret = nilfs_bmap_lookup_at_level(bmap,
474						 bdescs[i].bd_offset,
475						 bdescs[i].bd_level + 1,
476						 &bdescs[i].bd_blocknr);
477		if (ret < 0) {
478			if (ret != -ENOENT) {
479				up_read(&nilfs->ns_segctor_sem);
480				return ret;
481			}
482			bdescs[i].bd_blocknr = 0;
483		}
484	}
485	up_read(&nilfs->ns_segctor_sem);
486	return nmembs;
487}
488
489/**
490 * nilfs_ioctl_get_bdescs - get disk block descriptors
491 * @inode: inode object
492 * @filp: file object
493 * @cmd: ioctl's request code
494 * @argp: pointer on argument from userspace
495 *
496 * Description: nilfs_ioctl_do_get_bdescs() function returns information
497 * about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl
498 * is used by nilfs_cleanerd daemon.
499 *
500 * Return Value: On success, 0 is returned, and disk block descriptors are
501 * copied into userspace pointer @argp. On error, one of the following
502 * negative error codes is returned.
503 *
504 * %-EINVAL - Invalid arguments from userspace.
505 *
506 * %-EIO - I/O error.
507 *
508 * %-ENOMEM - Insufficient amount of memory available.
509 *
510 * %-EFAULT - Failure during getting disk block descriptors.
511 */
512static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
513				  unsigned int cmd, void __user *argp)
514{
515	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
516	struct nilfs_argv argv;
517	int ret;
518
519	if (copy_from_user(&argv, argp, sizeof(argv)))
520		return -EFAULT;
521
522	if (argv.v_size != sizeof(struct nilfs_bdesc))
523		return -EINVAL;
524
525	ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
526				    nilfs_ioctl_do_get_bdescs);
527	if (ret < 0)
528		return ret;
529
530	if (copy_to_user(argp, &argv, sizeof(argv)))
531		ret = -EFAULT;
532	return ret;
533}
534
535/**
536 * nilfs_ioctl_move_inode_block - prepare data/node block for moving by GC
537 * @inode: inode object
538 * @vdesc: descriptor of virtual block number
539 * @buffers: list of moving buffers
540 *
541 * Description: nilfs_ioctl_move_inode_block() function registers data/node
542 * buffer in the GC pagecache and submit read request.
543 *
544 * Return Value: On success, 0 is returned. On error, one of the following
545 * negative error codes is returned.
546 *
547 * %-EIO - I/O error.
548 *
549 * %-ENOMEM - Insufficient amount of memory available.
550 *
551 * %-ENOENT - Requested block doesn't exist.
552 *
553 * %-EEXIST - Blocks conflict is detected.
554 */
555static int nilfs_ioctl_move_inode_block(struct inode *inode,
556					struct nilfs_vdesc *vdesc,
557					struct list_head *buffers)
558{
559	struct buffer_head *bh;
560	int ret;
561
562	if (vdesc->vd_flags == 0)
563		ret = nilfs_gccache_submit_read_data(
564			inode, vdesc->vd_offset, vdesc->vd_blocknr,
565			vdesc->vd_vblocknr, &bh);
566	else
567		ret = nilfs_gccache_submit_read_node(
568			inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
569
570	if (unlikely(ret < 0)) {
571		if (ret == -ENOENT)
572			nilfs_crit(inode->i_sb,
573				   "%s: invalid virtual block address (%s): ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu",
574				   __func__, vdesc->vd_flags ? "node" : "data",
575				   (unsigned long long)vdesc->vd_ino,
576				   (unsigned long long)vdesc->vd_cno,
577				   (unsigned long long)vdesc->vd_offset,
578				   (unsigned long long)vdesc->vd_blocknr,
579				   (unsigned long long)vdesc->vd_vblocknr);
580		return ret;
581	}
582	if (unlikely(!list_empty(&bh->b_assoc_buffers))) {
583		nilfs_crit(inode->i_sb,
584			   "%s: conflicting %s buffer: ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu",
585			   __func__, vdesc->vd_flags ? "node" : "data",
586			   (unsigned long long)vdesc->vd_ino,
587			   (unsigned long long)vdesc->vd_cno,
588			   (unsigned long long)vdesc->vd_offset,
589			   (unsigned long long)vdesc->vd_blocknr,
590			   (unsigned long long)vdesc->vd_vblocknr);
591		brelse(bh);
592		return -EEXIST;
593	}
594	list_add_tail(&bh->b_assoc_buffers, buffers);
595	return 0;
596}
597
598/**
599 * nilfs_ioctl_move_blocks - move valid inode's blocks during garbage collection
600 * @sb: superblock object
601 * @argv: vector of arguments from userspace
602 * @buf: array of nilfs_vdesc structures
603 *
604 * Description: nilfs_ioctl_move_blocks() function reads valid data/node
605 * blocks that garbage collector specified with the array of nilfs_vdesc
606 * structures and stores them into page caches of GC inodes.
607 *
608 * Return Value: Number of processed nilfs_vdesc structures or
609 * error code, otherwise.
610 */
611static int nilfs_ioctl_move_blocks(struct super_block *sb,
612				   struct nilfs_argv *argv, void *buf)
613{
614	size_t nmembs = argv->v_nmembs;
615	struct the_nilfs *nilfs = sb->s_fs_info;
616	struct inode *inode;
617	struct nilfs_vdesc *vdesc;
618	struct buffer_head *bh, *n;
619	LIST_HEAD(buffers);
620	ino_t ino;
621	__u64 cno;
622	int i, ret;
623
624	for (i = 0, vdesc = buf; i < nmembs; ) {
625		ino = vdesc->vd_ino;
626		cno = vdesc->vd_cno;
627		inode = nilfs_iget_for_gc(sb, ino, cno);
628		if (IS_ERR(inode)) {
629			ret = PTR_ERR(inode);
630			goto failed;
631		}
632		if (list_empty(&NILFS_I(inode)->i_dirty)) {
633			/*
634			 * Add the inode to GC inode list. Garbage Collection
635			 * is serialized and no two processes manipulate the
636			 * list simultaneously.
637			 */
638			igrab(inode);
639			list_add(&NILFS_I(inode)->i_dirty,
640				 &nilfs->ns_gc_inodes);
641		}
642
643		do {
644			ret = nilfs_ioctl_move_inode_block(inode, vdesc,
645							   &buffers);
646			if (unlikely(ret < 0)) {
647				iput(inode);
648				goto failed;
649			}
650			vdesc++;
651		} while (++i < nmembs &&
652			 vdesc->vd_ino == ino && vdesc->vd_cno == cno);
653
654		iput(inode); /* The inode still remains in GC inode list */
655	}
656
657	list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
658		ret = nilfs_gccache_wait_and_mark_dirty(bh);
659		if (unlikely(ret < 0)) {
660			WARN_ON(ret == -EEXIST);
661			goto failed;
662		}
663		list_del_init(&bh->b_assoc_buffers);
664		brelse(bh);
665	}
666	return nmembs;
667
668 failed:
669	list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
670		list_del_init(&bh->b_assoc_buffers);
671		brelse(bh);
672	}
673	return ret;
674}
675
676/**
677 * nilfs_ioctl_delete_checkpoints - delete checkpoints
678 * @nilfs: nilfs object
679 * @argv: vector of arguments from userspace
680 * @buf: array of periods of checkpoints numbers
681 *
682 * Description: nilfs_ioctl_delete_checkpoints() function deletes checkpoints
683 * in the period from p_start to p_end, excluding p_end itself. The checkpoints
684 * which have been already deleted are ignored.
685 *
686 * Return Value: Number of processed nilfs_period structures or
687 * error code, otherwise.
688 *
689 * %-EIO - I/O error.
690 *
691 * %-ENOMEM - Insufficient amount of memory available.
692 *
693 * %-EINVAL - invalid checkpoints.
694 */
695static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
696					  struct nilfs_argv *argv, void *buf)
697{
698	size_t nmembs = argv->v_nmembs;
699	struct inode *cpfile = nilfs->ns_cpfile;
700	struct nilfs_period *periods = buf;
701	int ret, i;
702
703	for (i = 0; i < nmembs; i++) {
704		ret = nilfs_cpfile_delete_checkpoints(
705			cpfile, periods[i].p_start, periods[i].p_end);
706		if (ret < 0)
707			return ret;
708	}
709	return nmembs;
710}
711
712/**
713 * nilfs_ioctl_free_vblocknrs - free virtual block numbers
714 * @nilfs: nilfs object
715 * @argv: vector of arguments from userspace
716 * @buf: array of virtual block numbers
717 *
718 * Description: nilfs_ioctl_free_vblocknrs() function frees
719 * the virtual block numbers specified by @buf and @argv->v_nmembs.
720 *
721 * Return Value: Number of processed virtual block numbers or
722 * error code, otherwise.
723 *
724 * %-EIO - I/O error.
725 *
726 * %-ENOMEM - Insufficient amount of memory available.
727 *
728 * %-ENOENT - The virtual block number have not been allocated.
729 */
730static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
731				      struct nilfs_argv *argv, void *buf)
732{
733	size_t nmembs = argv->v_nmembs;
734	int ret;
735
736	ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs);
737
738	return (ret < 0) ? ret : nmembs;
739}
740
741/**
742 * nilfs_ioctl_mark_blocks_dirty - mark blocks dirty
743 * @nilfs: nilfs object
744 * @argv: vector of arguments from userspace
745 * @buf: array of block descriptors
746 *
747 * Description: nilfs_ioctl_mark_blocks_dirty() function marks
748 * metadata file or data blocks as dirty.
749 *
750 * Return Value: Number of processed block descriptors or
751 * error code, otherwise.
752 *
753 * %-ENOMEM - Insufficient memory available.
754 *
755 * %-EIO - I/O error
756 *
757 * %-ENOENT - the specified block does not exist (hole block)
758 */
759static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
760					 struct nilfs_argv *argv, void *buf)
761{
762	size_t nmembs = argv->v_nmembs;
763	struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
764	struct nilfs_bdesc *bdescs = buf;
765	struct buffer_head *bh;
766	int ret, i;
767
768	for (i = 0; i < nmembs; i++) {
769		/* XXX: use macro or inline func to check liveness */
770		ret = nilfs_bmap_lookup_at_level(bmap,
771						 bdescs[i].bd_offset,
772						 bdescs[i].bd_level + 1,
773						 &bdescs[i].bd_blocknr);
774		if (ret < 0) {
775			if (ret != -ENOENT)
776				return ret;
777			bdescs[i].bd_blocknr = 0;
778		}
779		if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr)
780			/* skip dead block */
781			continue;
782		if (bdescs[i].bd_level == 0) {
783			ret = nilfs_mdt_get_block(nilfs->ns_dat,
784						  bdescs[i].bd_offset,
785						  false, NULL, &bh);
786			if (unlikely(ret)) {
787				WARN_ON(ret == -ENOENT);
788				return ret;
789			}
790			mark_buffer_dirty(bh);
791			nilfs_mdt_mark_dirty(nilfs->ns_dat);
792			put_bh(bh);
793		} else {
794			ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset,
795					      bdescs[i].bd_level);
796			if (ret < 0) {
797				WARN_ON(ret == -ENOENT);
798				return ret;
799			}
800		}
801	}
802	return nmembs;
803}
804
805int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
806				       struct nilfs_argv *argv, void **kbufs)
807{
808	const char *msg;
809	int ret;
810
811	ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
812	if (ret < 0) {
813		/*
814		 * can safely abort because checkpoints can be removed
815		 * independently.
816		 */
817		msg = "cannot delete checkpoints";
818		goto failed;
819	}
820	ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
821	if (ret < 0) {
822		/*
823		 * can safely abort because DAT file is updated atomically
824		 * using a copy-on-write technique.
825		 */
826		msg = "cannot delete virtual blocks from DAT file";
827		goto failed;
828	}
829	ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
830	if (ret < 0) {
831		/*
832		 * can safely abort because the operation is nondestructive.
833		 */
834		msg = "cannot mark copying blocks dirty";
835		goto failed;
836	}
837	return 0;
838
839 failed:
840	nilfs_err(nilfs->ns_sb, "error %d preparing GC: %s", ret, msg);
841	return ret;
842}
843
844/**
845 * nilfs_ioctl_clean_segments - clean segments
846 * @inode: inode object
847 * @filp: file object
848 * @cmd: ioctl's request code
849 * @argp: pointer on argument from userspace
850 *
851 * Description: nilfs_ioctl_clean_segments() function makes garbage
852 * collection operation in the environment of requested parameters
853 * from userspace. The NILFS_IOCTL_CLEAN_SEGMENTS ioctl is used by
854 * nilfs_cleanerd daemon.
855 *
856 * Return Value: On success, 0 is returned or error code, otherwise.
857 */
858static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
859				      unsigned int cmd, void __user *argp)
860{
861	struct nilfs_argv argv[5];
862	static const size_t argsz[5] = {
863		sizeof(struct nilfs_vdesc),
864		sizeof(struct nilfs_period),
865		sizeof(__u64),
866		sizeof(struct nilfs_bdesc),
867		sizeof(__u64),
868	};
869	void __user *base;
870	void *kbufs[5];
871	struct the_nilfs *nilfs;
872	size_t len, nsegs;
873	int n, ret;
874
875	if (!capable(CAP_SYS_ADMIN))
876		return -EPERM;
877
878	ret = mnt_want_write_file(filp);
879	if (ret)
880		return ret;
881
882	ret = -EFAULT;
883	if (copy_from_user(argv, argp, sizeof(argv)))
884		goto out;
885
886	ret = -EINVAL;
887	nsegs = argv[4].v_nmembs;
888	if (argv[4].v_size != argsz[4])
889		goto out;
890	if (nsegs > UINT_MAX / sizeof(__u64))
891		goto out;
892
893	/*
894	 * argv[4] points to segment numbers this ioctl cleans.  We
895	 * use kmalloc() for its buffer because memory used for the
896	 * segment numbers is enough small.
897	 */
898	kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base,
899			       nsegs * sizeof(__u64));
900	if (IS_ERR(kbufs[4])) {
901		ret = PTR_ERR(kbufs[4]);
902		goto out;
903	}
904	nilfs = inode->i_sb->s_fs_info;
905
906	for (n = 0; n < 4; n++) {
907		ret = -EINVAL;
908		if (argv[n].v_size != argsz[n])
909			goto out_free;
910
911		if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment)
912			goto out_free;
913
914		if (argv[n].v_nmembs >= UINT_MAX / argv[n].v_size)
915			goto out_free;
916
917		len = argv[n].v_size * argv[n].v_nmembs;
918		base = (void __user *)(unsigned long)argv[n].v_base;
919		if (len == 0) {
920			kbufs[n] = NULL;
921			continue;
922		}
923
924		kbufs[n] = vmalloc(len);
925		if (!kbufs[n]) {
926			ret = -ENOMEM;
927			goto out_free;
928		}
929		if (copy_from_user(kbufs[n], base, len)) {
930			ret = -EFAULT;
931			vfree(kbufs[n]);
932			goto out_free;
933		}
934	}
935
936	/*
937	 * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(),
938	 * which will operates an inode list without blocking.
939	 * To protect the list from concurrent operations,
940	 * nilfs_ioctl_move_blocks should be atomic operation.
941	 */
942	if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) {
943		ret = -EBUSY;
944		goto out_free;
945	}
946
947	ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
948	if (ret < 0) {
949		nilfs_err(inode->i_sb,
950			  "error %d preparing GC: cannot read source blocks",
951			  ret);
952	} else {
953		if (nilfs_sb_need_update(nilfs))
954			set_nilfs_discontinued(nilfs);
955		ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
956	}
957
958	nilfs_remove_all_gcinodes(nilfs);
959	clear_nilfs_gc_running(nilfs);
960
961out_free:
962	while (--n >= 0)
963		vfree(kbufs[n]);
964	kfree(kbufs[4]);
965out:
966	mnt_drop_write_file(filp);
967	return ret;
968}
969
970/**
971 * nilfs_ioctl_sync - make a checkpoint
972 * @inode: inode object
973 * @filp: file object
974 * @cmd: ioctl's request code
975 * @argp: pointer on argument from userspace
976 *
977 * Description: nilfs_ioctl_sync() function constructs a logical segment
978 * for checkpointing.  This function guarantees that all modified data
979 * and metadata are written out to the device when it successfully
980 * returned.
981 *
982 * Return Value: On success, 0 is retured. On errors, one of the following
983 * negative error code is returned.
984 *
985 * %-EROFS - Read only filesystem.
986 *
987 * %-EIO - I/O error
988 *
989 * %-ENOSPC - No space left on device (only in a panic state).
990 *
991 * %-ERESTARTSYS - Interrupted.
992 *
993 * %-ENOMEM - Insufficient memory available.
994 *
995 * %-EFAULT - Failure during execution of requested operation.
996 */
997static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
998			    unsigned int cmd, void __user *argp)
999{
1000	__u64 cno;
1001	int ret;
1002	struct the_nilfs *nilfs;
1003
1004	ret = nilfs_construct_segment(inode->i_sb);
1005	if (ret < 0)
1006		return ret;
1007
1008	nilfs = inode->i_sb->s_fs_info;
1009	ret = nilfs_flush_device(nilfs);
1010	if (ret < 0)
1011		return ret;
1012
1013	if (argp != NULL) {
1014		down_read(&nilfs->ns_segctor_sem);
1015		cno = nilfs->ns_cno - 1;
1016		up_read(&nilfs->ns_segctor_sem);
1017		if (copy_to_user(argp, &cno, sizeof(cno)))
1018			return -EFAULT;
1019	}
1020	return 0;
1021}
1022
1023/**
1024 * nilfs_ioctl_resize - resize NILFS2 volume
1025 * @inode: inode object
1026 * @filp: file object
1027 * @argp: pointer on argument from userspace
1028 *
1029 * Return Value: On success, 0 is returned or error code, otherwise.
1030 */
1031static int nilfs_ioctl_resize(struct inode *inode, struct file *filp,
1032			      void __user *argp)
1033{
1034	__u64 newsize;
1035	int ret = -EPERM;
1036
1037	if (!capable(CAP_SYS_ADMIN))
1038		goto out;
1039
1040	ret = mnt_want_write_file(filp);
1041	if (ret)
1042		goto out;
1043
1044	ret = -EFAULT;
1045	if (copy_from_user(&newsize, argp, sizeof(newsize)))
1046		goto out_drop_write;
1047
1048	ret = nilfs_resize_fs(inode->i_sb, newsize);
1049
1050out_drop_write:
1051	mnt_drop_write_file(filp);
1052out:
1053	return ret;
1054}
1055
1056/**
1057 * nilfs_ioctl_trim_fs() - trim ioctl handle function
1058 * @inode: inode object
1059 * @argp: pointer on argument from userspace
1060 *
1061 * Decription: nilfs_ioctl_trim_fs is the FITRIM ioctl handle function. It
1062 * checks the arguments from userspace and calls nilfs_sufile_trim_fs, which
1063 * performs the actual trim operation.
1064 *
1065 * Return Value: On success, 0 is returned or negative error code, otherwise.
1066 */
1067static int nilfs_ioctl_trim_fs(struct inode *inode, void __user *argp)
1068{
1069	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1070	struct request_queue *q = bdev_get_queue(nilfs->ns_bdev);
1071	struct fstrim_range range;
1072	int ret;
1073
1074	if (!capable(CAP_SYS_ADMIN))
1075		return -EPERM;
1076
1077	if (!blk_queue_discard(q))
1078		return -EOPNOTSUPP;
1079
1080	if (copy_from_user(&range, argp, sizeof(range)))
1081		return -EFAULT;
1082
1083	range.minlen = max_t(u64, range.minlen, q->limits.discard_granularity);
1084
1085	down_read(&nilfs->ns_segctor_sem);
1086	ret = nilfs_sufile_trim_fs(nilfs->ns_sufile, &range);
1087	up_read(&nilfs->ns_segctor_sem);
1088
1089	if (ret < 0)
1090		return ret;
1091
1092	if (copy_to_user(argp, &range, sizeof(range)))
1093		return -EFAULT;
1094
1095	return 0;
1096}
1097
1098/**
1099 * nilfs_ioctl_set_alloc_range - limit range of segments to be allocated
1100 * @inode: inode object
1101 * @argp: pointer on argument from userspace
1102 *
1103 * Decription: nilfs_ioctl_set_alloc_range() function defines lower limit
1104 * of segments in bytes and upper limit of segments in bytes.
1105 * The NILFS_IOCTL_SET_ALLOC_RANGE is used by nilfs_resize utility.
1106 *
1107 * Return Value: On success, 0 is returned or error code, otherwise.
1108 */
1109static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
1110{
1111	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1112	__u64 range[2];
1113	__u64 minseg, maxseg;
1114	unsigned long segbytes;
1115	int ret = -EPERM;
1116
1117	if (!capable(CAP_SYS_ADMIN))
1118		goto out;
1119
1120	ret = -EFAULT;
1121	if (copy_from_user(range, argp, sizeof(__u64[2])))
1122		goto out;
1123
1124	ret = -ERANGE;
1125	if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode))
1126		goto out;
1127
1128	segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize;
1129
1130	minseg = range[0] + segbytes - 1;
1131	do_div(minseg, segbytes);
1132
1133	if (range[1] < 4096)
1134		goto out;
1135
1136	maxseg = NILFS_SB2_OFFSET_BYTES(range[1]);
1137	if (maxseg < segbytes)
1138		goto out;
1139
1140	do_div(maxseg, segbytes);
1141	maxseg--;
1142
1143	ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg);
1144out:
1145	return ret;
1146}
1147
1148/**
1149 * nilfs_ioctl_get_info - wrapping function of get metadata info
1150 * @inode: inode object
1151 * @filp: file object
1152 * @cmd: ioctl's request code
1153 * @argp: pointer on argument from userspace
1154 * @membsz: size of an item in bytes
1155 * @dofunc: concrete function of getting metadata info
1156 *
1157 * Description: nilfs_ioctl_get_info() gets metadata info by means of
1158 * calling dofunc() function.
1159 *
1160 * Return Value: On success, 0 is returned and requested metadata info
1161 * is copied into userspace. On error, one of the following
1162 * negative error codes is returned.
1163 *
1164 * %-EINVAL - Invalid arguments from userspace.
1165 *
1166 * %-ENOMEM - Insufficient amount of memory available.
1167 *
1168 * %-EFAULT - Failure during execution of requested operation.
1169 */
1170static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
1171				unsigned int cmd, void __user *argp,
1172				size_t membsz,
1173				ssize_t (*dofunc)(struct the_nilfs *,
1174						  __u64 *, int,
1175						  void *, size_t, size_t))
1176
1177{
1178	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1179	struct nilfs_argv argv;
1180	int ret;
1181
1182	if (copy_from_user(&argv, argp, sizeof(argv)))
1183		return -EFAULT;
1184
1185	if (argv.v_size < membsz)
1186		return -EINVAL;
1187
1188	ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
1189	if (ret < 0)
1190		return ret;
1191
1192	if (copy_to_user(argp, &argv, sizeof(argv)))
1193		ret = -EFAULT;
1194	return ret;
1195}
1196
1197/**
1198 * nilfs_ioctl_set_suinfo - set segment usage info
1199 * @inode: inode object
1200 * @filp: file object
1201 * @cmd: ioctl's request code
1202 * @argp: pointer on argument from userspace
1203 *
1204 * Description: Expects an array of nilfs_suinfo_update structures
1205 * encapsulated in nilfs_argv and updates the segment usage info
1206 * according to the flags in nilfs_suinfo_update.
1207 *
1208 * Return Value: On success, 0 is returned. On error, one of the
1209 * following negative error codes is returned.
1210 *
1211 * %-EPERM - Not enough permissions
1212 *
1213 * %-EFAULT - Error copying input data
1214 *
1215 * %-EIO - I/O error.
1216 *
1217 * %-ENOMEM - Insufficient amount of memory available.
1218 *
1219 * %-EINVAL - Invalid values in input (segment number, flags or nblocks)
1220 */
1221static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
1222				unsigned int cmd, void __user *argp)
1223{
1224	struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1225	struct nilfs_transaction_info ti;
1226	struct nilfs_argv argv;
1227	size_t len;
1228	void __user *base;
1229	void *kbuf;
1230	int ret;
1231
1232	if (!capable(CAP_SYS_ADMIN))
1233		return -EPERM;
1234
1235	ret = mnt_want_write_file(filp);
1236	if (ret)
1237		return ret;
1238
1239	ret = -EFAULT;
1240	if (copy_from_user(&argv, argp, sizeof(argv)))
1241		goto out;
1242
1243	ret = -EINVAL;
1244	if (argv.v_size < sizeof(struct nilfs_suinfo_update))
1245		goto out;
1246
1247	if (argv.v_nmembs > nilfs->ns_nsegments)
1248		goto out;
1249
1250	if (argv.v_nmembs >= UINT_MAX / argv.v_size)
1251		goto out;
1252
1253	len = argv.v_size * argv.v_nmembs;
1254	if (!len) {
1255		ret = 0;
1256		goto out;
1257	}
1258
1259	base = (void __user *)(unsigned long)argv.v_base;
1260	kbuf = vmalloc(len);
1261	if (!kbuf) {
1262		ret = -ENOMEM;
1263		goto out;
1264	}
1265
1266	if (copy_from_user(kbuf, base, len)) {
1267		ret = -EFAULT;
1268		goto out_free;
1269	}
1270
1271	nilfs_transaction_begin(inode->i_sb, &ti, 0);
1272	ret = nilfs_sufile_set_suinfo(nilfs->ns_sufile, kbuf, argv.v_size,
1273			argv.v_nmembs);
1274	if (unlikely(ret < 0))
1275		nilfs_transaction_abort(inode->i_sb);
1276	else
1277		nilfs_transaction_commit(inode->i_sb); /* never fails */
1278
1279out_free:
1280	vfree(kbuf);
1281out:
1282	mnt_drop_write_file(filp);
1283	return ret;
1284}
1285
1286long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1287{
1288	struct inode *inode = file_inode(filp);
1289	void __user *argp = (void __user *)arg;
1290
1291	switch (cmd) {
1292	case FS_IOC_GETFLAGS:
1293		return nilfs_ioctl_getflags(inode, argp);
1294	case FS_IOC_SETFLAGS:
1295		return nilfs_ioctl_setflags(inode, filp, argp);
1296	case FS_IOC_GETVERSION:
1297		return nilfs_ioctl_getversion(inode, argp);
1298	case NILFS_IOCTL_CHANGE_CPMODE:
1299		return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
1300	case NILFS_IOCTL_DELETE_CHECKPOINT:
1301		return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
1302	case NILFS_IOCTL_GET_CPINFO:
1303		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1304					    sizeof(struct nilfs_cpinfo),
1305					    nilfs_ioctl_do_get_cpinfo);
1306	case NILFS_IOCTL_GET_CPSTAT:
1307		return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
1308	case NILFS_IOCTL_GET_SUINFO:
1309		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1310					    sizeof(struct nilfs_suinfo),
1311					    nilfs_ioctl_do_get_suinfo);
1312	case NILFS_IOCTL_SET_SUINFO:
1313		return nilfs_ioctl_set_suinfo(inode, filp, cmd, argp);
1314	case NILFS_IOCTL_GET_SUSTAT:
1315		return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
1316	case NILFS_IOCTL_GET_VINFO:
1317		return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1318					    sizeof(struct nilfs_vinfo),
1319					    nilfs_ioctl_do_get_vinfo);
1320	case NILFS_IOCTL_GET_BDESCS:
1321		return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
1322	case NILFS_IOCTL_CLEAN_SEGMENTS:
1323		return nilfs_ioctl_clean_segments(inode, filp, cmd, argp);
1324	case NILFS_IOCTL_SYNC:
1325		return nilfs_ioctl_sync(inode, filp, cmd, argp);
1326	case NILFS_IOCTL_RESIZE:
1327		return nilfs_ioctl_resize(inode, filp, argp);
1328	case NILFS_IOCTL_SET_ALLOC_RANGE:
1329		return nilfs_ioctl_set_alloc_range(inode, argp);
1330	case FITRIM:
1331		return nilfs_ioctl_trim_fs(inode, argp);
1332	default:
1333		return -ENOTTY;
1334	}
1335}
1336
1337#ifdef CONFIG_COMPAT
1338long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1339{
1340	switch (cmd) {
1341	case FS_IOC32_GETFLAGS:
1342		cmd = FS_IOC_GETFLAGS;
1343		break;
1344	case FS_IOC32_SETFLAGS:
1345		cmd = FS_IOC_SETFLAGS;
1346		break;
1347	case FS_IOC32_GETVERSION:
1348		cmd = FS_IOC_GETVERSION;
1349		break;
1350	case NILFS_IOCTL_CHANGE_CPMODE:
1351	case NILFS_IOCTL_DELETE_CHECKPOINT:
1352	case NILFS_IOCTL_GET_CPINFO:
1353	case NILFS_IOCTL_GET_CPSTAT:
1354	case NILFS_IOCTL_GET_SUINFO:
1355	case NILFS_IOCTL_SET_SUINFO:
1356	case NILFS_IOCTL_GET_SUSTAT:
1357	case NILFS_IOCTL_GET_VINFO:
1358	case NILFS_IOCTL_GET_BDESCS:
1359	case NILFS_IOCTL_CLEAN_SEGMENTS:
1360	case NILFS_IOCTL_SYNC:
1361	case NILFS_IOCTL_RESIZE:
1362	case NILFS_IOCTL_SET_ALLOC_RANGE:
1363	case FITRIM:
1364		break;
1365	default:
1366		return -ENOIOCTLCMD;
1367	}
1368	return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
1369}
1370#endif
1371