blob: d22281d60071122de626d5d6296127b3f223f86d [file] [log] [blame]
Koji Sato7942b912009-04-06 19:01:41 -07001/*
2 * ioctl.c - NILFS ioctl operations.
3 *
4 * Copyright (C) 2007, 2008 Nippon Telegraph and Telephone Corporation.
5 *
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.
10 *
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.
15 *
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
19 *
20 * Written by Koji Sato <koji@osrg.net>.
21 */
22
23#include <linux/fs.h>
24#include <linux/wait.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090025#include <linux/slab.h>
Koji Sato7942b912009-04-06 19:01:41 -070026#include <linux/capability.h> /* capable() */
27#include <linux/uaccess.h> /* copy_from_user(), copy_to_user() */
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +090028#include <linux/vmalloc.h>
Ryusuke Konishi828b1c52011-02-03 21:26:17 +090029#include <linux/compat.h> /* compat_ptr() */
Al Viro2a79f172011-12-09 08:06:57 -050030#include <linux/mount.h> /* mnt_want_write_file(), mnt_drop_write_file() */
Ryusuke Konishiae191832011-02-04 01:19:38 +090031#include <linux/buffer_head.h>
Koji Sato7942b912009-04-06 19:01:41 -070032#include <linux/nilfs2_fs.h>
33#include "nilfs.h"
34#include "segment.h"
35#include "bmap.h"
36#include "cpfile.h"
37#include "sufile.h"
38#include "dat.h"
39
40
Koji Sato7942b912009-04-06 19:01:41 -070041static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
42 struct nilfs_argv *argv, int dir,
43 ssize_t (*dofunc)(struct the_nilfs *,
Ryusuke Konishib028fcf2009-04-06 19:01:47 -070044 __u64 *, int,
Koji Sato7942b912009-04-06 19:01:41 -070045 void *, size_t, size_t))
46{
47 void *buf;
Ryusuke Konishidc498d02009-04-06 19:01:52 -070048 void __user *base = (void __user *)(unsigned long)argv->v_base;
Ryusuke Konishi3358b4a2009-04-06 19:01:43 -070049 size_t maxmembs, total, n;
Koji Sato7942b912009-04-06 19:01:41 -070050 ssize_t nr;
51 int ret, i;
Ryusuke Konishib028fcf2009-04-06 19:01:47 -070052 __u64 pos, ppos;
Koji Sato7942b912009-04-06 19:01:41 -070053
54 if (argv->v_nmembs == 0)
55 return 0;
56
Ryusuke Konishi3358b4a2009-04-06 19:01:43 -070057 if (argv->v_size > PAGE_SIZE)
58 return -EINVAL;
59
Wenliang Fan4b15d612014-01-23 15:55:22 -080060 /*
61 * Reject pairs of a start item position (argv->v_index) and a
62 * total count (argv->v_nmembs) which leads position 'pos' to
63 * overflow by the increment at the end of the loop.
64 */
65 if (argv->v_index > ~(__u64)0 - argv->v_nmembs)
66 return -EINVAL;
67
Ryusuke Konishi3358b4a2009-04-06 19:01:43 -070068 buf = (void *)__get_free_pages(GFP_NOFS, 0);
69 if (unlikely(!buf))
Koji Sato7942b912009-04-06 19:01:41 -070070 return -ENOMEM;
Ryusuke Konishi3358b4a2009-04-06 19:01:43 -070071 maxmembs = PAGE_SIZE / argv->v_size;
Koji Sato7942b912009-04-06 19:01:41 -070072
73 ret = 0;
74 total = 0;
Ryusuke Konishib028fcf2009-04-06 19:01:47 -070075 pos = argv->v_index;
Koji Sato7942b912009-04-06 19:01:41 -070076 for (i = 0; i < argv->v_nmembs; i += n) {
77 n = (argv->v_nmembs - i < maxmembs) ?
78 argv->v_nmembs - i : maxmembs;
79 if ((dir & _IOC_WRITE) &&
Ryusuke Konishidc498d02009-04-06 19:01:52 -070080 copy_from_user(buf, base + argv->v_size * i,
81 argv->v_size * n)) {
Koji Sato7942b912009-04-06 19:01:41 -070082 ret = -EFAULT;
83 break;
84 }
Ryusuke Konishib028fcf2009-04-06 19:01:47 -070085 ppos = pos;
Pekka Enberg8acfbf02009-04-06 19:01:49 -070086 nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size,
Ryusuke Konishib028fcf2009-04-06 19:01:47 -070087 n);
Koji Sato7942b912009-04-06 19:01:41 -070088 if (nr < 0) {
89 ret = nr;
90 break;
91 }
92 if ((dir & _IOC_READ) &&
Ryusuke Konishidc498d02009-04-06 19:01:52 -070093 copy_to_user(base + argv->v_size * i, buf,
94 argv->v_size * nr)) {
Koji Sato7942b912009-04-06 19:01:41 -070095 ret = -EFAULT;
96 break;
97 }
98 total += nr;
Ryusuke Konishib028fcf2009-04-06 19:01:47 -070099 if ((size_t)nr < n)
100 break;
101 if (pos == ppos)
102 pos += n;
Koji Sato7942b912009-04-06 19:01:41 -0700103 }
104 argv->v_nmembs = total;
105
Ryusuke Konishi3358b4a2009-04-06 19:01:43 -0700106 free_pages((unsigned long)buf, 0);
Koji Sato7942b912009-04-06 19:01:41 -0700107 return ret;
108}
109
Ryusuke Konishicde98f02011-01-20 02:09:53 +0900110static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
111{
112 unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
113
114 return put_user(flags, (int __user *)argp);
115}
116
117static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
118 void __user *argp)
119{
120 struct nilfs_transaction_info ti;
121 unsigned int flags, oldflags;
122 int ret;
123
Serge E. Hallyn2e149672011-03-23 16:43:26 -0700124 if (!inode_owner_or_capable(inode))
Ryusuke Konishicde98f02011-01-20 02:09:53 +0900125 return -EACCES;
126
127 if (get_user(flags, (int __user *)argp))
128 return -EFAULT;
129
Al Viroa561be72011-11-23 11:57:51 -0500130 ret = mnt_want_write_file(filp);
Ryusuke Konishicde98f02011-01-20 02:09:53 +0900131 if (ret)
132 return ret;
133
134 flags = nilfs_mask_flags(inode->i_mode, flags);
135
136 mutex_lock(&inode->i_mutex);
137
138 oldflags = NILFS_I(inode)->i_flags;
139
140 /*
141 * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
142 * relevant capability.
143 */
144 ret = -EPERM;
145 if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
146 !capable(CAP_LINUX_IMMUTABLE))
147 goto out;
148
149 ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
150 if (ret)
151 goto out;
152
153 NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
154 (flags & FS_FL_USER_MODIFIABLE);
155
156 nilfs_set_inode_flags(inode);
157 inode->i_ctime = CURRENT_TIME;
158 if (IS_SYNC(inode))
159 nilfs_set_transaction_flag(NILFS_TI_SYNC);
160
161 nilfs_mark_inode_dirty(inode);
162 ret = nilfs_transaction_commit(inode->i_sb);
163out:
164 mutex_unlock(&inode->i_mutex);
Al Viro2a79f172011-12-09 08:06:57 -0500165 mnt_drop_write_file(filp);
Ryusuke Konishicde98f02011-01-20 02:09:53 +0900166 return ret;
167}
168
169static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
170{
171 return put_user(inode->i_generation, (int __user *)argp);
172}
173
Koji Sato7942b912009-04-06 19:01:41 -0700174static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
175 unsigned int cmd, void __user *argp)
176{
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900177 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
Koji Sato7942b912009-04-06 19:01:41 -0700178 struct nilfs_transaction_info ti;
179 struct nilfs_cpmode cpmode;
180 int ret;
181
182 if (!capable(CAP_SYS_ADMIN))
183 return -EPERM;
Ryusuke Konishi75124872010-01-26 13:59:40 +0900184
Al Viroa561be72011-11-23 11:57:51 -0500185 ret = mnt_want_write_file(filp);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900186 if (ret)
187 return ret;
188
189 ret = -EFAULT;
Koji Sato7942b912009-04-06 19:01:41 -0700190 if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
Ryusuke Konishi75124872010-01-26 13:59:40 +0900191 goto out;
Koji Sato7942b912009-04-06 19:01:41 -0700192
Ryusuke Konishi572d8b32012-07-30 14:42:07 -0700193 mutex_lock(&nilfs->ns_snapshot_mount_mutex);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900194
Koji Sato7942b912009-04-06 19:01:41 -0700195 nilfs_transaction_begin(inode->i_sb, &ti, 0);
196 ret = nilfs_cpfile_change_cpmode(
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900197 nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900198 if (unlikely(ret < 0))
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700199 nilfs_transaction_abort(inode->i_sb);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900200 else
201 nilfs_transaction_commit(inode->i_sb); /* never fails */
202
Ryusuke Konishi572d8b32012-07-30 14:42:07 -0700203 mutex_unlock(&nilfs->ns_snapshot_mount_mutex);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900204out:
Al Viro2a79f172011-12-09 08:06:57 -0500205 mnt_drop_write_file(filp);
Koji Sato7942b912009-04-06 19:01:41 -0700206 return ret;
207}
208
209static int
210nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
211 unsigned int cmd, void __user *argp)
212{
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900213 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
Koji Sato7942b912009-04-06 19:01:41 -0700214 struct nilfs_transaction_info ti;
215 __u64 cno;
216 int ret;
217
218 if (!capable(CAP_SYS_ADMIN))
219 return -EPERM;
Ryusuke Konishi75124872010-01-26 13:59:40 +0900220
Al Viroa561be72011-11-23 11:57:51 -0500221 ret = mnt_want_write_file(filp);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900222 if (ret)
223 return ret;
224
225 ret = -EFAULT;
Koji Sato7942b912009-04-06 19:01:41 -0700226 if (copy_from_user(&cno, argp, sizeof(cno)))
Ryusuke Konishi75124872010-01-26 13:59:40 +0900227 goto out;
Koji Sato7942b912009-04-06 19:01:41 -0700228
229 nilfs_transaction_begin(inode->i_sb, &ti, 0);
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900230 ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900231 if (unlikely(ret < 0))
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700232 nilfs_transaction_abort(inode->i_sb);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900233 else
234 nilfs_transaction_commit(inode->i_sb); /* never fails */
235out:
Al Viro2a79f172011-12-09 08:06:57 -0500236 mnt_drop_write_file(filp);
Koji Sato7942b912009-04-06 19:01:41 -0700237 return ret;
238}
239
240static ssize_t
Ryusuke Konishib028fcf2009-04-06 19:01:47 -0700241nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
Koji Sato7942b912009-04-06 19:01:41 -0700242 void *buf, size_t size, size_t nmembs)
243{
Koji Sato7942b912009-04-06 19:01:41 -0700244 int ret;
245
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700246 down_read(&nilfs->ns_segctor_sem);
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900247 ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
Ryusuke Konishi003ff182009-05-12 03:58:47 +0900248 size, nmembs);
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700249 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700250 return ret;
251}
252
253static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
254 unsigned int cmd, void __user *argp)
255{
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900256 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
Koji Sato7942b912009-04-06 19:01:41 -0700257 struct nilfs_cpstat cpstat;
Koji Sato7942b912009-04-06 19:01:41 -0700258 int ret;
259
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700260 down_read(&nilfs->ns_segctor_sem);
261 ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
262 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700263 if (ret < 0)
264 return ret;
265
266 if (copy_to_user(argp, &cpstat, sizeof(cpstat)))
267 ret = -EFAULT;
268 return ret;
269}
270
271static ssize_t
Ryusuke Konishib028fcf2009-04-06 19:01:47 -0700272nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
Koji Sato7942b912009-04-06 19:01:41 -0700273 void *buf, size_t size, size_t nmembs)
274{
Koji Sato7942b912009-04-06 19:01:41 -0700275 int ret;
276
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700277 down_read(&nilfs->ns_segctor_sem);
Ryusuke Konishi003ff182009-05-12 03:58:47 +0900278 ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
279 nmembs);
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700280 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700281 return ret;
282}
283
284static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
285 unsigned int cmd, void __user *argp)
286{
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900287 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
Koji Sato7942b912009-04-06 19:01:41 -0700288 struct nilfs_sustat sustat;
Koji Sato7942b912009-04-06 19:01:41 -0700289 int ret;
290
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700291 down_read(&nilfs->ns_segctor_sem);
292 ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
293 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700294 if (ret < 0)
295 return ret;
296
297 if (copy_to_user(argp, &sustat, sizeof(sustat)))
298 ret = -EFAULT;
299 return ret;
300}
301
302static ssize_t
Ryusuke Konishib028fcf2009-04-06 19:01:47 -0700303nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
Koji Sato7942b912009-04-06 19:01:41 -0700304 void *buf, size_t size, size_t nmembs)
305{
Koji Sato7942b912009-04-06 19:01:41 -0700306 int ret;
307
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700308 down_read(&nilfs->ns_segctor_sem);
Ryusuke Konishi365e2152010-12-27 00:07:30 +0900309 ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs);
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700310 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700311 return ret;
312}
313
314static ssize_t
Ryusuke Konishib028fcf2009-04-06 19:01:47 -0700315nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
Koji Sato7942b912009-04-06 19:01:41 -0700316 void *buf, size_t size, size_t nmembs)
317{
Ryusuke Konishi365e2152010-12-27 00:07:30 +0900318 struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
Koji Sato7942b912009-04-06 19:01:41 -0700319 struct nilfs_bdesc *bdescs = buf;
320 int ret, i;
321
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900322 down_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700323 for (i = 0; i < nmembs; i++) {
324 ret = nilfs_bmap_lookup_at_level(bmap,
325 bdescs[i].bd_offset,
326 bdescs[i].bd_level + 1,
327 &bdescs[i].bd_blocknr);
328 if (ret < 0) {
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900329 if (ret != -ENOENT) {
330 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700331 return ret;
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900332 }
Koji Sato7942b912009-04-06 19:01:41 -0700333 bdescs[i].bd_blocknr = 0;
334 }
335 }
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900336 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700337 return nmembs;
338}
339
340static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
341 unsigned int cmd, void __user *argp)
342{
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900343 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
Koji Sato7942b912009-04-06 19:01:41 -0700344 struct nilfs_argv argv;
Koji Sato7942b912009-04-06 19:01:41 -0700345 int ret;
346
347 if (copy_from_user(&argv, argp, sizeof(argv)))
348 return -EFAULT;
349
Ryusuke Konishi83aca8f2009-05-11 23:24:47 +0900350 if (argv.v_size != sizeof(struct nilfs_bdesc))
351 return -EINVAL;
352
Koji Sato7942b912009-04-06 19:01:41 -0700353 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
354 nilfs_ioctl_do_get_bdescs);
Ryusuke Konishi47420c72009-04-06 19:01:45 -0700355 if (ret < 0)
356 return ret;
Koji Sato7942b912009-04-06 19:01:41 -0700357
358 if (copy_to_user(argp, &argv, sizeof(argv)))
359 ret = -EFAULT;
360 return ret;
361}
362
363static int nilfs_ioctl_move_inode_block(struct inode *inode,
364 struct nilfs_vdesc *vdesc,
365 struct list_head *buffers)
366{
367 struct buffer_head *bh;
368 int ret;
369
370 if (vdesc->vd_flags == 0)
371 ret = nilfs_gccache_submit_read_data(
372 inode, vdesc->vd_offset, vdesc->vd_blocknr,
373 vdesc->vd_vblocknr, &bh);
374 else
375 ret = nilfs_gccache_submit_read_node(
376 inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
377
378 if (unlikely(ret < 0)) {
379 if (ret == -ENOENT)
380 printk(KERN_CRIT
381 "%s: invalid virtual block address (%s): "
382 "ino=%llu, cno=%llu, offset=%llu, "
383 "blocknr=%llu, vblocknr=%llu\n",
384 __func__, vdesc->vd_flags ? "node" : "data",
385 (unsigned long long)vdesc->vd_ino,
386 (unsigned long long)vdesc->vd_cno,
387 (unsigned long long)vdesc->vd_offset,
388 (unsigned long long)vdesc->vd_blocknr,
389 (unsigned long long)vdesc->vd_vblocknr);
390 return ret;
391 }
Ryusuke Konishi5399dd12009-11-07 18:45:16 +0900392 if (unlikely(!list_empty(&bh->b_assoc_buffers))) {
393 printk(KERN_CRIT "%s: conflicting %s buffer: ino=%llu, "
394 "cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu\n",
395 __func__, vdesc->vd_flags ? "node" : "data",
396 (unsigned long long)vdesc->vd_ino,
397 (unsigned long long)vdesc->vd_cno,
398 (unsigned long long)vdesc->vd_offset,
399 (unsigned long long)vdesc->vd_blocknr,
400 (unsigned long long)vdesc->vd_vblocknr);
401 brelse(bh);
402 return -EEXIST;
403 }
Koji Sato7942b912009-04-06 19:01:41 -0700404 list_add_tail(&bh->b_assoc_buffers, buffers);
405 return 0;
406}
407
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900408static int nilfs_ioctl_move_blocks(struct super_block *sb,
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900409 struct nilfs_argv *argv, void *buf)
Koji Sato7942b912009-04-06 19:01:41 -0700410{
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900411 size_t nmembs = argv->v_nmembs;
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900412 struct the_nilfs *nilfs = sb->s_fs_info;
Koji Sato7942b912009-04-06 19:01:41 -0700413 struct inode *inode;
414 struct nilfs_vdesc *vdesc;
415 struct buffer_head *bh, *n;
416 LIST_HEAD(buffers);
417 ino_t ino;
418 __u64 cno;
419 int i, ret;
420
421 for (i = 0, vdesc = buf; i < nmembs; ) {
422 ino = vdesc->vd_ino;
423 cno = vdesc->vd_cno;
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900424 inode = nilfs_iget_for_gc(sb, ino, cno);
Dan Carpenter103cfcf2010-11-23 09:26:02 +0300425 if (IS_ERR(inode)) {
426 ret = PTR_ERR(inode);
Koji Sato7942b912009-04-06 19:01:41 -0700427 goto failed;
428 }
Ryusuke Konishi947b10a2010-12-16 09:57:57 +0900429 if (list_empty(&NILFS_I(inode)->i_dirty)) {
430 /*
431 * Add the inode to GC inode list. Garbage Collection
432 * is serialized and no two processes manipulate the
433 * list simultaneously.
434 */
435 igrab(inode);
436 list_add(&NILFS_I(inode)->i_dirty,
437 &nilfs->ns_gc_inodes);
438 }
439
Koji Sato7942b912009-04-06 19:01:41 -0700440 do {
441 ret = nilfs_ioctl_move_inode_block(inode, vdesc,
442 &buffers);
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900443 if (unlikely(ret < 0)) {
444 iput(inode);
Koji Sato7942b912009-04-06 19:01:41 -0700445 goto failed;
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900446 }
Koji Sato7942b912009-04-06 19:01:41 -0700447 vdesc++;
448 } while (++i < nmembs &&
449 vdesc->vd_ino == ino && vdesc->vd_cno == cno);
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900450
451 iput(inode); /* The inode still remains in GC inode list */
Koji Sato7942b912009-04-06 19:01:41 -0700452 }
453
454 list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
455 ret = nilfs_gccache_wait_and_mark_dirty(bh);
456 if (unlikely(ret < 0)) {
Ryusuke Konishi5399dd12009-11-07 18:45:16 +0900457 WARN_ON(ret == -EEXIST);
Koji Sato7942b912009-04-06 19:01:41 -0700458 goto failed;
459 }
460 list_del_init(&bh->b_assoc_buffers);
Koji Sato7942b912009-04-06 19:01:41 -0700461 brelse(bh);
462 }
463 return nmembs;
464
465 failed:
466 list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
467 list_del_init(&bh->b_assoc_buffers);
Koji Sato7942b912009-04-06 19:01:41 -0700468 brelse(bh);
469 }
470 return ret;
471}
472
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900473static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
474 struct nilfs_argv *argv, void *buf)
Koji Sato7942b912009-04-06 19:01:41 -0700475{
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900476 size_t nmembs = argv->v_nmembs;
Koji Sato7942b912009-04-06 19:01:41 -0700477 struct inode *cpfile = nilfs->ns_cpfile;
478 struct nilfs_period *periods = buf;
479 int ret, i;
480
481 for (i = 0; i < nmembs; i++) {
482 ret = nilfs_cpfile_delete_checkpoints(
483 cpfile, periods[i].p_start, periods[i].p_end);
484 if (ret < 0)
485 return ret;
486 }
487 return nmembs;
488}
489
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900490static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
491 struct nilfs_argv *argv, void *buf)
Koji Sato7942b912009-04-06 19:01:41 -0700492{
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900493 size_t nmembs = argv->v_nmembs;
494 int ret;
Koji Sato7942b912009-04-06 19:01:41 -0700495
Ryusuke Konishi365e2152010-12-27 00:07:30 +0900496 ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs);
Koji Sato7942b912009-04-06 19:01:41 -0700497
498 return (ret < 0) ? ret : nmembs;
499}
500
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900501static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
502 struct nilfs_argv *argv, void *buf)
Koji Sato7942b912009-04-06 19:01:41 -0700503{
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900504 size_t nmembs = argv->v_nmembs;
Ryusuke Konishi365e2152010-12-27 00:07:30 +0900505 struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
Koji Sato7942b912009-04-06 19:01:41 -0700506 struct nilfs_bdesc *bdescs = buf;
507 int ret, i;
508
509 for (i = 0; i < nmembs; i++) {
510 /* XXX: use macro or inline func to check liveness */
511 ret = nilfs_bmap_lookup_at_level(bmap,
512 bdescs[i].bd_offset,
513 bdescs[i].bd_level + 1,
514 &bdescs[i].bd_blocknr);
515 if (ret < 0) {
516 if (ret != -ENOENT)
517 return ret;
518 bdescs[i].bd_blocknr = 0;
519 }
520 if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr)
521 /* skip dead block */
522 continue;
523 if (bdescs[i].bd_level == 0) {
Ryusuke Konishi365e2152010-12-27 00:07:30 +0900524 ret = nilfs_mdt_mark_block_dirty(nilfs->ns_dat,
Koji Sato7942b912009-04-06 19:01:41 -0700525 bdescs[i].bd_offset);
526 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700527 WARN_ON(ret == -ENOENT);
Koji Sato7942b912009-04-06 19:01:41 -0700528 return ret;
529 }
530 } else {
531 ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset,
532 bdescs[i].bd_level);
533 if (ret < 0) {
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700534 WARN_ON(ret == -ENOENT);
Koji Sato7942b912009-04-06 19:01:41 -0700535 return ret;
536 }
537 }
538 }
539 return nmembs;
540}
541
Koji Sato7942b912009-04-06 19:01:41 -0700542int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900543 struct nilfs_argv *argv, void **kbufs)
Koji Sato7942b912009-04-06 19:01:41 -0700544{
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700545 const char *msg;
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900546 int ret;
Koji Sato7942b912009-04-06 19:01:41 -0700547
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900548 ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700549 if (ret < 0) {
550 /*
551 * can safely abort because checkpoints can be removed
552 * independently.
553 */
554 msg = "cannot delete checkpoints";
555 goto failed;
556 }
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900557 ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700558 if (ret < 0) {
559 /*
560 * can safely abort because DAT file is updated atomically
561 * using a copy-on-write technique.
562 */
563 msg = "cannot delete virtual blocks from DAT file";
564 goto failed;
565 }
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900566 ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700567 if (ret < 0) {
568 /*
569 * can safely abort because the operation is nondestructive.
570 */
571 msg = "cannot mark copying blocks dirty";
572 goto failed;
573 }
Koji Sato7942b912009-04-06 19:01:41 -0700574 return 0;
575
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700576 failed:
Ryusuke Konishi1f5abe72009-04-06 19:01:55 -0700577 printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n",
578 msg, ret);
Koji Sato7942b912009-04-06 19:01:41 -0700579 return ret;
580}
581
582static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
583 unsigned int cmd, void __user *argp)
584{
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900585 struct nilfs_argv argv[5];
Tobias Klauser33e189b2009-12-23 13:57:47 +0100586 static const size_t argsz[5] = {
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900587 sizeof(struct nilfs_vdesc),
588 sizeof(struct nilfs_period),
589 sizeof(__u64),
590 sizeof(struct nilfs_bdesc),
591 sizeof(__u64),
592 };
593 void __user *base;
594 void *kbufs[5];
595 struct the_nilfs *nilfs;
596 size_t len, nsegs;
597 int n, ret;
598
Koji Sato7942b912009-04-06 19:01:41 -0700599 if (!capable(CAP_SYS_ADMIN))
600 return -EPERM;
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900601
Al Viroa561be72011-11-23 11:57:51 -0500602 ret = mnt_want_write_file(filp);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900603 if (ret)
604 return ret;
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900605
Ryusuke Konishi75124872010-01-26 13:59:40 +0900606 ret = -EFAULT;
607 if (copy_from_user(argv, argp, sizeof(argv)))
608 goto out;
609
610 ret = -EINVAL;
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900611 nsegs = argv[4].v_nmembs;
612 if (argv[4].v_size != argsz[4])
Ryusuke Konishi75124872010-01-26 13:59:40 +0900613 goto out;
Xi Wang1ecd3c72012-02-08 17:13:37 -0800614 if (nsegs > UINT_MAX / sizeof(__u64))
615 goto out;
Ryusuke Konishi75124872010-01-26 13:59:40 +0900616
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900617 /*
618 * argv[4] points to segment numbers this ioctl cleans. We
619 * use kmalloc() for its buffer because memory used for the
620 * segment numbers is enough small.
621 */
622 kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base,
623 nsegs * sizeof(__u64));
Ryusuke Konishi75124872010-01-26 13:59:40 +0900624 if (IS_ERR(kbufs[4])) {
625 ret = PTR_ERR(kbufs[4]);
626 goto out;
627 }
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900628 nilfs = inode->i_sb->s_fs_info;
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900629
630 for (n = 0; n < 4; n++) {
631 ret = -EINVAL;
632 if (argv[n].v_size != argsz[n])
633 goto out_free;
634
635 if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment)
636 goto out_free;
637
Haogang Chen481fe172011-12-19 17:11:56 -0800638 if (argv[n].v_nmembs >= UINT_MAX / argv[n].v_size)
639 goto out_free;
640
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900641 len = argv[n].v_size * argv[n].v_nmembs;
642 base = (void __user *)(unsigned long)argv[n].v_base;
643 if (len == 0) {
644 kbufs[n] = NULL;
645 continue;
646 }
647
648 kbufs[n] = vmalloc(len);
649 if (!kbufs[n]) {
650 ret = -ENOMEM;
651 goto out_free;
652 }
653 if (copy_from_user(kbufs[n], base, len)) {
654 ret = -EFAULT;
655 vfree(kbufs[n]);
656 goto out_free;
657 }
658 }
659
Jiro SEKIBA1cf58fa2009-09-03 22:24:17 +0900660 /*
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900661 * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(),
Jiro SEKIBA1cf58fa2009-09-03 22:24:17 +0900662 * which will operates an inode list without blocking.
663 * To protect the list from concurrent operations,
664 * nilfs_ioctl_move_blocks should be atomic operation.
665 */
666 if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) {
667 ret = -EBUSY;
668 goto out_free;
669 }
670
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900671 ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
Jiro SEKIBA1cf58fa2009-09-03 22:24:17 +0900672 if (ret < 0)
673 printk(KERN_ERR "NILFS: GC failed during preparation: "
674 "cannot read source blocks: err=%d\n", ret);
Vyacheslav Dubeykoa9bae182013-02-04 14:28:41 -0800675 else {
676 if (nilfs_sb_need_update(nilfs))
677 set_nilfs_discontinued(nilfs);
Jiro SEKIBA1cf58fa2009-09-03 22:24:17 +0900678 ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
Vyacheslav Dubeykoa9bae182013-02-04 14:28:41 -0800679 }
Jiro SEKIBA1cf58fa2009-09-03 22:24:17 +0900680
Ryusuke Konishi263d90c2010-08-20 19:06:11 +0900681 nilfs_remove_all_gcinodes(nilfs);
Jiro SEKIBA1cf58fa2009-09-03 22:24:17 +0900682 clear_nilfs_gc_running(nilfs);
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900683
Ryusuke Konishi75124872010-01-26 13:59:40 +0900684out_free:
Ryusuke Konishid50468532009-05-22 20:36:21 +0900685 while (--n >= 0)
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900686 vfree(kbufs[n]);
687 kfree(kbufs[4]);
Ryusuke Konishi75124872010-01-26 13:59:40 +0900688out:
Al Viro2a79f172011-12-09 08:06:57 -0500689 mnt_drop_write_file(filp);
Ryusuke Konishi4f6b8282009-05-10 22:41:43 +0900690 return ret;
Koji Sato7942b912009-04-06 19:01:41 -0700691}
692
693static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
694 unsigned int cmd, void __user *argp)
695{
696 __u64 cno;
697 int ret;
Jiro SEKIBA0d561f12010-02-20 19:47:49 +0900698 struct the_nilfs *nilfs;
Koji Sato7942b912009-04-06 19:01:41 -0700699
700 ret = nilfs_construct_segment(inode->i_sb);
701 if (ret < 0)
702 return ret;
703
Ryusuke Konishi11475972012-05-31 16:26:11 -0700704 nilfs = inode->i_sb->s_fs_info;
705 if (nilfs_test_opt(nilfs, BARRIER)) {
706 ret = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
707 if (ret == -EIO)
708 return ret;
709 }
710
Koji Sato7942b912009-04-06 19:01:41 -0700711 if (argp != NULL) {
Jiro SEKIBA0d561f12010-02-20 19:47:49 +0900712 down_read(&nilfs->ns_segctor_sem);
713 cno = nilfs->ns_cno - 1;
714 up_read(&nilfs->ns_segctor_sem);
Koji Sato7942b912009-04-06 19:01:41 -0700715 if (copy_to_user(argp, &cno, sizeof(cno)))
716 return -EFAULT;
717 }
718 return 0;
719}
720
Ryusuke Konishi4e33f9e2011-05-05 01:23:58 +0900721static int nilfs_ioctl_resize(struct inode *inode, struct file *filp,
722 void __user *argp)
723{
724 __u64 newsize;
725 int ret = -EPERM;
726
727 if (!capable(CAP_SYS_ADMIN))
728 goto out;
729
Al Viroa561be72011-11-23 11:57:51 -0500730 ret = mnt_want_write_file(filp);
Ryusuke Konishi4e33f9e2011-05-05 01:23:58 +0900731 if (ret)
732 goto out;
733
734 ret = -EFAULT;
735 if (copy_from_user(&newsize, argp, sizeof(newsize)))
736 goto out_drop_write;
737
738 ret = nilfs_resize_fs(inode->i_sb, newsize);
739
740out_drop_write:
Al Viro2a79f172011-12-09 08:06:57 -0500741 mnt_drop_write_file(filp);
Ryusuke Konishi4e33f9e2011-05-05 01:23:58 +0900742out:
743 return ret;
744}
745
Ryusuke Konishi619205d2011-05-05 01:23:57 +0900746static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
747{
748 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
749 __u64 range[2];
750 __u64 minseg, maxseg;
751 unsigned long segbytes;
752 int ret = -EPERM;
753
754 if (!capable(CAP_SYS_ADMIN))
755 goto out;
756
757 ret = -EFAULT;
758 if (copy_from_user(range, argp, sizeof(__u64[2])))
759 goto out;
760
761 ret = -ERANGE;
762 if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode))
763 goto out;
764
765 segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize;
766
767 minseg = range[0] + segbytes - 1;
768 do_div(minseg, segbytes);
769 maxseg = NILFS_SB2_OFFSET_BYTES(range[1]);
770 do_div(maxseg, segbytes);
771 maxseg--;
772
773 ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg);
774out:
775 return ret;
776}
777
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900778static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
779 unsigned int cmd, void __user *argp,
Ryusuke Konishi83aca8f2009-05-11 23:24:47 +0900780 size_t membsz,
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900781 ssize_t (*dofunc)(struct the_nilfs *,
782 __u64 *, int,
783 void *, size_t, size_t))
784
785{
Ryusuke Konishie3154e92011-03-09 11:05:08 +0900786 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900787 struct nilfs_argv argv;
788 int ret;
789
790 if (copy_from_user(&argv, argp, sizeof(argv)))
791 return -EFAULT;
792
Ryusuke Konishi003ff182009-05-12 03:58:47 +0900793 if (argv.v_size < membsz)
Ryusuke Konishi83aca8f2009-05-11 23:24:47 +0900794 return -EINVAL;
795
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900796 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
797 if (ret < 0)
798 return ret;
799
800 if (copy_to_user(argp, &argv, sizeof(argv)))
801 ret = -EFAULT;
802 return ret;
803}
804
Ryusuke Konishi7a946192009-04-06 19:01:53 -0700805long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Koji Sato7942b912009-04-06 19:01:41 -0700806{
Al Viro496ad9a2013-01-23 17:07:38 -0500807 struct inode *inode = file_inode(filp);
Li Hong75323402010-03-31 15:41:00 +0800808 void __user *argp = (void __user *)arg;
Koji Sato7942b912009-04-06 19:01:41 -0700809
810 switch (cmd) {
Ryusuke Konishicde98f02011-01-20 02:09:53 +0900811 case FS_IOC_GETFLAGS:
812 return nilfs_ioctl_getflags(inode, argp);
813 case FS_IOC_SETFLAGS:
814 return nilfs_ioctl_setflags(inode, filp, argp);
815 case FS_IOC_GETVERSION:
816 return nilfs_ioctl_getversion(inode, argp);
Koji Sato7942b912009-04-06 19:01:41 -0700817 case NILFS_IOCTL_CHANGE_CPMODE:
818 return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
819 case NILFS_IOCTL_DELETE_CHECKPOINT:
820 return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
821 case NILFS_IOCTL_GET_CPINFO:
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900822 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
Ryusuke Konishi83aca8f2009-05-11 23:24:47 +0900823 sizeof(struct nilfs_cpinfo),
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900824 nilfs_ioctl_do_get_cpinfo);
Koji Sato7942b912009-04-06 19:01:41 -0700825 case NILFS_IOCTL_GET_CPSTAT:
826 return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
827 case NILFS_IOCTL_GET_SUINFO:
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900828 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
Ryusuke Konishi83aca8f2009-05-11 23:24:47 +0900829 sizeof(struct nilfs_suinfo),
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900830 nilfs_ioctl_do_get_suinfo);
Koji Sato7942b912009-04-06 19:01:41 -0700831 case NILFS_IOCTL_GET_SUSTAT:
832 return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
833 case NILFS_IOCTL_GET_VINFO:
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900834 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
Ryusuke Konishi83aca8f2009-05-11 23:24:47 +0900835 sizeof(struct nilfs_vinfo),
Ryusuke Konishi47eb6b92009-04-30 02:21:00 +0900836 nilfs_ioctl_do_get_vinfo);
Koji Sato7942b912009-04-06 19:01:41 -0700837 case NILFS_IOCTL_GET_BDESCS:
838 return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
839 case NILFS_IOCTL_CLEAN_SEGMENTS:
840 return nilfs_ioctl_clean_segments(inode, filp, cmd, argp);
Koji Sato7942b912009-04-06 19:01:41 -0700841 case NILFS_IOCTL_SYNC:
842 return nilfs_ioctl_sync(inode, filp, cmd, argp);
Ryusuke Konishi4e33f9e2011-05-05 01:23:58 +0900843 case NILFS_IOCTL_RESIZE:
844 return nilfs_ioctl_resize(inode, filp, argp);
Ryusuke Konishi619205d2011-05-05 01:23:57 +0900845 case NILFS_IOCTL_SET_ALLOC_RANGE:
846 return nilfs_ioctl_set_alloc_range(inode, argp);
Koji Sato7942b912009-04-06 19:01:41 -0700847 default:
848 return -ENOTTY;
849 }
850}
Ryusuke Konishi828b1c52011-02-03 21:26:17 +0900851
852#ifdef CONFIG_COMPAT
853long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
854{
855 switch (cmd) {
856 case FS_IOC32_GETFLAGS:
857 cmd = FS_IOC_GETFLAGS;
858 break;
859 case FS_IOC32_SETFLAGS:
860 cmd = FS_IOC_SETFLAGS;
861 break;
862 case FS_IOC32_GETVERSION:
863 cmd = FS_IOC_GETVERSION;
864 break;
Thomas Meyer695c60f2011-12-19 17:11:55 -0800865 case NILFS_IOCTL_CHANGE_CPMODE:
866 case NILFS_IOCTL_DELETE_CHECKPOINT:
867 case NILFS_IOCTL_GET_CPINFO:
868 case NILFS_IOCTL_GET_CPSTAT:
869 case NILFS_IOCTL_GET_SUINFO:
870 case NILFS_IOCTL_GET_SUSTAT:
871 case NILFS_IOCTL_GET_VINFO:
872 case NILFS_IOCTL_GET_BDESCS:
873 case NILFS_IOCTL_CLEAN_SEGMENTS:
874 case NILFS_IOCTL_SYNC:
875 case NILFS_IOCTL_RESIZE:
876 case NILFS_IOCTL_SET_ALLOC_RANGE:
877 break;
Ryusuke Konishi828b1c52011-02-03 21:26:17 +0900878 default:
879 return -ENOIOCTLCMD;
880 }
881 return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
882}
883#endif