17942b919SKoji Sato /* 27942b919SKoji Sato * ioctl.c - NILFS ioctl operations. 37942b919SKoji Sato * 47942b919SKoji Sato * Copyright (C) 2007, 2008 Nippon Telegraph and Telephone Corporation. 57942b919SKoji Sato * 67942b919SKoji Sato * This program is free software; you can redistribute it and/or modify 77942b919SKoji Sato * it under the terms of the GNU General Public License as published by 87942b919SKoji Sato * the Free Software Foundation; either version 2 of the License, or 97942b919SKoji Sato * (at your option) any later version. 107942b919SKoji Sato * 117942b919SKoji Sato * This program is distributed in the hope that it will be useful, 127942b919SKoji Sato * but WITHOUT ANY WARRANTY; without even the implied warranty of 137942b919SKoji Sato * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 147942b919SKoji Sato * GNU General Public License for more details. 157942b919SKoji Sato * 167942b919SKoji Sato * You should have received a copy of the GNU General Public License 177942b919SKoji Sato * along with this program; if not, write to the Free Software 187942b919SKoji Sato * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 197942b919SKoji Sato * 207942b919SKoji Sato * Written by Koji Sato <koji@osrg.net>. 217942b919SKoji Sato */ 227942b919SKoji Sato 237942b919SKoji Sato #include <linux/fs.h> 247942b919SKoji Sato #include <linux/wait.h> 255a0e3ad6STejun Heo #include <linux/slab.h> 267942b919SKoji Sato #include <linux/capability.h> /* capable() */ 277942b919SKoji Sato #include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */ 284f6b8288SRyusuke Konishi #include <linux/vmalloc.h> 297512487eSRyusuke Konishi #include <linux/mount.h> /* mnt_want_write(), mnt_drop_write() */ 307942b919SKoji Sato #include <linux/nilfs2_fs.h> 317942b919SKoji Sato #include "nilfs.h" 327942b919SKoji Sato #include "segment.h" 337942b919SKoji Sato #include "bmap.h" 347942b919SKoji Sato #include "cpfile.h" 357942b919SKoji Sato #include "sufile.h" 367942b919SKoji Sato #include "dat.h" 377942b919SKoji Sato 387942b919SKoji Sato 397942b919SKoji Sato static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, 407942b919SKoji Sato struct nilfs_argv *argv, int dir, 417942b919SKoji Sato ssize_t (*dofunc)(struct the_nilfs *, 42b028fcfcSRyusuke Konishi __u64 *, int, 437942b919SKoji Sato void *, size_t, size_t)) 447942b919SKoji Sato { 457942b919SKoji Sato void *buf; 46dc498d09SRyusuke Konishi void __user *base = (void __user *)(unsigned long)argv->v_base; 473358b4aaSRyusuke Konishi size_t maxmembs, total, n; 487942b919SKoji Sato ssize_t nr; 497942b919SKoji Sato int ret, i; 50b028fcfcSRyusuke Konishi __u64 pos, ppos; 517942b919SKoji Sato 527942b919SKoji Sato if (argv->v_nmembs == 0) 537942b919SKoji Sato return 0; 547942b919SKoji Sato 553358b4aaSRyusuke Konishi if (argv->v_size > PAGE_SIZE) 563358b4aaSRyusuke Konishi return -EINVAL; 573358b4aaSRyusuke Konishi 583358b4aaSRyusuke Konishi buf = (void *)__get_free_pages(GFP_NOFS, 0); 593358b4aaSRyusuke Konishi if (unlikely(!buf)) 607942b919SKoji Sato return -ENOMEM; 613358b4aaSRyusuke Konishi maxmembs = PAGE_SIZE / argv->v_size; 627942b919SKoji Sato 637942b919SKoji Sato ret = 0; 647942b919SKoji Sato total = 0; 65b028fcfcSRyusuke Konishi pos = argv->v_index; 667942b919SKoji Sato for (i = 0; i < argv->v_nmembs; i += n) { 677942b919SKoji Sato n = (argv->v_nmembs - i < maxmembs) ? 687942b919SKoji Sato argv->v_nmembs - i : maxmembs; 697942b919SKoji Sato if ((dir & _IOC_WRITE) && 70dc498d09SRyusuke Konishi copy_from_user(buf, base + argv->v_size * i, 717942b919SKoji Sato argv->v_size * n)) { 727942b919SKoji Sato ret = -EFAULT; 737942b919SKoji Sato break; 747942b919SKoji Sato } 75b028fcfcSRyusuke Konishi ppos = pos; 768acfbf09SPekka Enberg nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size, 77b028fcfcSRyusuke Konishi n); 787942b919SKoji Sato if (nr < 0) { 797942b919SKoji Sato ret = nr; 807942b919SKoji Sato break; 817942b919SKoji Sato } 827942b919SKoji Sato if ((dir & _IOC_READ) && 83dc498d09SRyusuke Konishi copy_to_user(base + argv->v_size * i, buf, 84dc498d09SRyusuke Konishi argv->v_size * nr)) { 857942b919SKoji Sato ret = -EFAULT; 867942b919SKoji Sato break; 877942b919SKoji Sato } 887942b919SKoji Sato total += nr; 89b028fcfcSRyusuke Konishi if ((size_t)nr < n) 90b028fcfcSRyusuke Konishi break; 91b028fcfcSRyusuke Konishi if (pos == ppos) 92b028fcfcSRyusuke Konishi pos += n; 937942b919SKoji Sato } 947942b919SKoji Sato argv->v_nmembs = total; 957942b919SKoji Sato 963358b4aaSRyusuke Konishi free_pages((unsigned long)buf, 0); 977942b919SKoji Sato return ret; 987942b919SKoji Sato } 997942b919SKoji Sato 100cde98f0fSRyusuke Konishi static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp) 101cde98f0fSRyusuke Konishi { 102cde98f0fSRyusuke Konishi unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE; 103cde98f0fSRyusuke Konishi 104cde98f0fSRyusuke Konishi return put_user(flags, (int __user *)argp); 105cde98f0fSRyusuke Konishi } 106cde98f0fSRyusuke Konishi 107cde98f0fSRyusuke Konishi static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp, 108cde98f0fSRyusuke Konishi void __user *argp) 109cde98f0fSRyusuke Konishi { 110cde98f0fSRyusuke Konishi struct nilfs_transaction_info ti; 111cde98f0fSRyusuke Konishi unsigned int flags, oldflags; 112cde98f0fSRyusuke Konishi int ret; 113cde98f0fSRyusuke Konishi 114cde98f0fSRyusuke Konishi if (!is_owner_or_cap(inode)) 115cde98f0fSRyusuke Konishi return -EACCES; 116cde98f0fSRyusuke Konishi 117cde98f0fSRyusuke Konishi if (get_user(flags, (int __user *)argp)) 118cde98f0fSRyusuke Konishi return -EFAULT; 119cde98f0fSRyusuke Konishi 120cde98f0fSRyusuke Konishi ret = mnt_want_write(filp->f_path.mnt); 121cde98f0fSRyusuke Konishi if (ret) 122cde98f0fSRyusuke Konishi return ret; 123cde98f0fSRyusuke Konishi 124cde98f0fSRyusuke Konishi flags = nilfs_mask_flags(inode->i_mode, flags); 125cde98f0fSRyusuke Konishi 126cde98f0fSRyusuke Konishi mutex_lock(&inode->i_mutex); 127cde98f0fSRyusuke Konishi 128cde98f0fSRyusuke Konishi oldflags = NILFS_I(inode)->i_flags; 129cde98f0fSRyusuke Konishi 130cde98f0fSRyusuke Konishi /* 131cde98f0fSRyusuke Konishi * The IMMUTABLE and APPEND_ONLY flags can only be changed by the 132cde98f0fSRyusuke Konishi * relevant capability. 133cde98f0fSRyusuke Konishi */ 134cde98f0fSRyusuke Konishi ret = -EPERM; 135cde98f0fSRyusuke Konishi if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) && 136cde98f0fSRyusuke Konishi !capable(CAP_LINUX_IMMUTABLE)) 137cde98f0fSRyusuke Konishi goto out; 138cde98f0fSRyusuke Konishi 139cde98f0fSRyusuke Konishi ret = nilfs_transaction_begin(inode->i_sb, &ti, 0); 140cde98f0fSRyusuke Konishi if (ret) 141cde98f0fSRyusuke Konishi goto out; 142cde98f0fSRyusuke Konishi 143cde98f0fSRyusuke Konishi NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) | 144cde98f0fSRyusuke Konishi (flags & FS_FL_USER_MODIFIABLE); 145cde98f0fSRyusuke Konishi 146cde98f0fSRyusuke Konishi nilfs_set_inode_flags(inode); 147cde98f0fSRyusuke Konishi inode->i_ctime = CURRENT_TIME; 148cde98f0fSRyusuke Konishi if (IS_SYNC(inode)) 149cde98f0fSRyusuke Konishi nilfs_set_transaction_flag(NILFS_TI_SYNC); 150cde98f0fSRyusuke Konishi 151cde98f0fSRyusuke Konishi nilfs_mark_inode_dirty(inode); 152cde98f0fSRyusuke Konishi ret = nilfs_transaction_commit(inode->i_sb); 153cde98f0fSRyusuke Konishi out: 154cde98f0fSRyusuke Konishi mutex_unlock(&inode->i_mutex); 155cde98f0fSRyusuke Konishi mnt_drop_write(filp->f_path.mnt); 156cde98f0fSRyusuke Konishi return ret; 157cde98f0fSRyusuke Konishi } 158cde98f0fSRyusuke Konishi 159cde98f0fSRyusuke Konishi static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp) 160cde98f0fSRyusuke Konishi { 161cde98f0fSRyusuke Konishi return put_user(inode->i_generation, (int __user *)argp); 162cde98f0fSRyusuke Konishi } 163cde98f0fSRyusuke Konishi 1647942b919SKoji Sato static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, 1657942b919SKoji Sato unsigned int cmd, void __user *argp) 1667942b919SKoji Sato { 167c1ea985cSRyusuke Konishi struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 168c1ea985cSRyusuke Konishi struct inode *cpfile = nilfs->ns_cpfile; 1697942b919SKoji Sato struct nilfs_transaction_info ti; 1707942b919SKoji Sato struct nilfs_cpmode cpmode; 1717942b919SKoji Sato int ret; 1727942b919SKoji Sato 1737942b919SKoji Sato if (!capable(CAP_SYS_ADMIN)) 1747942b919SKoji Sato return -EPERM; 1757512487eSRyusuke Konishi 1767512487eSRyusuke Konishi ret = mnt_want_write(filp->f_path.mnt); 1777512487eSRyusuke Konishi if (ret) 1787512487eSRyusuke Konishi return ret; 1797512487eSRyusuke Konishi 1807512487eSRyusuke Konishi ret = -EFAULT; 1817942b919SKoji Sato if (copy_from_user(&cpmode, argp, sizeof(cpmode))) 1827512487eSRyusuke Konishi goto out; 1837942b919SKoji Sato 184348fe8daSRyusuke Konishi down_read(&inode->i_sb->s_umount); 1857512487eSRyusuke Konishi 1867942b919SKoji Sato nilfs_transaction_begin(inode->i_sb, &ti, 0); 1877942b919SKoji Sato ret = nilfs_cpfile_change_cpmode( 1887942b919SKoji Sato cpfile, cpmode.cm_cno, cpmode.cm_mode); 1897512487eSRyusuke Konishi if (unlikely(ret < 0)) 19047420c79SRyusuke Konishi nilfs_transaction_abort(inode->i_sb); 1917512487eSRyusuke Konishi else 19247420c79SRyusuke Konishi nilfs_transaction_commit(inode->i_sb); /* never fails */ 1937512487eSRyusuke Konishi 194348fe8daSRyusuke Konishi up_read(&inode->i_sb->s_umount); 1957512487eSRyusuke Konishi out: 1967512487eSRyusuke Konishi mnt_drop_write(filp->f_path.mnt); 1977942b919SKoji Sato return ret; 1987942b919SKoji Sato } 1997942b919SKoji Sato 2007942b919SKoji Sato static int 2017942b919SKoji Sato nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp, 2027942b919SKoji Sato unsigned int cmd, void __user *argp) 2037942b919SKoji Sato { 2047942b919SKoji Sato struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile; 2057942b919SKoji Sato struct nilfs_transaction_info ti; 2067942b919SKoji Sato __u64 cno; 2077942b919SKoji Sato int ret; 2087942b919SKoji Sato 2097942b919SKoji Sato if (!capable(CAP_SYS_ADMIN)) 2107942b919SKoji Sato return -EPERM; 2117512487eSRyusuke Konishi 2127512487eSRyusuke Konishi ret = mnt_want_write(filp->f_path.mnt); 2137512487eSRyusuke Konishi if (ret) 2147512487eSRyusuke Konishi return ret; 2157512487eSRyusuke Konishi 2167512487eSRyusuke Konishi ret = -EFAULT; 2177942b919SKoji Sato if (copy_from_user(&cno, argp, sizeof(cno))) 2187512487eSRyusuke Konishi goto out; 2197942b919SKoji Sato 2207942b919SKoji Sato nilfs_transaction_begin(inode->i_sb, &ti, 0); 2217942b919SKoji Sato ret = nilfs_cpfile_delete_checkpoint(cpfile, cno); 2227512487eSRyusuke Konishi if (unlikely(ret < 0)) 22347420c79SRyusuke Konishi nilfs_transaction_abort(inode->i_sb); 2247512487eSRyusuke Konishi else 22547420c79SRyusuke Konishi nilfs_transaction_commit(inode->i_sb); /* never fails */ 2267512487eSRyusuke Konishi out: 2277512487eSRyusuke Konishi mnt_drop_write(filp->f_path.mnt); 2287942b919SKoji Sato return ret; 2297942b919SKoji Sato } 2307942b919SKoji Sato 2317942b919SKoji Sato static ssize_t 232b028fcfcSRyusuke Konishi nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, 2337942b919SKoji Sato void *buf, size_t size, size_t nmembs) 2347942b919SKoji Sato { 2357942b919SKoji Sato int ret; 2367942b919SKoji Sato 23747420c79SRyusuke Konishi down_read(&nilfs->ns_segctor_sem); 23847eb6b9cSRyusuke Konishi ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf, 239003ff182SRyusuke Konishi size, nmembs); 24047420c79SRyusuke Konishi up_read(&nilfs->ns_segctor_sem); 2417942b919SKoji Sato return ret; 2427942b919SKoji Sato } 2437942b919SKoji Sato 2447942b919SKoji Sato static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp, 2457942b919SKoji Sato unsigned int cmd, void __user *argp) 2467942b919SKoji Sato { 24747420c79SRyusuke Konishi struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 2487942b919SKoji Sato struct nilfs_cpstat cpstat; 2497942b919SKoji Sato int ret; 2507942b919SKoji Sato 25147420c79SRyusuke Konishi down_read(&nilfs->ns_segctor_sem); 25247420c79SRyusuke Konishi ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat); 25347420c79SRyusuke Konishi up_read(&nilfs->ns_segctor_sem); 2547942b919SKoji Sato if (ret < 0) 2557942b919SKoji Sato return ret; 2567942b919SKoji Sato 2577942b919SKoji Sato if (copy_to_user(argp, &cpstat, sizeof(cpstat))) 2587942b919SKoji Sato ret = -EFAULT; 2597942b919SKoji Sato return ret; 2607942b919SKoji Sato } 2617942b919SKoji Sato 2627942b919SKoji Sato static ssize_t 263b028fcfcSRyusuke Konishi nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, 2647942b919SKoji Sato void *buf, size_t size, size_t nmembs) 2657942b919SKoji Sato { 2667942b919SKoji Sato int ret; 2677942b919SKoji Sato 26847420c79SRyusuke Konishi down_read(&nilfs->ns_segctor_sem); 269003ff182SRyusuke Konishi ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size, 270003ff182SRyusuke Konishi nmembs); 27147420c79SRyusuke Konishi up_read(&nilfs->ns_segctor_sem); 2727942b919SKoji Sato return ret; 2737942b919SKoji Sato } 2747942b919SKoji Sato 2757942b919SKoji Sato static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp, 2767942b919SKoji Sato unsigned int cmd, void __user *argp) 2777942b919SKoji Sato { 27847420c79SRyusuke Konishi struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 2797942b919SKoji Sato struct nilfs_sustat sustat; 2807942b919SKoji Sato int ret; 2817942b919SKoji Sato 28247420c79SRyusuke Konishi down_read(&nilfs->ns_segctor_sem); 28347420c79SRyusuke Konishi ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat); 28447420c79SRyusuke Konishi up_read(&nilfs->ns_segctor_sem); 2857942b919SKoji Sato if (ret < 0) 2867942b919SKoji Sato return ret; 2877942b919SKoji Sato 2887942b919SKoji Sato if (copy_to_user(argp, &sustat, sizeof(sustat))) 2897942b919SKoji Sato ret = -EFAULT; 2907942b919SKoji Sato return ret; 2917942b919SKoji Sato } 2927942b919SKoji Sato 2937942b919SKoji Sato static ssize_t 294b028fcfcSRyusuke Konishi nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags, 2957942b919SKoji Sato void *buf, size_t size, size_t nmembs) 2967942b919SKoji Sato { 2977942b919SKoji Sato int ret; 2987942b919SKoji Sato 29947420c79SRyusuke Konishi down_read(&nilfs->ns_segctor_sem); 300365e215cSRyusuke Konishi ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs); 30147420c79SRyusuke Konishi up_read(&nilfs->ns_segctor_sem); 3027942b919SKoji Sato return ret; 3037942b919SKoji Sato } 3047942b919SKoji Sato 3057942b919SKoji Sato static ssize_t 306b028fcfcSRyusuke Konishi nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags, 3077942b919SKoji Sato void *buf, size_t size, size_t nmembs) 3087942b919SKoji Sato { 309365e215cSRyusuke Konishi struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap; 3107942b919SKoji Sato struct nilfs_bdesc *bdescs = buf; 3117942b919SKoji Sato int ret, i; 3127942b919SKoji Sato 31347eb6b9cSRyusuke Konishi down_read(&nilfs->ns_segctor_sem); 3147942b919SKoji Sato for (i = 0; i < nmembs; i++) { 3157942b919SKoji Sato ret = nilfs_bmap_lookup_at_level(bmap, 3167942b919SKoji Sato bdescs[i].bd_offset, 3177942b919SKoji Sato bdescs[i].bd_level + 1, 3187942b919SKoji Sato &bdescs[i].bd_blocknr); 3197942b919SKoji Sato if (ret < 0) { 32047eb6b9cSRyusuke Konishi if (ret != -ENOENT) { 32147eb6b9cSRyusuke Konishi up_read(&nilfs->ns_segctor_sem); 3227942b919SKoji Sato return ret; 32347eb6b9cSRyusuke Konishi } 3247942b919SKoji Sato bdescs[i].bd_blocknr = 0; 3257942b919SKoji Sato } 3267942b919SKoji Sato } 32747eb6b9cSRyusuke Konishi up_read(&nilfs->ns_segctor_sem); 3287942b919SKoji Sato return nmembs; 3297942b919SKoji Sato } 3307942b919SKoji Sato 3317942b919SKoji Sato static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp, 3327942b919SKoji Sato unsigned int cmd, void __user *argp) 3337942b919SKoji Sato { 3347942b919SKoji Sato struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 3357942b919SKoji Sato struct nilfs_argv argv; 3367942b919SKoji Sato int ret; 3377942b919SKoji Sato 3387942b919SKoji Sato if (copy_from_user(&argv, argp, sizeof(argv))) 3397942b919SKoji Sato return -EFAULT; 3407942b919SKoji Sato 34183aca8f4SRyusuke Konishi if (argv.v_size != sizeof(struct nilfs_bdesc)) 34283aca8f4SRyusuke Konishi return -EINVAL; 34383aca8f4SRyusuke Konishi 3447942b919SKoji Sato ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), 3457942b919SKoji Sato nilfs_ioctl_do_get_bdescs); 34647420c79SRyusuke Konishi if (ret < 0) 34747420c79SRyusuke Konishi return ret; 3487942b919SKoji Sato 3497942b919SKoji Sato if (copy_to_user(argp, &argv, sizeof(argv))) 3507942b919SKoji Sato ret = -EFAULT; 3517942b919SKoji Sato return ret; 3527942b919SKoji Sato } 3537942b919SKoji Sato 3547942b919SKoji Sato static int nilfs_ioctl_move_inode_block(struct inode *inode, 3557942b919SKoji Sato struct nilfs_vdesc *vdesc, 3567942b919SKoji Sato struct list_head *buffers) 3577942b919SKoji Sato { 3587942b919SKoji Sato struct buffer_head *bh; 3597942b919SKoji Sato int ret; 3607942b919SKoji Sato 3617942b919SKoji Sato if (vdesc->vd_flags == 0) 3627942b919SKoji Sato ret = nilfs_gccache_submit_read_data( 3637942b919SKoji Sato inode, vdesc->vd_offset, vdesc->vd_blocknr, 3647942b919SKoji Sato vdesc->vd_vblocknr, &bh); 3657942b919SKoji Sato else 3667942b919SKoji Sato ret = nilfs_gccache_submit_read_node( 3677942b919SKoji Sato inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh); 3687942b919SKoji Sato 3697942b919SKoji Sato if (unlikely(ret < 0)) { 3707942b919SKoji Sato if (ret == -ENOENT) 3717942b919SKoji Sato printk(KERN_CRIT 3727942b919SKoji Sato "%s: invalid virtual block address (%s): " 3737942b919SKoji Sato "ino=%llu, cno=%llu, offset=%llu, " 3747942b919SKoji Sato "blocknr=%llu, vblocknr=%llu\n", 3757942b919SKoji Sato __func__, vdesc->vd_flags ? "node" : "data", 3767942b919SKoji Sato (unsigned long long)vdesc->vd_ino, 3777942b919SKoji Sato (unsigned long long)vdesc->vd_cno, 3787942b919SKoji Sato (unsigned long long)vdesc->vd_offset, 3797942b919SKoji Sato (unsigned long long)vdesc->vd_blocknr, 3807942b919SKoji Sato (unsigned long long)vdesc->vd_vblocknr); 3817942b919SKoji Sato return ret; 3827942b919SKoji Sato } 3835399dd1fSRyusuke Konishi if (unlikely(!list_empty(&bh->b_assoc_buffers))) { 3845399dd1fSRyusuke Konishi printk(KERN_CRIT "%s: conflicting %s buffer: ino=%llu, " 3855399dd1fSRyusuke Konishi "cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu\n", 3865399dd1fSRyusuke Konishi __func__, vdesc->vd_flags ? "node" : "data", 3875399dd1fSRyusuke Konishi (unsigned long long)vdesc->vd_ino, 3885399dd1fSRyusuke Konishi (unsigned long long)vdesc->vd_cno, 3895399dd1fSRyusuke Konishi (unsigned long long)vdesc->vd_offset, 3905399dd1fSRyusuke Konishi (unsigned long long)vdesc->vd_blocknr, 3915399dd1fSRyusuke Konishi (unsigned long long)vdesc->vd_vblocknr); 3925399dd1fSRyusuke Konishi brelse(bh); 3935399dd1fSRyusuke Konishi return -EEXIST; 3945399dd1fSRyusuke Konishi } 3957942b919SKoji Sato list_add_tail(&bh->b_assoc_buffers, buffers); 3967942b919SKoji Sato return 0; 3977942b919SKoji Sato } 3987942b919SKoji Sato 399263d90ceSRyusuke Konishi static int nilfs_ioctl_move_blocks(struct super_block *sb, 4004f6b8288SRyusuke Konishi struct nilfs_argv *argv, void *buf) 4017942b919SKoji Sato { 4024f6b8288SRyusuke Konishi size_t nmembs = argv->v_nmembs; 403947b10aeSRyusuke Konishi struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs; 4047942b919SKoji Sato struct inode *inode; 4057942b919SKoji Sato struct nilfs_vdesc *vdesc; 4067942b919SKoji Sato struct buffer_head *bh, *n; 4077942b919SKoji Sato LIST_HEAD(buffers); 4087942b919SKoji Sato ino_t ino; 4097942b919SKoji Sato __u64 cno; 4107942b919SKoji Sato int i, ret; 4117942b919SKoji Sato 4127942b919SKoji Sato for (i = 0, vdesc = buf; i < nmembs; ) { 4137942b919SKoji Sato ino = vdesc->vd_ino; 4147942b919SKoji Sato cno = vdesc->vd_cno; 415263d90ceSRyusuke Konishi inode = nilfs_iget_for_gc(sb, ino, cno); 416103cfcf5SDan Carpenter if (IS_ERR(inode)) { 417103cfcf5SDan Carpenter ret = PTR_ERR(inode); 4187942b919SKoji Sato goto failed; 4197942b919SKoji Sato } 420947b10aeSRyusuke Konishi if (list_empty(&NILFS_I(inode)->i_dirty)) { 421947b10aeSRyusuke Konishi /* 422947b10aeSRyusuke Konishi * Add the inode to GC inode list. Garbage Collection 423947b10aeSRyusuke Konishi * is serialized and no two processes manipulate the 424947b10aeSRyusuke Konishi * list simultaneously. 425947b10aeSRyusuke Konishi */ 426947b10aeSRyusuke Konishi igrab(inode); 427947b10aeSRyusuke Konishi list_add(&NILFS_I(inode)->i_dirty, 428947b10aeSRyusuke Konishi &nilfs->ns_gc_inodes); 429947b10aeSRyusuke Konishi } 430947b10aeSRyusuke Konishi 4317942b919SKoji Sato do { 4327942b919SKoji Sato ret = nilfs_ioctl_move_inode_block(inode, vdesc, 4337942b919SKoji Sato &buffers); 434263d90ceSRyusuke Konishi if (unlikely(ret < 0)) { 435263d90ceSRyusuke Konishi iput(inode); 4367942b919SKoji Sato goto failed; 437263d90ceSRyusuke Konishi } 4387942b919SKoji Sato vdesc++; 4397942b919SKoji Sato } while (++i < nmembs && 4407942b919SKoji Sato vdesc->vd_ino == ino && vdesc->vd_cno == cno); 441263d90ceSRyusuke Konishi 442263d90ceSRyusuke Konishi iput(inode); /* The inode still remains in GC inode list */ 4437942b919SKoji Sato } 4447942b919SKoji Sato 4457942b919SKoji Sato list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { 4467942b919SKoji Sato ret = nilfs_gccache_wait_and_mark_dirty(bh); 4477942b919SKoji Sato if (unlikely(ret < 0)) { 4485399dd1fSRyusuke Konishi WARN_ON(ret == -EEXIST); 4497942b919SKoji Sato goto failed; 4507942b919SKoji Sato } 4517942b919SKoji Sato list_del_init(&bh->b_assoc_buffers); 4527942b919SKoji Sato brelse(bh); 4537942b919SKoji Sato } 4547942b919SKoji Sato return nmembs; 4557942b919SKoji Sato 4567942b919SKoji Sato failed: 4577942b919SKoji Sato list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) { 4587942b919SKoji Sato list_del_init(&bh->b_assoc_buffers); 4597942b919SKoji Sato brelse(bh); 4607942b919SKoji Sato } 4617942b919SKoji Sato return ret; 4627942b919SKoji Sato } 4637942b919SKoji Sato 4644f6b8288SRyusuke Konishi static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs, 4654f6b8288SRyusuke Konishi struct nilfs_argv *argv, void *buf) 4667942b919SKoji Sato { 4674f6b8288SRyusuke Konishi size_t nmembs = argv->v_nmembs; 4687942b919SKoji Sato struct inode *cpfile = nilfs->ns_cpfile; 4697942b919SKoji Sato struct nilfs_period *periods = buf; 4707942b919SKoji Sato int ret, i; 4717942b919SKoji Sato 4727942b919SKoji Sato for (i = 0; i < nmembs; i++) { 4737942b919SKoji Sato ret = nilfs_cpfile_delete_checkpoints( 4747942b919SKoji Sato cpfile, periods[i].p_start, periods[i].p_end); 4757942b919SKoji Sato if (ret < 0) 4767942b919SKoji Sato return ret; 4777942b919SKoji Sato } 4787942b919SKoji Sato return nmembs; 4797942b919SKoji Sato } 4807942b919SKoji Sato 4814f6b8288SRyusuke Konishi static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs, 4824f6b8288SRyusuke Konishi struct nilfs_argv *argv, void *buf) 4837942b919SKoji Sato { 4844f6b8288SRyusuke Konishi size_t nmembs = argv->v_nmembs; 4854f6b8288SRyusuke Konishi int ret; 4867942b919SKoji Sato 487365e215cSRyusuke Konishi ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs); 4887942b919SKoji Sato 4897942b919SKoji Sato return (ret < 0) ? ret : nmembs; 4907942b919SKoji Sato } 4917942b919SKoji Sato 4924f6b8288SRyusuke Konishi static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs, 4934f6b8288SRyusuke Konishi struct nilfs_argv *argv, void *buf) 4947942b919SKoji Sato { 4954f6b8288SRyusuke Konishi size_t nmembs = argv->v_nmembs; 496365e215cSRyusuke Konishi struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap; 4977942b919SKoji Sato struct nilfs_bdesc *bdescs = buf; 4987942b919SKoji Sato int ret, i; 4997942b919SKoji Sato 5007942b919SKoji Sato for (i = 0; i < nmembs; i++) { 5017942b919SKoji Sato /* XXX: use macro or inline func to check liveness */ 5027942b919SKoji Sato ret = nilfs_bmap_lookup_at_level(bmap, 5037942b919SKoji Sato bdescs[i].bd_offset, 5047942b919SKoji Sato bdescs[i].bd_level + 1, 5057942b919SKoji Sato &bdescs[i].bd_blocknr); 5067942b919SKoji Sato if (ret < 0) { 5077942b919SKoji Sato if (ret != -ENOENT) 5087942b919SKoji Sato return ret; 5097942b919SKoji Sato bdescs[i].bd_blocknr = 0; 5107942b919SKoji Sato } 5117942b919SKoji Sato if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr) 5127942b919SKoji Sato /* skip dead block */ 5137942b919SKoji Sato continue; 5147942b919SKoji Sato if (bdescs[i].bd_level == 0) { 515365e215cSRyusuke Konishi ret = nilfs_mdt_mark_block_dirty(nilfs->ns_dat, 5167942b919SKoji Sato bdescs[i].bd_offset); 5177942b919SKoji Sato if (ret < 0) { 5181f5abe7eSRyusuke Konishi WARN_ON(ret == -ENOENT); 5197942b919SKoji Sato return ret; 5207942b919SKoji Sato } 5217942b919SKoji Sato } else { 5227942b919SKoji Sato ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset, 5237942b919SKoji Sato bdescs[i].bd_level); 5247942b919SKoji Sato if (ret < 0) { 5251f5abe7eSRyusuke Konishi WARN_ON(ret == -ENOENT); 5267942b919SKoji Sato return ret; 5277942b919SKoji Sato } 5287942b919SKoji Sato } 5297942b919SKoji Sato } 5307942b919SKoji Sato return nmembs; 5317942b919SKoji Sato } 5327942b919SKoji Sato 5337942b919SKoji Sato int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, 5344f6b8288SRyusuke Konishi struct nilfs_argv *argv, void **kbufs) 5357942b919SKoji Sato { 5361f5abe7eSRyusuke Konishi const char *msg; 5374f6b8288SRyusuke Konishi int ret; 5387942b919SKoji Sato 5394f6b8288SRyusuke Konishi ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]); 5401f5abe7eSRyusuke Konishi if (ret < 0) { 5411f5abe7eSRyusuke Konishi /* 5421f5abe7eSRyusuke Konishi * can safely abort because checkpoints can be removed 5431f5abe7eSRyusuke Konishi * independently. 5441f5abe7eSRyusuke Konishi */ 5451f5abe7eSRyusuke Konishi msg = "cannot delete checkpoints"; 5461f5abe7eSRyusuke Konishi goto failed; 5471f5abe7eSRyusuke Konishi } 5484f6b8288SRyusuke Konishi ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]); 5491f5abe7eSRyusuke Konishi if (ret < 0) { 5501f5abe7eSRyusuke Konishi /* 5511f5abe7eSRyusuke Konishi * can safely abort because DAT file is updated atomically 5521f5abe7eSRyusuke Konishi * using a copy-on-write technique. 5531f5abe7eSRyusuke Konishi */ 5541f5abe7eSRyusuke Konishi msg = "cannot delete virtual blocks from DAT file"; 5551f5abe7eSRyusuke Konishi goto failed; 5561f5abe7eSRyusuke Konishi } 5574f6b8288SRyusuke Konishi ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]); 5581f5abe7eSRyusuke Konishi if (ret < 0) { 5591f5abe7eSRyusuke Konishi /* 5601f5abe7eSRyusuke Konishi * can safely abort because the operation is nondestructive. 5611f5abe7eSRyusuke Konishi */ 5621f5abe7eSRyusuke Konishi msg = "cannot mark copying blocks dirty"; 5631f5abe7eSRyusuke Konishi goto failed; 5641f5abe7eSRyusuke Konishi } 5657942b919SKoji Sato return 0; 5667942b919SKoji Sato 5671f5abe7eSRyusuke Konishi failed: 5681f5abe7eSRyusuke Konishi printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n", 5691f5abe7eSRyusuke Konishi msg, ret); 5707942b919SKoji Sato return ret; 5717942b919SKoji Sato } 5727942b919SKoji Sato 5737942b919SKoji Sato static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, 5747942b919SKoji Sato unsigned int cmd, void __user *argp) 5757942b919SKoji Sato { 5764f6b8288SRyusuke Konishi struct nilfs_argv argv[5]; 57733e189bdSTobias Klauser static const size_t argsz[5] = { 5784f6b8288SRyusuke Konishi sizeof(struct nilfs_vdesc), 5794f6b8288SRyusuke Konishi sizeof(struct nilfs_period), 5804f6b8288SRyusuke Konishi sizeof(__u64), 5814f6b8288SRyusuke Konishi sizeof(struct nilfs_bdesc), 5824f6b8288SRyusuke Konishi sizeof(__u64), 5834f6b8288SRyusuke Konishi }; 5844f6b8288SRyusuke Konishi void __user *base; 5854f6b8288SRyusuke Konishi void *kbufs[5]; 5864f6b8288SRyusuke Konishi struct the_nilfs *nilfs; 5874f6b8288SRyusuke Konishi size_t len, nsegs; 5884f6b8288SRyusuke Konishi int n, ret; 5894f6b8288SRyusuke Konishi 5907942b919SKoji Sato if (!capable(CAP_SYS_ADMIN)) 5917942b919SKoji Sato return -EPERM; 5924f6b8288SRyusuke Konishi 5937512487eSRyusuke Konishi ret = mnt_want_write(filp->f_path.mnt); 5947512487eSRyusuke Konishi if (ret) 5957512487eSRyusuke Konishi return ret; 5964f6b8288SRyusuke Konishi 5977512487eSRyusuke Konishi ret = -EFAULT; 5987512487eSRyusuke Konishi if (copy_from_user(argv, argp, sizeof(argv))) 5997512487eSRyusuke Konishi goto out; 6007512487eSRyusuke Konishi 6017512487eSRyusuke Konishi ret = -EINVAL; 6024f6b8288SRyusuke Konishi nsegs = argv[4].v_nmembs; 6034f6b8288SRyusuke Konishi if (argv[4].v_size != argsz[4]) 6047512487eSRyusuke Konishi goto out; 6057512487eSRyusuke Konishi 6064f6b8288SRyusuke Konishi /* 6074f6b8288SRyusuke Konishi * argv[4] points to segment numbers this ioctl cleans. We 6084f6b8288SRyusuke Konishi * use kmalloc() for its buffer because memory used for the 6094f6b8288SRyusuke Konishi * segment numbers is enough small. 6104f6b8288SRyusuke Konishi */ 6114f6b8288SRyusuke Konishi kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base, 6124f6b8288SRyusuke Konishi nsegs * sizeof(__u64)); 6137512487eSRyusuke Konishi if (IS_ERR(kbufs[4])) { 6147512487eSRyusuke Konishi ret = PTR_ERR(kbufs[4]); 6157512487eSRyusuke Konishi goto out; 6167512487eSRyusuke Konishi } 6174f6b8288SRyusuke Konishi nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 6184f6b8288SRyusuke Konishi 6194f6b8288SRyusuke Konishi for (n = 0; n < 4; n++) { 6204f6b8288SRyusuke Konishi ret = -EINVAL; 6214f6b8288SRyusuke Konishi if (argv[n].v_size != argsz[n]) 6224f6b8288SRyusuke Konishi goto out_free; 6234f6b8288SRyusuke Konishi 6244f6b8288SRyusuke Konishi if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment) 6254f6b8288SRyusuke Konishi goto out_free; 6264f6b8288SRyusuke Konishi 6274f6b8288SRyusuke Konishi len = argv[n].v_size * argv[n].v_nmembs; 6284f6b8288SRyusuke Konishi base = (void __user *)(unsigned long)argv[n].v_base; 6294f6b8288SRyusuke Konishi if (len == 0) { 6304f6b8288SRyusuke Konishi kbufs[n] = NULL; 6314f6b8288SRyusuke Konishi continue; 6324f6b8288SRyusuke Konishi } 6334f6b8288SRyusuke Konishi 6344f6b8288SRyusuke Konishi kbufs[n] = vmalloc(len); 6354f6b8288SRyusuke Konishi if (!kbufs[n]) { 6364f6b8288SRyusuke Konishi ret = -ENOMEM; 6374f6b8288SRyusuke Konishi goto out_free; 6384f6b8288SRyusuke Konishi } 6394f6b8288SRyusuke Konishi if (copy_from_user(kbufs[n], base, len)) { 6404f6b8288SRyusuke Konishi ret = -EFAULT; 6414f6b8288SRyusuke Konishi vfree(kbufs[n]); 6424f6b8288SRyusuke Konishi goto out_free; 6434f6b8288SRyusuke Konishi } 6444f6b8288SRyusuke Konishi } 6454f6b8288SRyusuke Konishi 6461cf58fa8SJiro SEKIBA /* 647263d90ceSRyusuke Konishi * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(), 6481cf58fa8SJiro SEKIBA * which will operates an inode list without blocking. 6491cf58fa8SJiro SEKIBA * To protect the list from concurrent operations, 6501cf58fa8SJiro SEKIBA * nilfs_ioctl_move_blocks should be atomic operation. 6511cf58fa8SJiro SEKIBA */ 6521cf58fa8SJiro SEKIBA if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) { 6531cf58fa8SJiro SEKIBA ret = -EBUSY; 6541cf58fa8SJiro SEKIBA goto out_free; 6551cf58fa8SJiro SEKIBA } 6561cf58fa8SJiro SEKIBA 6575beb6e0bSRyusuke Konishi vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); 6585beb6e0bSRyusuke Konishi 659263d90ceSRyusuke Konishi ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]); 6601cf58fa8SJiro SEKIBA if (ret < 0) 6611cf58fa8SJiro SEKIBA printk(KERN_ERR "NILFS: GC failed during preparation: " 6621cf58fa8SJiro SEKIBA "cannot read source blocks: err=%d\n", ret); 6631cf58fa8SJiro SEKIBA else 6644f6b8288SRyusuke Konishi ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); 6654f6b8288SRyusuke Konishi 666263d90ceSRyusuke Konishi nilfs_remove_all_gcinodes(nilfs); 6671cf58fa8SJiro SEKIBA clear_nilfs_gc_running(nilfs); 6681cf58fa8SJiro SEKIBA 6694f6b8288SRyusuke Konishi out_free: 670d5046853SRyusuke Konishi while (--n >= 0) 6714f6b8288SRyusuke Konishi vfree(kbufs[n]); 6724f6b8288SRyusuke Konishi kfree(kbufs[4]); 6737512487eSRyusuke Konishi out: 6747512487eSRyusuke Konishi mnt_drop_write(filp->f_path.mnt); 6754f6b8288SRyusuke Konishi return ret; 6767942b919SKoji Sato } 6777942b919SKoji Sato 6787942b919SKoji Sato static int nilfs_ioctl_sync(struct inode *inode, struct file *filp, 6797942b919SKoji Sato unsigned int cmd, void __user *argp) 6807942b919SKoji Sato { 6817942b919SKoji Sato __u64 cno; 6827942b919SKoji Sato int ret; 6830d561f12SJiro SEKIBA struct the_nilfs *nilfs; 6847942b919SKoji Sato 6857942b919SKoji Sato ret = nilfs_construct_segment(inode->i_sb); 6867942b919SKoji Sato if (ret < 0) 6877942b919SKoji Sato return ret; 6887942b919SKoji Sato 6897942b919SKoji Sato if (argp != NULL) { 6900d561f12SJiro SEKIBA nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 6910d561f12SJiro SEKIBA down_read(&nilfs->ns_segctor_sem); 6920d561f12SJiro SEKIBA cno = nilfs->ns_cno - 1; 6930d561f12SJiro SEKIBA up_read(&nilfs->ns_segctor_sem); 6947942b919SKoji Sato if (copy_to_user(argp, &cno, sizeof(cno))) 6957942b919SKoji Sato return -EFAULT; 6967942b919SKoji Sato } 6977942b919SKoji Sato return 0; 6987942b919SKoji Sato } 6997942b919SKoji Sato 70047eb6b9cSRyusuke Konishi static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, 70147eb6b9cSRyusuke Konishi unsigned int cmd, void __user *argp, 70283aca8f4SRyusuke Konishi size_t membsz, 70347eb6b9cSRyusuke Konishi ssize_t (*dofunc)(struct the_nilfs *, 70447eb6b9cSRyusuke Konishi __u64 *, int, 70547eb6b9cSRyusuke Konishi void *, size_t, size_t)) 70647eb6b9cSRyusuke Konishi 70747eb6b9cSRyusuke Konishi { 70847eb6b9cSRyusuke Konishi struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs; 70947eb6b9cSRyusuke Konishi struct nilfs_argv argv; 71047eb6b9cSRyusuke Konishi int ret; 71147eb6b9cSRyusuke Konishi 71247eb6b9cSRyusuke Konishi if (copy_from_user(&argv, argp, sizeof(argv))) 71347eb6b9cSRyusuke Konishi return -EFAULT; 71447eb6b9cSRyusuke Konishi 715003ff182SRyusuke Konishi if (argv.v_size < membsz) 71683aca8f4SRyusuke Konishi return -EINVAL; 71783aca8f4SRyusuke Konishi 71847eb6b9cSRyusuke Konishi ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc); 71947eb6b9cSRyusuke Konishi if (ret < 0) 72047eb6b9cSRyusuke Konishi return ret; 72147eb6b9cSRyusuke Konishi 72247eb6b9cSRyusuke Konishi if (copy_to_user(argp, &argv, sizeof(argv))) 72347eb6b9cSRyusuke Konishi ret = -EFAULT; 72447eb6b9cSRyusuke Konishi return ret; 72547eb6b9cSRyusuke Konishi } 72647eb6b9cSRyusuke Konishi 7277a946193SRyusuke Konishi long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) 7287942b919SKoji Sato { 7297a946193SRyusuke Konishi struct inode *inode = filp->f_dentry->d_inode; 73075323400SLi Hong void __user *argp = (void __user *)arg; 7317942b919SKoji Sato 7327942b919SKoji Sato switch (cmd) { 733cde98f0fSRyusuke Konishi case FS_IOC_GETFLAGS: 734cde98f0fSRyusuke Konishi return nilfs_ioctl_getflags(inode, argp); 735cde98f0fSRyusuke Konishi case FS_IOC_SETFLAGS: 736cde98f0fSRyusuke Konishi return nilfs_ioctl_setflags(inode, filp, argp); 737cde98f0fSRyusuke Konishi case FS_IOC_GETVERSION: 738cde98f0fSRyusuke Konishi return nilfs_ioctl_getversion(inode, argp); 7397942b919SKoji Sato case NILFS_IOCTL_CHANGE_CPMODE: 7407942b919SKoji Sato return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp); 7417942b919SKoji Sato case NILFS_IOCTL_DELETE_CHECKPOINT: 7427942b919SKoji Sato return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp); 7437942b919SKoji Sato case NILFS_IOCTL_GET_CPINFO: 74447eb6b9cSRyusuke Konishi return nilfs_ioctl_get_info(inode, filp, cmd, argp, 74583aca8f4SRyusuke Konishi sizeof(struct nilfs_cpinfo), 74647eb6b9cSRyusuke Konishi nilfs_ioctl_do_get_cpinfo); 7477942b919SKoji Sato case NILFS_IOCTL_GET_CPSTAT: 7487942b919SKoji Sato return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp); 7497942b919SKoji Sato case NILFS_IOCTL_GET_SUINFO: 75047eb6b9cSRyusuke Konishi return nilfs_ioctl_get_info(inode, filp, cmd, argp, 75183aca8f4SRyusuke Konishi sizeof(struct nilfs_suinfo), 75247eb6b9cSRyusuke Konishi nilfs_ioctl_do_get_suinfo); 7537942b919SKoji Sato case NILFS_IOCTL_GET_SUSTAT: 7547942b919SKoji Sato return nilfs_ioctl_get_sustat(inode, filp, cmd, argp); 7557942b919SKoji Sato case NILFS_IOCTL_GET_VINFO: 75647eb6b9cSRyusuke Konishi return nilfs_ioctl_get_info(inode, filp, cmd, argp, 75783aca8f4SRyusuke Konishi sizeof(struct nilfs_vinfo), 75847eb6b9cSRyusuke Konishi nilfs_ioctl_do_get_vinfo); 7597942b919SKoji Sato case NILFS_IOCTL_GET_BDESCS: 7607942b919SKoji Sato return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp); 7617942b919SKoji Sato case NILFS_IOCTL_CLEAN_SEGMENTS: 7627942b919SKoji Sato return nilfs_ioctl_clean_segments(inode, filp, cmd, argp); 7637942b919SKoji Sato case NILFS_IOCTL_SYNC: 7647942b919SKoji Sato return nilfs_ioctl_sync(inode, filp, cmd, argp); 7657942b919SKoji Sato default: 7667942b919SKoji Sato return -ENOTTY; 7677942b919SKoji Sato } 7687942b919SKoji Sato } 769