886649627c3d68d568914ee3d88983cbebcf08a5
[linux-2.6.git] / fs / nilfs2 / ioctl.c
1 /*
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>
25 #include <linux/slab.h>
26 #include <linux/capability.h>   /* capable() */
27 #include <linux/uaccess.h>      /* copy_from_user(), copy_to_user() */
28 #include <linux/vmalloc.h>
29 #include <linux/compat.h>       /* compat_ptr() */
30 #include <linux/mount.h>        /* mnt_want_write_file(), mnt_drop_write_file() */
31 #include <linux/buffer_head.h>
32 #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
41 static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
42                                  struct nilfs_argv *argv, int dir,
43                                  ssize_t (*dofunc)(struct the_nilfs *,
44                                                    __u64 *, int,
45                                                    void *, size_t, size_t))
46 {
47         void *buf;
48         void __user *base = (void __user *)(unsigned long)argv->v_base;
49         size_t maxmembs, total, n;
50         ssize_t nr;
51         int ret, i;
52         __u64 pos, ppos;
53
54         if (argv->v_nmembs == 0)
55                 return 0;
56
57         if (argv->v_size > PAGE_SIZE)
58                 return -EINVAL;
59
60         buf = (void *)__get_free_pages(GFP_NOFS, 0);
61         if (unlikely(!buf))
62                 return -ENOMEM;
63         maxmembs = PAGE_SIZE / argv->v_size;
64
65         ret = 0;
66         total = 0;
67         pos = argv->v_index;
68         for (i = 0; i < argv->v_nmembs; i += n) {
69                 n = (argv->v_nmembs - i < maxmembs) ?
70                         argv->v_nmembs - i : maxmembs;
71                 if ((dir & _IOC_WRITE) &&
72                     copy_from_user(buf, base + argv->v_size * i,
73                                    argv->v_size * n)) {
74                         ret = -EFAULT;
75                         break;
76                 }
77                 ppos = pos;
78                 nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size,
79                                n);
80                 if (nr < 0) {
81                         ret = nr;
82                         break;
83                 }
84                 if ((dir & _IOC_READ) &&
85                     copy_to_user(base + argv->v_size * i, buf,
86                                  argv->v_size * nr)) {
87                         ret = -EFAULT;
88                         break;
89                 }
90                 total += nr;
91                 if ((size_t)nr < n)
92                         break;
93                 if (pos == ppos)
94                         pos += n;
95         }
96         argv->v_nmembs = total;
97
98         free_pages((unsigned long)buf, 0);
99         return ret;
100 }
101
102 static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
103 {
104         unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
105
106         return put_user(flags, (int __user *)argp);
107 }
108
109 static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
110                                 void __user *argp)
111 {
112         struct nilfs_transaction_info ti;
113         unsigned int flags, oldflags;
114         int ret;
115
116         if (!inode_owner_or_capable(inode))
117                 return -EACCES;
118
119         if (get_user(flags, (int __user *)argp))
120                 return -EFAULT;
121
122         ret = mnt_want_write_file(filp);
123         if (ret)
124                 return ret;
125
126         flags = nilfs_mask_flags(inode->i_mode, flags);
127
128         mutex_lock(&inode->i_mutex);
129
130         oldflags = NILFS_I(inode)->i_flags;
131
132         /*
133          * The IMMUTABLE and APPEND_ONLY flags can only be changed by the
134          * relevant capability.
135          */
136         ret = -EPERM;
137         if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
138             !capable(CAP_LINUX_IMMUTABLE))
139                 goto out;
140
141         ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
142         if (ret)
143                 goto out;
144
145         NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
146                 (flags & FS_FL_USER_MODIFIABLE);
147
148         nilfs_set_inode_flags(inode);
149         inode->i_ctime = CURRENT_TIME;
150         if (IS_SYNC(inode))
151                 nilfs_set_transaction_flag(NILFS_TI_SYNC);
152
153         nilfs_mark_inode_dirty(inode);
154         ret = nilfs_transaction_commit(inode->i_sb);
155 out:
156         mutex_unlock(&inode->i_mutex);
157         mnt_drop_write_file(filp);
158         return ret;
159 }
160
161 static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
162 {
163         return put_user(inode->i_generation, (int __user *)argp);
164 }
165
166 static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
167                                      unsigned int cmd, void __user *argp)
168 {
169         struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
170         struct nilfs_transaction_info ti;
171         struct nilfs_cpmode cpmode;
172         int ret;
173
174         if (!capable(CAP_SYS_ADMIN))
175                 return -EPERM;
176
177         ret = mnt_want_write_file(filp);
178         if (ret)
179                 return ret;
180
181         ret = -EFAULT;
182         if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
183                 goto out;
184
185         down_read(&inode->i_sb->s_umount);
186
187         nilfs_transaction_begin(inode->i_sb, &ti, 0);
188         ret = nilfs_cpfile_change_cpmode(
189                 nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
190         if (unlikely(ret < 0))
191                 nilfs_transaction_abort(inode->i_sb);
192         else
193                 nilfs_transaction_commit(inode->i_sb); /* never fails */
194
195         up_read(&inode->i_sb->s_umount);
196 out:
197         mnt_drop_write_file(filp);
198         return ret;
199 }
200
201 static int
202 nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
203                               unsigned int cmd, void __user *argp)
204 {
205         struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
206         struct nilfs_transaction_info ti;
207         __u64 cno;
208         int ret;
209
210         if (!capable(CAP_SYS_ADMIN))
211                 return -EPERM;
212
213         ret = mnt_want_write_file(filp);
214         if (ret)
215                 return ret;
216
217         ret = -EFAULT;
218         if (copy_from_user(&cno, argp, sizeof(cno)))
219                 goto out;
220
221         nilfs_transaction_begin(inode->i_sb, &ti, 0);
222         ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
223         if (unlikely(ret < 0))
224                 nilfs_transaction_abort(inode->i_sb);
225         else
226                 nilfs_transaction_commit(inode->i_sb); /* never fails */
227 out:
228         mnt_drop_write_file(filp);
229         return ret;
230 }
231
232 static ssize_t
233 nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
234                           void *buf, size_t size, size_t nmembs)
235 {
236         int ret;
237
238         down_read(&nilfs->ns_segctor_sem);
239         ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
240                                       size, nmembs);
241         up_read(&nilfs->ns_segctor_sem);
242         return ret;
243 }
244
245 static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
246                                   unsigned int cmd, void __user *argp)
247 {
248         struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
249         struct nilfs_cpstat cpstat;
250         int ret;
251
252         down_read(&nilfs->ns_segctor_sem);
253         ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
254         up_read(&nilfs->ns_segctor_sem);
255         if (ret < 0)
256                 return ret;
257
258         if (copy_to_user(argp, &cpstat, sizeof(cpstat)))
259                 ret = -EFAULT;
260         return ret;
261 }
262
263 static ssize_t
264 nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
265                           void *buf, size_t size, size_t nmembs)
266 {
267         int ret;
268
269         down_read(&nilfs->ns_segctor_sem);
270         ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
271                                       nmembs);
272         up_read(&nilfs->ns_segctor_sem);
273         return ret;
274 }
275
276 static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
277                                   unsigned int cmd, void __user *argp)
278 {
279         struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
280         struct nilfs_sustat sustat;
281         int ret;
282
283         down_read(&nilfs->ns_segctor_sem);
284         ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
285         up_read(&nilfs->ns_segctor_sem);
286         if (ret < 0)
287                 return ret;
288
289         if (copy_to_user(argp, &sustat, sizeof(sustat)))
290                 ret = -EFAULT;
291         return ret;
292 }
293
294 static ssize_t
295 nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
296                          void *buf, size_t size, size_t nmembs)
297 {
298         int ret;
299
300         down_read(&nilfs->ns_segctor_sem);
301         ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs);
302         up_read(&nilfs->ns_segctor_sem);
303         return ret;
304 }
305
306 static ssize_t
307 nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
308                           void *buf, size_t size, size_t nmembs)
309 {
310         struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
311         struct nilfs_bdesc *bdescs = buf;
312         int ret, i;
313
314         down_read(&nilfs->ns_segctor_sem);
315         for (i = 0; i < nmembs; i++) {
316                 ret = nilfs_bmap_lookup_at_level(bmap,
317                                                  bdescs[i].bd_offset,
318                                                  bdescs[i].bd_level + 1,
319                                                  &bdescs[i].bd_blocknr);
320                 if (ret < 0) {
321                         if (ret != -ENOENT) {
322                                 up_read(&nilfs->ns_segctor_sem);
323                                 return ret;
324                         }
325                         bdescs[i].bd_blocknr = 0;
326                 }
327         }
328         up_read(&nilfs->ns_segctor_sem);
329         return nmembs;
330 }
331
332 static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
333                                   unsigned int cmd, void __user *argp)
334 {
335         struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
336         struct nilfs_argv argv;
337         int ret;
338
339         if (copy_from_user(&argv, argp, sizeof(argv)))
340                 return -EFAULT;
341
342         if (argv.v_size != sizeof(struct nilfs_bdesc))
343                 return -EINVAL;
344
345         ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
346                                     nilfs_ioctl_do_get_bdescs);
347         if (ret < 0)
348                 return ret;
349
350         if (copy_to_user(argp, &argv, sizeof(argv)))
351                 ret = -EFAULT;
352         return ret;
353 }
354
355 static int nilfs_ioctl_move_inode_block(struct inode *inode,
356                                         struct nilfs_vdesc *vdesc,
357                                         struct list_head *buffers)
358 {
359         struct buffer_head *bh;
360         int ret;
361
362         if (vdesc->vd_flags == 0)
363                 ret = nilfs_gccache_submit_read_data(
364                         inode, vdesc->vd_offset, vdesc->vd_blocknr,
365                         vdesc->vd_vblocknr, &bh);
366         else
367                 ret = nilfs_gccache_submit_read_node(
368                         inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
369
370         if (unlikely(ret < 0)) {
371                 if (ret == -ENOENT)
372                         printk(KERN_CRIT
373                                "%s: invalid virtual block address (%s): "
374                                "ino=%llu, cno=%llu, offset=%llu, "
375                                "blocknr=%llu, vblocknr=%llu\n",
376                                __func__, vdesc->vd_flags ? "node" : "data",
377                                (unsigned long long)vdesc->vd_ino,
378                                (unsigned long long)vdesc->vd_cno,
379                                (unsigned long long)vdesc->vd_offset,
380                                (unsigned long long)vdesc->vd_blocknr,
381                                (unsigned long long)vdesc->vd_vblocknr);
382                 return ret;
383         }
384         if (unlikely(!list_empty(&bh->b_assoc_buffers))) {
385                 printk(KERN_CRIT "%s: conflicting %s buffer: ino=%llu, "
386                        "cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu\n",
387                        __func__, vdesc->vd_flags ? "node" : "data",
388                        (unsigned long long)vdesc->vd_ino,
389                        (unsigned long long)vdesc->vd_cno,
390                        (unsigned long long)vdesc->vd_offset,
391                        (unsigned long long)vdesc->vd_blocknr,
392                        (unsigned long long)vdesc->vd_vblocknr);
393                 brelse(bh);
394                 return -EEXIST;
395         }
396         list_add_tail(&bh->b_assoc_buffers, buffers);
397         return 0;
398 }
399
400 static int nilfs_ioctl_move_blocks(struct super_block *sb,
401                                    struct nilfs_argv *argv, void *buf)
402 {
403         size_t nmembs = argv->v_nmembs;
404         struct the_nilfs *nilfs = sb->s_fs_info;
405         struct inode *inode;
406         struct nilfs_vdesc *vdesc;
407         struct buffer_head *bh, *n;
408         LIST_HEAD(buffers);
409         ino_t ino;
410         __u64 cno;
411         int i, ret;
412
413         for (i = 0, vdesc = buf; i < nmembs; ) {
414                 ino = vdesc->vd_ino;
415                 cno = vdesc->vd_cno;
416                 inode = nilfs_iget_for_gc(sb, ino, cno);
417                 if (IS_ERR(inode)) {
418                         ret = PTR_ERR(inode);
419                         goto failed;
420                 }
421                 if (list_empty(&NILFS_I(inode)->i_dirty)) {
422                         /*
423                          * Add the inode to GC inode list. Garbage Collection
424                          * is serialized and no two processes manipulate the
425                          * list simultaneously.
426                          */
427                         igrab(inode);
428                         list_add(&NILFS_I(inode)->i_dirty,
429                                  &nilfs->ns_gc_inodes);
430                 }
431
432                 do {
433                         ret = nilfs_ioctl_move_inode_block(inode, vdesc,
434                                                            &buffers);
435                         if (unlikely(ret < 0)) {
436                                 iput(inode);
437                                 goto failed;
438                         }
439                         vdesc++;
440                 } while (++i < nmembs &&
441                          vdesc->vd_ino == ino && vdesc->vd_cno == cno);
442
443                 iput(inode); /* The inode still remains in GC inode list */
444         }
445
446         list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
447                 ret = nilfs_gccache_wait_and_mark_dirty(bh);
448                 if (unlikely(ret < 0)) {
449                         WARN_ON(ret == -EEXIST);
450                         goto failed;
451                 }
452                 list_del_init(&bh->b_assoc_buffers);
453                 brelse(bh);
454         }
455         return nmembs;
456
457  failed:
458         list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
459                 list_del_init(&bh->b_assoc_buffers);
460                 brelse(bh);
461         }
462         return ret;
463 }
464
465 static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
466                                           struct nilfs_argv *argv, void *buf)
467 {
468         size_t nmembs = argv->v_nmembs;
469         struct inode *cpfile = nilfs->ns_cpfile;
470         struct nilfs_period *periods = buf;
471         int ret, i;
472
473         for (i = 0; i < nmembs; i++) {
474                 ret = nilfs_cpfile_delete_checkpoints(
475                         cpfile, periods[i].p_start, periods[i].p_end);
476                 if (ret < 0)
477                         return ret;
478         }
479         return nmembs;
480 }
481
482 static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
483                                       struct nilfs_argv *argv, void *buf)
484 {
485         size_t nmembs = argv->v_nmembs;
486         int ret;
487
488         ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs);
489
490         return (ret < 0) ? ret : nmembs;
491 }
492
493 static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
494                                          struct nilfs_argv *argv, void *buf)
495 {
496         size_t nmembs = argv->v_nmembs;
497         struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
498         struct nilfs_bdesc *bdescs = buf;
499         int ret, i;
500
501         for (i = 0; i < nmembs; i++) {
502                 /* XXX: use macro or inline func to check liveness */
503                 ret = nilfs_bmap_lookup_at_level(bmap,
504                                                  bdescs[i].bd_offset,
505                                                  bdescs[i].bd_level + 1,
506                                                  &bdescs[i].bd_blocknr);
507                 if (ret < 0) {
508                         if (ret != -ENOENT)
509                                 return ret;
510                         bdescs[i].bd_blocknr = 0;
511                 }
512                 if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr)
513                         /* skip dead block */
514                         continue;
515                 if (bdescs[i].bd_level == 0) {
516                         ret = nilfs_mdt_mark_block_dirty(nilfs->ns_dat,
517                                                          bdescs[i].bd_offset);
518                         if (ret < 0) {
519                                 WARN_ON(ret == -ENOENT);
520                                 return ret;
521                         }
522                 } else {
523                         ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset,
524                                               bdescs[i].bd_level);
525                         if (ret < 0) {
526                                 WARN_ON(ret == -ENOENT);
527                                 return ret;
528                         }
529                 }
530         }
531         return nmembs;
532 }
533
534 int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
535                                        struct nilfs_argv *argv, void **kbufs)
536 {
537         const char *msg;
538         int ret;
539
540         ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
541         if (ret < 0) {
542                 /*
543                  * can safely abort because checkpoints can be removed
544                  * independently.
545                  */
546                 msg = "cannot delete checkpoints";
547                 goto failed;
548         }
549         ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
550         if (ret < 0) {
551                 /*
552                  * can safely abort because DAT file is updated atomically
553                  * using a copy-on-write technique.
554                  */
555                 msg = "cannot delete virtual blocks from DAT file";
556                 goto failed;
557         }
558         ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
559         if (ret < 0) {
560                 /*
561                  * can safely abort because the operation is nondestructive.
562                  */
563                 msg = "cannot mark copying blocks dirty";
564                 goto failed;
565         }
566         return 0;
567
568  failed:
569         printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n",
570                msg, ret);
571         return ret;
572 }
573
574 static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
575                                       unsigned int cmd, void __user *argp)
576 {
577         struct nilfs_argv argv[5];
578         static const size_t argsz[5] = {
579                 sizeof(struct nilfs_vdesc),
580                 sizeof(struct nilfs_period),
581                 sizeof(__u64),
582                 sizeof(struct nilfs_bdesc),
583                 sizeof(__u64),
584         };
585         void __user *base;
586         void *kbufs[5];
587         struct the_nilfs *nilfs;
588         size_t len, nsegs;
589         int n, ret;
590
591         if (!capable(CAP_SYS_ADMIN))
592                 return -EPERM;
593
594         ret = mnt_want_write_file(filp);
595         if (ret)
596                 return ret;
597
598         ret = -EFAULT;
599         if (copy_from_user(argv, argp, sizeof(argv)))
600                 goto out;
601
602         ret = -EINVAL;
603         nsegs = argv[4].v_nmembs;
604         if (argv[4].v_size != argsz[4])
605                 goto out;
606
607         /*
608          * argv[4] points to segment numbers this ioctl cleans.  We
609          * use kmalloc() for its buffer because memory used for the
610          * segment numbers is enough small.
611          */
612         kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base,
613                                nsegs * sizeof(__u64));
614         if (IS_ERR(kbufs[4])) {
615                 ret = PTR_ERR(kbufs[4]);
616                 goto out;
617         }
618         nilfs = inode->i_sb->s_fs_info;
619
620         for (n = 0; n < 4; n++) {
621                 ret = -EINVAL;
622                 if (argv[n].v_size != argsz[n])
623                         goto out_free;
624
625                 if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment)
626                         goto out_free;
627
628                 if (argv[n].v_nmembs >= UINT_MAX / argv[n].v_size)
629                         goto out_free;
630
631                 len = argv[n].v_size * argv[n].v_nmembs;
632                 base = (void __user *)(unsigned long)argv[n].v_base;
633                 if (len == 0) {
634                         kbufs[n] = NULL;
635                         continue;
636                 }
637
638                 kbufs[n] = vmalloc(len);
639                 if (!kbufs[n]) {
640                         ret = -ENOMEM;
641                         goto out_free;
642                 }
643                 if (copy_from_user(kbufs[n], base, len)) {
644                         ret = -EFAULT;
645                         vfree(kbufs[n]);
646                         goto out_free;
647                 }
648         }
649
650         /*
651          * nilfs_ioctl_move_blocks() will call nilfs_iget_for_gc(),
652          * which will operates an inode list without blocking.
653          * To protect the list from concurrent operations,
654          * nilfs_ioctl_move_blocks should be atomic operation.
655          */
656         if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) {
657                 ret = -EBUSY;
658                 goto out_free;
659         }
660
661         vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
662
663         ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
664         if (ret < 0)
665                 printk(KERN_ERR "NILFS: GC failed during preparation: "
666                         "cannot read source blocks: err=%d\n", ret);
667         else
668                 ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
669
670         nilfs_remove_all_gcinodes(nilfs);
671         clear_nilfs_gc_running(nilfs);
672
673 out_free:
674         while (--n >= 0)
675                 vfree(kbufs[n]);
676         kfree(kbufs[4]);
677 out:
678         mnt_drop_write_file(filp);
679         return ret;
680 }
681
682 static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
683                             unsigned int cmd, void __user *argp)
684 {
685         __u64 cno;
686         int ret;
687         struct the_nilfs *nilfs;
688
689         ret = nilfs_construct_segment(inode->i_sb);
690         if (ret < 0)
691                 return ret;
692
693         if (argp != NULL) {
694                 nilfs = inode->i_sb->s_fs_info;
695                 down_read(&nilfs->ns_segctor_sem);
696                 cno = nilfs->ns_cno - 1;
697                 up_read(&nilfs->ns_segctor_sem);
698                 if (copy_to_user(argp, &cno, sizeof(cno)))
699                         return -EFAULT;
700         }
701         return 0;
702 }
703
704 static int nilfs_ioctl_resize(struct inode *inode, struct file *filp,
705                               void __user *argp)
706 {
707         __u64 newsize;
708         int ret = -EPERM;
709
710         if (!capable(CAP_SYS_ADMIN))
711                 goto out;
712
713         ret = mnt_want_write_file(filp);
714         if (ret)
715                 goto out;
716
717         ret = -EFAULT;
718         if (copy_from_user(&newsize, argp, sizeof(newsize)))
719                 goto out_drop_write;
720
721         ret = nilfs_resize_fs(inode->i_sb, newsize);
722
723 out_drop_write:
724         mnt_drop_write_file(filp);
725 out:
726         return ret;
727 }
728
729 static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
730 {
731         struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
732         __u64 range[2];
733         __u64 minseg, maxseg;
734         unsigned long segbytes;
735         int ret = -EPERM;
736
737         if (!capable(CAP_SYS_ADMIN))
738                 goto out;
739
740         ret = -EFAULT;
741         if (copy_from_user(range, argp, sizeof(__u64[2])))
742                 goto out;
743
744         ret = -ERANGE;
745         if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode))
746                 goto out;
747
748         segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize;
749
750         minseg = range[0] + segbytes - 1;
751         do_div(minseg, segbytes);
752         maxseg = NILFS_SB2_OFFSET_BYTES(range[1]);
753         do_div(maxseg, segbytes);
754         maxseg--;
755
756         ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg);
757 out:
758         return ret;
759 }
760
761 static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
762                                 unsigned int cmd, void __user *argp,
763                                 size_t membsz,
764                                 ssize_t (*dofunc)(struct the_nilfs *,
765                                                   __u64 *, int,
766                                                   void *, size_t, size_t))
767
768 {
769         struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
770         struct nilfs_argv argv;
771         int ret;
772
773         if (copy_from_user(&argv, argp, sizeof(argv)))
774                 return -EFAULT;
775
776         if (argv.v_size < membsz)
777                 return -EINVAL;
778
779         ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
780         if (ret < 0)
781                 return ret;
782
783         if (copy_to_user(argp, &argv, sizeof(argv)))
784                 ret = -EFAULT;
785         return ret;
786 }
787
788 long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
789 {
790         struct inode *inode = filp->f_dentry->d_inode;
791         void __user *argp = (void __user *)arg;
792
793         switch (cmd) {
794         case FS_IOC_GETFLAGS:
795                 return nilfs_ioctl_getflags(inode, argp);
796         case FS_IOC_SETFLAGS:
797                 return nilfs_ioctl_setflags(inode, filp, argp);
798         case FS_IOC_GETVERSION:
799                 return nilfs_ioctl_getversion(inode, argp);
800         case NILFS_IOCTL_CHANGE_CPMODE:
801                 return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
802         case NILFS_IOCTL_DELETE_CHECKPOINT:
803                 return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
804         case NILFS_IOCTL_GET_CPINFO:
805                 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
806                                             sizeof(struct nilfs_cpinfo),
807                                             nilfs_ioctl_do_get_cpinfo);
808         case NILFS_IOCTL_GET_CPSTAT:
809                 return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
810         case NILFS_IOCTL_GET_SUINFO:
811                 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
812                                             sizeof(struct nilfs_suinfo),
813                                             nilfs_ioctl_do_get_suinfo);
814         case NILFS_IOCTL_GET_SUSTAT:
815                 return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
816         case NILFS_IOCTL_GET_VINFO:
817                 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
818                                             sizeof(struct nilfs_vinfo),
819                                             nilfs_ioctl_do_get_vinfo);
820         case NILFS_IOCTL_GET_BDESCS:
821                 return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
822         case NILFS_IOCTL_CLEAN_SEGMENTS:
823                 return nilfs_ioctl_clean_segments(inode, filp, cmd, argp);
824         case NILFS_IOCTL_SYNC:
825                 return nilfs_ioctl_sync(inode, filp, cmd, argp);
826         case NILFS_IOCTL_RESIZE:
827                 return nilfs_ioctl_resize(inode, filp, argp);
828         case NILFS_IOCTL_SET_ALLOC_RANGE:
829                 return nilfs_ioctl_set_alloc_range(inode, argp);
830         default:
831                 return -ENOTTY;
832         }
833 }
834
835 #ifdef CONFIG_COMPAT
836 long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
837 {
838         switch (cmd) {
839         case FS_IOC32_GETFLAGS:
840                 cmd = FS_IOC_GETFLAGS;
841                 break;
842         case FS_IOC32_SETFLAGS:
843                 cmd = FS_IOC_SETFLAGS;
844                 break;
845         case FS_IOC32_GETVERSION:
846                 cmd = FS_IOC_GETVERSION;
847                 break;
848         case NILFS_IOCTL_CHANGE_CPMODE:
849         case NILFS_IOCTL_DELETE_CHECKPOINT:
850         case NILFS_IOCTL_GET_CPINFO:
851         case NILFS_IOCTL_GET_CPSTAT:
852         case NILFS_IOCTL_GET_SUINFO:
853         case NILFS_IOCTL_GET_SUSTAT:
854         case NILFS_IOCTL_GET_VINFO:
855         case NILFS_IOCTL_GET_BDESCS:
856         case NILFS_IOCTL_CLEAN_SEGMENTS:
857         case NILFS_IOCTL_SYNC:
858         case NILFS_IOCTL_RESIZE:
859         case NILFS_IOCTL_SET_ALLOC_RANGE:
860                 break;
861         default:
862                 return -ENOIOCTLCMD;
863         }
864         return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
865 }
866 #endif