2 * ioctl.c - NILFS ioctl operations.
4 * Copyright (C) 2007, 2008 Nippon Telegraph and Telephone Corporation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 * Written by Koji Sato <koji@osrg.net>.
24 #include <linux/wait.h>
25 #include <linux/smp_lock.h> /* lock_kernel(), unlock_kernel() */
26 #include <linux/capability.h> /* capable() */
27 #include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */
28 #include <linux/nilfs2_fs.h>
37 static int nilfs_ioctl_wrap_copy(struct the_nilfs
*nilfs
,
38 struct nilfs_argv
*argv
, int dir
,
39 ssize_t (*dofunc
)(struct the_nilfs
*,
41 void *, size_t, size_t))
44 size_t maxmembs
, total
, n
;
49 if (argv
->v_nmembs
== 0)
52 if (argv
->v_size
> PAGE_SIZE
)
55 buf
= (void *)__get_free_pages(GFP_NOFS
, 0);
58 maxmembs
= PAGE_SIZE
/ argv
->v_size
;
63 for (i
= 0; i
< argv
->v_nmembs
; i
+= n
) {
64 n
= (argv
->v_nmembs
- i
< maxmembs
) ?
65 argv
->v_nmembs
- i
: maxmembs
;
66 if ((dir
& _IOC_WRITE
) &&
68 (void __user
*)argv
->v_base
+ argv
->v_size
* i
,
74 nr
= dofunc(nilfs
, &pos
, argv
->v_flags
, buf
, argv
->v_size
,
80 if ((dir
& _IOC_READ
) &&
82 (void __user
*)argv
->v_base
+ argv
->v_size
* i
,
83 buf
, argv
->v_size
* nr
)) {
93 argv
->v_nmembs
= total
;
95 free_pages((unsigned long)buf
, 0);
99 static int nilfs_ioctl_change_cpmode(struct inode
*inode
, struct file
*filp
,
100 unsigned int cmd
, void __user
*argp
)
102 struct inode
*cpfile
= NILFS_SB(inode
->i_sb
)->s_nilfs
->ns_cpfile
;
103 struct nilfs_transaction_info ti
;
104 struct nilfs_cpmode cpmode
;
107 if (!capable(CAP_SYS_ADMIN
))
109 if (copy_from_user(&cpmode
, argp
, sizeof(cpmode
)))
112 nilfs_transaction_begin(inode
->i_sb
, &ti
, 0);
113 ret
= nilfs_cpfile_change_cpmode(
114 cpfile
, cpmode
.cm_cno
, cpmode
.cm_mode
);
115 if (unlikely(ret
< 0)) {
116 nilfs_transaction_abort(inode
->i_sb
);
119 nilfs_transaction_commit(inode
->i_sb
); /* never fails */
124 nilfs_ioctl_delete_checkpoint(struct inode
*inode
, struct file
*filp
,
125 unsigned int cmd
, void __user
*argp
)
127 struct inode
*cpfile
= NILFS_SB(inode
->i_sb
)->s_nilfs
->ns_cpfile
;
128 struct nilfs_transaction_info ti
;
132 if (!capable(CAP_SYS_ADMIN
))
134 if (copy_from_user(&cno
, argp
, sizeof(cno
)))
137 nilfs_transaction_begin(inode
->i_sb
, &ti
, 0);
138 ret
= nilfs_cpfile_delete_checkpoint(cpfile
, cno
);
139 if (unlikely(ret
< 0)) {
140 nilfs_transaction_abort(inode
->i_sb
);
143 nilfs_transaction_commit(inode
->i_sb
); /* never fails */
148 nilfs_ioctl_do_get_cpinfo(struct the_nilfs
*nilfs
, __u64
*posp
, int flags
,
149 void *buf
, size_t size
, size_t nmembs
)
151 return nilfs_cpfile_get_cpinfo(nilfs
->ns_cpfile
, posp
, flags
, buf
,
155 static int nilfs_ioctl_get_cpinfo(struct inode
*inode
, struct file
*filp
,
156 unsigned int cmd
, void __user
*argp
)
158 struct the_nilfs
*nilfs
= NILFS_SB(inode
->i_sb
)->s_nilfs
;
159 struct nilfs_argv argv
;
162 if (copy_from_user(&argv
, argp
, sizeof(argv
)))
165 down_read(&nilfs
->ns_segctor_sem
);
166 ret
= nilfs_ioctl_wrap_copy(nilfs
, &argv
, _IOC_DIR(cmd
),
167 nilfs_ioctl_do_get_cpinfo
);
168 up_read(&nilfs
->ns_segctor_sem
);
172 if (copy_to_user(argp
, &argv
, sizeof(argv
)))
177 static int nilfs_ioctl_get_cpstat(struct inode
*inode
, struct file
*filp
,
178 unsigned int cmd
, void __user
*argp
)
180 struct the_nilfs
*nilfs
= NILFS_SB(inode
->i_sb
)->s_nilfs
;
181 struct nilfs_cpstat cpstat
;
184 down_read(&nilfs
->ns_segctor_sem
);
185 ret
= nilfs_cpfile_get_stat(nilfs
->ns_cpfile
, &cpstat
);
186 up_read(&nilfs
->ns_segctor_sem
);
190 if (copy_to_user(argp
, &cpstat
, sizeof(cpstat
)))
196 nilfs_ioctl_do_get_suinfo(struct the_nilfs
*nilfs
, __u64
*posp
, int flags
,
197 void *buf
, size_t size
, size_t nmembs
)
199 return nilfs_sufile_get_suinfo(nilfs
->ns_sufile
, *posp
, buf
, nmembs
);
202 static int nilfs_ioctl_get_suinfo(struct inode
*inode
, struct file
*filp
,
203 unsigned int cmd
, void __user
*argp
)
205 struct the_nilfs
*nilfs
= NILFS_SB(inode
->i_sb
)->s_nilfs
;
206 struct nilfs_argv argv
;
209 if (copy_from_user(&argv
, argp
, sizeof(argv
)))
212 down_read(&nilfs
->ns_segctor_sem
);
213 ret
= nilfs_ioctl_wrap_copy(nilfs
, &argv
, _IOC_DIR(cmd
),
214 nilfs_ioctl_do_get_suinfo
);
215 up_read(&nilfs
->ns_segctor_sem
);
219 if (copy_to_user(argp
, &argv
, sizeof(argv
)))
224 static int nilfs_ioctl_get_sustat(struct inode
*inode
, struct file
*filp
,
225 unsigned int cmd
, void __user
*argp
)
227 struct the_nilfs
*nilfs
= NILFS_SB(inode
->i_sb
)->s_nilfs
;
228 struct nilfs_sustat sustat
;
231 down_read(&nilfs
->ns_segctor_sem
);
232 ret
= nilfs_sufile_get_stat(nilfs
->ns_sufile
, &sustat
);
233 up_read(&nilfs
->ns_segctor_sem
);
237 if (copy_to_user(argp
, &sustat
, sizeof(sustat
)))
243 nilfs_ioctl_do_get_vinfo(struct the_nilfs
*nilfs
, __u64
*posp
, int flags
,
244 void *buf
, size_t size
, size_t nmembs
)
246 return nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs
), buf
, nmembs
);
249 static int nilfs_ioctl_get_vinfo(struct inode
*inode
, struct file
*filp
,
250 unsigned int cmd
, void __user
*argp
)
252 struct the_nilfs
*nilfs
= NILFS_SB(inode
->i_sb
)->s_nilfs
;
253 struct nilfs_argv argv
;
256 if (copy_from_user(&argv
, argp
, sizeof(argv
)))
259 down_read(&nilfs
->ns_segctor_sem
);
260 ret
= nilfs_ioctl_wrap_copy(nilfs
, &argv
, _IOC_DIR(cmd
),
261 nilfs_ioctl_do_get_vinfo
);
262 up_read(&nilfs
->ns_segctor_sem
);
266 if (copy_to_user(argp
, &argv
, sizeof(argv
)))
272 nilfs_ioctl_do_get_bdescs(struct the_nilfs
*nilfs
, __u64
*posp
, int flags
,
273 void *buf
, size_t size
, size_t nmembs
)
275 struct inode
*dat
= nilfs_dat_inode(nilfs
);
276 struct nilfs_bmap
*bmap
= NILFS_I(dat
)->i_bmap
;
277 struct nilfs_bdesc
*bdescs
= buf
;
280 for (i
= 0; i
< nmembs
; i
++) {
281 ret
= nilfs_bmap_lookup_at_level(bmap
,
283 bdescs
[i
].bd_level
+ 1,
284 &bdescs
[i
].bd_blocknr
);
288 bdescs
[i
].bd_blocknr
= 0;
294 static int nilfs_ioctl_get_bdescs(struct inode
*inode
, struct file
*filp
,
295 unsigned int cmd
, void __user
*argp
)
297 struct the_nilfs
*nilfs
= NILFS_SB(inode
->i_sb
)->s_nilfs
;
298 struct nilfs_argv argv
;
301 if (copy_from_user(&argv
, argp
, sizeof(argv
)))
304 down_read(&nilfs
->ns_segctor_sem
);
305 ret
= nilfs_ioctl_wrap_copy(nilfs
, &argv
, _IOC_DIR(cmd
),
306 nilfs_ioctl_do_get_bdescs
);
307 up_read(&nilfs
->ns_segctor_sem
);
311 if (copy_to_user(argp
, &argv
, sizeof(argv
)))
316 static int nilfs_ioctl_move_inode_block(struct inode
*inode
,
317 struct nilfs_vdesc
*vdesc
,
318 struct list_head
*buffers
)
320 struct buffer_head
*bh
;
323 if (vdesc
->vd_flags
== 0)
324 ret
= nilfs_gccache_submit_read_data(
325 inode
, vdesc
->vd_offset
, vdesc
->vd_blocknr
,
326 vdesc
->vd_vblocknr
, &bh
);
328 ret
= nilfs_gccache_submit_read_node(
329 inode
, vdesc
->vd_blocknr
, vdesc
->vd_vblocknr
, &bh
);
331 if (unlikely(ret
< 0)) {
334 "%s: invalid virtual block address (%s): "
335 "ino=%llu, cno=%llu, offset=%llu, "
336 "blocknr=%llu, vblocknr=%llu\n",
337 __func__
, vdesc
->vd_flags
? "node" : "data",
338 (unsigned long long)vdesc
->vd_ino
,
339 (unsigned long long)vdesc
->vd_cno
,
340 (unsigned long long)vdesc
->vd_offset
,
341 (unsigned long long)vdesc
->vd_blocknr
,
342 (unsigned long long)vdesc
->vd_vblocknr
);
345 bh
->b_private
= vdesc
;
346 list_add_tail(&bh
->b_assoc_buffers
, buffers
);
351 nilfs_ioctl_do_move_blocks(struct the_nilfs
*nilfs
, __u64
*posp
, int flags
,
352 void *buf
, size_t size
, size_t nmembs
)
355 struct nilfs_vdesc
*vdesc
;
356 struct buffer_head
*bh
, *n
;
362 for (i
= 0, vdesc
= buf
; i
< nmembs
; ) {
365 inode
= nilfs_gc_iget(nilfs
, ino
, cno
);
366 if (unlikely(inode
== NULL
)) {
371 ret
= nilfs_ioctl_move_inode_block(inode
, vdesc
,
373 if (unlikely(ret
< 0))
376 } while (++i
< nmembs
&&
377 vdesc
->vd_ino
== ino
&& vdesc
->vd_cno
== cno
);
380 list_for_each_entry_safe(bh
, n
, &buffers
, b_assoc_buffers
) {
381 ret
= nilfs_gccache_wait_and_mark_dirty(bh
);
382 if (unlikely(ret
< 0)) {
383 if (ret
== -EEXIST
) {
384 vdesc
= bh
->b_private
;
386 "%s: conflicting %s buffer: "
387 "ino=%llu, cno=%llu, offset=%llu, "
388 "blocknr=%llu, vblocknr=%llu\n",
390 vdesc
->vd_flags
? "node" : "data",
391 (unsigned long long)vdesc
->vd_ino
,
392 (unsigned long long)vdesc
->vd_cno
,
393 (unsigned long long)vdesc
->vd_offset
,
394 (unsigned long long)vdesc
->vd_blocknr
,
395 (unsigned long long)vdesc
->vd_vblocknr
);
399 list_del_init(&bh
->b_assoc_buffers
);
400 bh
->b_private
= NULL
;
406 list_for_each_entry_safe(bh
, n
, &buffers
, b_assoc_buffers
) {
407 list_del_init(&bh
->b_assoc_buffers
);
408 bh
->b_private
= NULL
;
414 static inline int nilfs_ioctl_move_blocks(struct the_nilfs
*nilfs
,
415 struct nilfs_argv
*argv
,
418 return nilfs_ioctl_wrap_copy(nilfs
, argv
, dir
,
419 nilfs_ioctl_do_move_blocks
);
423 nilfs_ioctl_do_delete_checkpoints(struct the_nilfs
*nilfs
, __u64
*posp
,
424 int flags
, void *buf
, size_t size
,
427 struct inode
*cpfile
= nilfs
->ns_cpfile
;
428 struct nilfs_period
*periods
= buf
;
431 for (i
= 0; i
< nmembs
; i
++) {
432 ret
= nilfs_cpfile_delete_checkpoints(
433 cpfile
, periods
[i
].p_start
, periods
[i
].p_end
);
440 static inline int nilfs_ioctl_delete_checkpoints(struct the_nilfs
*nilfs
,
441 struct nilfs_argv
*argv
,
444 return nilfs_ioctl_wrap_copy(nilfs
, argv
, dir
,
445 nilfs_ioctl_do_delete_checkpoints
);
449 nilfs_ioctl_do_free_vblocknrs(struct the_nilfs
*nilfs
, __u64
*posp
, int flags
,
450 void *buf
, size_t size
, size_t nmembs
)
452 int ret
= nilfs_dat_freev(nilfs_dat_inode(nilfs
), buf
, nmembs
);
454 return (ret
< 0) ? ret
: nmembs
;
457 static inline int nilfs_ioctl_free_vblocknrs(struct the_nilfs
*nilfs
,
458 struct nilfs_argv
*argv
,
461 return nilfs_ioctl_wrap_copy(nilfs
, argv
, dir
,
462 nilfs_ioctl_do_free_vblocknrs
);
466 nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs
*nilfs
, __u64
*posp
,
467 int flags
, void *buf
, size_t size
,
470 struct inode
*dat
= nilfs_dat_inode(nilfs
);
471 struct nilfs_bmap
*bmap
= NILFS_I(dat
)->i_bmap
;
472 struct nilfs_bdesc
*bdescs
= buf
;
475 for (i
= 0; i
< nmembs
; i
++) {
476 /* XXX: use macro or inline func to check liveness */
477 ret
= nilfs_bmap_lookup_at_level(bmap
,
479 bdescs
[i
].bd_level
+ 1,
480 &bdescs
[i
].bd_blocknr
);
484 bdescs
[i
].bd_blocknr
= 0;
486 if (bdescs
[i
].bd_blocknr
!= bdescs
[i
].bd_oblocknr
)
487 /* skip dead block */
489 if (bdescs
[i
].bd_level
== 0) {
490 ret
= nilfs_mdt_mark_block_dirty(dat
,
491 bdescs
[i
].bd_offset
);
493 BUG_ON(ret
== -ENOENT
);
497 ret
= nilfs_bmap_mark(bmap
, bdescs
[i
].bd_offset
,
500 BUG_ON(ret
== -ENOENT
);
508 static inline int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs
*nilfs
,
509 struct nilfs_argv
*argv
,
512 return nilfs_ioctl_wrap_copy(nilfs
, argv
, dir
,
513 nilfs_ioctl_do_mark_blocks_dirty
);
517 nilfs_ioctl_do_free_segments(struct the_nilfs
*nilfs
, __u64
*posp
, int flags
,
518 void *buf
, size_t size
, size_t nmembs
)
520 struct nilfs_sb_info
*sbi
= nilfs_get_writer(nilfs
);
524 ret
= nilfs_segctor_add_segments_to_be_freed(
525 NILFS_SC(sbi
), buf
, nmembs
);
526 nilfs_put_writer(nilfs
);
528 return (ret
< 0) ? ret
: nmembs
;
531 static inline int nilfs_ioctl_free_segments(struct the_nilfs
*nilfs
,
532 struct nilfs_argv
*argv
,
535 return nilfs_ioctl_wrap_copy(nilfs
, argv
, dir
,
536 nilfs_ioctl_do_free_segments
);
539 int nilfs_ioctl_prepare_clean_segments(struct the_nilfs
*nilfs
,
542 struct nilfs_argv argv
[5];
545 if (copy_from_user(argv
, argp
, sizeof(argv
)))
549 ret
= nilfs_ioctl_move_blocks(nilfs
, &argv
[0], dir
);
552 ret
= nilfs_ioctl_delete_checkpoints(nilfs
, &argv
[1], dir
);
555 ret
= nilfs_ioctl_free_vblocknrs(nilfs
, &argv
[2], dir
);
558 ret
= nilfs_ioctl_mark_blocks_dirty(nilfs
, &argv
[3], dir
);
561 ret
= nilfs_ioctl_free_segments(nilfs
, &argv
[4], dir
);
568 BUG(); /* XXX: not implemented yet */
570 BUG();/* XXX: not implemented yet */
572 BUG();/* XXX: not implemented yet */
574 nilfs_remove_all_gcinode(nilfs
);
578 static int nilfs_ioctl_clean_segments(struct inode
*inode
, struct file
*filp
,
579 unsigned int cmd
, void __user
*argp
)
581 if (!capable(CAP_SYS_ADMIN
))
583 return nilfs_clean_segments(inode
->i_sb
, argp
);
586 static int nilfs_ioctl_sync(struct inode
*inode
, struct file
*filp
,
587 unsigned int cmd
, void __user
*argp
)
592 ret
= nilfs_construct_segment(inode
->i_sb
);
597 cno
= NILFS_SB(inode
->i_sb
)->s_nilfs
->ns_cno
- 1;
598 if (copy_to_user(argp
, &cno
, sizeof(cno
)))
604 int nilfs_ioctl(struct inode
*inode
, struct file
*filp
, unsigned int cmd
,
607 void __user
*argp
= (void * __user
*)arg
;
610 case NILFS_IOCTL_CHANGE_CPMODE
:
611 return nilfs_ioctl_change_cpmode(inode
, filp
, cmd
, argp
);
612 case NILFS_IOCTL_DELETE_CHECKPOINT
:
613 return nilfs_ioctl_delete_checkpoint(inode
, filp
, cmd
, argp
);
614 case NILFS_IOCTL_GET_CPINFO
:
615 return nilfs_ioctl_get_cpinfo(inode
, filp
, cmd
, argp
);
616 case NILFS_IOCTL_GET_CPSTAT
:
617 return nilfs_ioctl_get_cpstat(inode
, filp
, cmd
, argp
);
618 case NILFS_IOCTL_GET_SUINFO
:
619 return nilfs_ioctl_get_suinfo(inode
, filp
, cmd
, argp
);
620 case NILFS_IOCTL_GET_SUSTAT
:
621 return nilfs_ioctl_get_sustat(inode
, filp
, cmd
, argp
);
622 case NILFS_IOCTL_GET_VINFO
:
623 /* XXX: rename to ??? */
624 return nilfs_ioctl_get_vinfo(inode
, filp
, cmd
, argp
);
625 case NILFS_IOCTL_GET_BDESCS
:
626 return nilfs_ioctl_get_bdescs(inode
, filp
, cmd
, argp
);
627 case NILFS_IOCTL_CLEAN_SEGMENTS
:
628 return nilfs_ioctl_clean_segments(inode
, filp
, cmd
, argp
);
629 case NILFS_IOCTL_SYNC
:
630 return nilfs_ioctl_sync(inode
, filp
, cmd
, argp
);
638 #include <linux/compat.h>
640 static int nilfs_compat_locked_ioctl(struct inode
*inode
, struct file
*filp
,
641 unsigned int cmd
, unsigned long arg
)
646 ret
= nilfs_ioctl(inode
, filp
, cmd
, arg
);
652 nilfs_compat_ioctl_uargv32_to_uargv(struct nilfs_argv32 __user
*uargv32
,
653 struct nilfs_argv __user
*uargv
)
656 compat_size_t nmembs
, size
;
657 compat_int_t index
, flags
;
659 if (get_user(base
, &uargv32
->v_base
) ||
660 put_user(compat_ptr(base
), &uargv
->v_base
) ||
661 get_user(nmembs
, &uargv32
->v_nmembs
) ||
662 put_user(nmembs
, &uargv
->v_nmembs
) ||
663 get_user(size
, &uargv32
->v_size
) ||
664 put_user(size
, &uargv
->v_size
) ||
665 get_user(index
, &uargv32
->v_index
) ||
666 put_user(index
, &uargv
->v_index
) ||
667 get_user(flags
, &uargv32
->v_flags
) ||
668 put_user(flags
, &uargv
->v_flags
))
674 nilfs_compat_ioctl_uargv_to_uargv32(struct nilfs_argv __user
*uargv
,
675 struct nilfs_argv32 __user
*uargv32
)
679 if (get_user(nmembs
, &uargv
->v_nmembs
) ||
680 put_user(nmembs
, &uargv32
->v_nmembs
))
686 nilfs_compat_ioctl_get_by_argv(struct inode
*inode
, struct file
*filp
,
687 unsigned int cmd
, unsigned long arg
)
689 struct nilfs_argv __user
*uargv
;
690 struct nilfs_argv32 __user
*uargv32
;
693 uargv
= compat_alloc_user_space(sizeof(struct nilfs_argv
));
694 uargv32
= compat_ptr(arg
);
695 ret
= nilfs_compat_ioctl_uargv32_to_uargv(uargv32
, uargv
);
699 ret
= nilfs_compat_locked_ioctl(inode
, filp
, cmd
, (unsigned long)uargv
);
703 return nilfs_compat_ioctl_uargv_to_uargv32(uargv
, uargv32
);
707 nilfs_compat_ioctl_change_cpmode(struct inode
*inode
, struct file
*filp
,
708 unsigned int cmd
, unsigned long arg
)
710 struct nilfs_cpmode __user
*ucpmode
;
711 struct nilfs_cpmode32 __user
*ucpmode32
;
714 ucpmode
= compat_alloc_user_space(sizeof(struct nilfs_cpmode
));
715 ucpmode32
= compat_ptr(arg
);
716 if (copy_in_user(&ucpmode
->cm_cno
, &ucpmode32
->cm_cno
,
718 get_user(mode
, &ucpmode32
->cm_mode
) ||
719 put_user(mode
, &ucpmode
->cm_mode
))
722 return nilfs_compat_locked_ioctl(
723 inode
, filp
, cmd
, (unsigned long)ucpmode
);
728 nilfs_compat_ioctl_delete_checkpoint(struct inode
*inode
, struct file
*filp
,
729 unsigned int cmd
, unsigned long arg
)
731 return nilfs_compat_locked_ioctl(inode
, filp
, cmd
, arg
);
735 nilfs_compat_ioctl_get_cpinfo(struct inode
*inode
, struct file
*filp
,
736 unsigned int cmd
, unsigned long arg
)
738 return nilfs_compat_ioctl_get_by_argv(inode
, filp
, cmd
, arg
);
742 nilfs_compat_ioctl_get_cpstat(struct inode
*inode
, struct file
*filp
,
743 unsigned int cmd
, unsigned long arg
)
745 return nilfs_compat_locked_ioctl(inode
, filp
, cmd
, arg
);
749 nilfs_compat_ioctl_get_suinfo(struct inode
*inode
, struct file
*filp
,
750 unsigned int cmd
, unsigned long arg
)
752 return nilfs_compat_ioctl_get_by_argv(inode
, filp
, cmd
, arg
);
756 nilfs_compat_ioctl_get_sustat(struct inode
*inode
, struct file
*filp
,
757 unsigned int cmd
, unsigned long arg
)
759 struct nilfs_sustat __user
*usustat
;
760 struct nilfs_sustat32 __user
*usustat32
;
761 time_t ctime
, nongc_ctime
;
764 usustat
= compat_alloc_user_space(sizeof(struct nilfs_sustat
));
765 ret
= nilfs_compat_locked_ioctl(inode
, filp
, cmd
,
766 (unsigned long)usustat
);
770 usustat32
= compat_ptr(arg
);
771 if (copy_in_user(&usustat32
->ss_nsegs
, &usustat
->ss_nsegs
,
773 copy_in_user(&usustat32
->ss_ncleansegs
, &usustat
->ss_ncleansegs
,
775 copy_in_user(&usustat32
->ss_ndirtysegs
, &usustat
->ss_ndirtysegs
,
777 get_user(ctime
, &usustat
->ss_ctime
) ||
778 put_user(ctime
, &usustat32
->ss_ctime
) ||
779 get_user(nongc_ctime
, &usustat
->ss_nongc_ctime
) ||
780 put_user(nongc_ctime
, &usustat32
->ss_nongc_ctime
))
786 nilfs_compat_ioctl_get_vinfo(struct inode
*inode
, struct file
*filp
,
787 unsigned int cmd
, unsigned long arg
)
789 return nilfs_compat_ioctl_get_by_argv(inode
, filp
, cmd
, arg
);
793 nilfs_compat_ioctl_get_bdescs(struct inode
*inode
, struct file
*filp
,
794 unsigned int cmd
, unsigned long arg
)
796 return nilfs_compat_ioctl_get_by_argv(inode
, filp
, cmd
, arg
);
800 nilfs_compat_ioctl_clean_segments(struct inode
*inode
, struct file
*filp
,
801 unsigned int cmd
, unsigned long arg
)
803 struct nilfs_argv __user
*uargv
;
804 struct nilfs_argv32 __user
*uargv32
;
807 uargv
= compat_alloc_user_space(sizeof(struct nilfs_argv
) * 5);
808 uargv32
= compat_ptr(arg
);
809 for (i
= 0; i
< 5; i
++) {
810 ret
= nilfs_compat_ioctl_uargv32_to_uargv(&uargv32
[i
],
815 return nilfs_compat_locked_ioctl(
816 inode
, filp
, cmd
, (unsigned long)uargv
);
819 static int nilfs_compat_ioctl_sync(struct inode
*inode
, struct file
*filp
,
820 unsigned int cmd
, unsigned long arg
)
822 return nilfs_compat_locked_ioctl(inode
, filp
, cmd
, arg
);
825 long nilfs_compat_ioctl(struct file
*filp
, unsigned int cmd
, unsigned long arg
)
827 struct inode
*inode
= filp
->f_dentry
->d_inode
;
830 case NILFS_IOCTL32_CHANGE_CPMODE
:
831 return nilfs_compat_ioctl_change_cpmode(
832 inode
, filp
, NILFS_IOCTL_CHANGE_CPMODE
, arg
);
833 case NILFS_IOCTL_DELETE_CHECKPOINT
:
834 return nilfs_compat_ioctl_delete_checkpoint(
835 inode
, filp
, cmd
, arg
);
836 case NILFS_IOCTL32_GET_CPINFO
:
837 return nilfs_compat_ioctl_get_cpinfo(
838 inode
, filp
, NILFS_IOCTL_GET_CPINFO
, arg
);
839 case NILFS_IOCTL_GET_CPSTAT
:
840 return nilfs_compat_ioctl_get_cpstat(inode
, filp
, cmd
, arg
);
841 case NILFS_IOCTL32_GET_SUINFO
:
842 return nilfs_compat_ioctl_get_suinfo(
843 inode
, filp
, NILFS_IOCTL_GET_SUINFO
, arg
);
844 case NILFS_IOCTL32_GET_SUSTAT
:
845 return nilfs_compat_ioctl_get_sustat(
846 inode
, filp
, NILFS_IOCTL_GET_SUSTAT
, arg
);
847 case NILFS_IOCTL32_GET_VINFO
:
848 return nilfs_compat_ioctl_get_vinfo(
849 inode
, filp
, NILFS_IOCTL_GET_VINFO
, arg
);
850 case NILFS_IOCTL32_GET_BDESCS
:
851 return nilfs_compat_ioctl_get_bdescs(
852 inode
, filp
, NILFS_IOCTL_GET_BDESCS
, arg
);
853 case NILFS_IOCTL32_CLEAN_SEGMENTS
:
854 return nilfs_compat_ioctl_clean_segments(
855 inode
, filp
, NILFS_IOCTL_CLEAN_SEGMENTS
, arg
);
856 case NILFS_IOCTL_SYNC
:
857 return nilfs_compat_ioctl_sync(inode
, filp
, cmd
, arg
);