nilfs2: fix possible circular locking for get information ioctls
[safe/jmp/linux-2.6] / 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/smp_lock.h>     /* lock_kernel(), unlock_kernel() */
26 #include <linux/capability.h>   /* capable() */
27 #include <linux/uaccess.h>      /* copy_from_user(), copy_to_user() */
28 #include <linux/nilfs2_fs.h>
29 #include "nilfs.h"
30 #include "segment.h"
31 #include "bmap.h"
32 #include "cpfile.h"
33 #include "sufile.h"
34 #include "dat.h"
35
36
37 static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
38                                  struct nilfs_argv *argv, int dir,
39                                  ssize_t (*dofunc)(struct the_nilfs *,
40                                                    __u64 *, int,
41                                                    void *, size_t, size_t))
42 {
43         void *buf;
44         void __user *base = (void __user *)(unsigned long)argv->v_base;
45         size_t maxmembs, total, n;
46         ssize_t nr;
47         int ret, i;
48         __u64 pos, ppos;
49
50         if (argv->v_nmembs == 0)
51                 return 0;
52
53         if (argv->v_size > PAGE_SIZE)
54                 return -EINVAL;
55
56         buf = (void *)__get_free_pages(GFP_NOFS, 0);
57         if (unlikely(!buf))
58                 return -ENOMEM;
59         maxmembs = PAGE_SIZE / argv->v_size;
60
61         ret = 0;
62         total = 0;
63         pos = argv->v_index;
64         for (i = 0; i < argv->v_nmembs; i += n) {
65                 n = (argv->v_nmembs - i < maxmembs) ?
66                         argv->v_nmembs - i : maxmembs;
67                 if ((dir & _IOC_WRITE) &&
68                     copy_from_user(buf, base + argv->v_size * i,
69                                    argv->v_size * n)) {
70                         ret = -EFAULT;
71                         break;
72                 }
73                 ppos = pos;
74                 nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size,
75                                n);
76                 if (nr < 0) {
77                         ret = nr;
78                         break;
79                 }
80                 if ((dir & _IOC_READ) &&
81                     copy_to_user(base + argv->v_size * i, buf,
82                                  argv->v_size * nr)) {
83                         ret = -EFAULT;
84                         break;
85                 }
86                 total += nr;
87                 if ((size_t)nr < n)
88                         break;
89                 if (pos == ppos)
90                         pos += n;
91         }
92         argv->v_nmembs = total;
93
94         free_pages((unsigned long)buf, 0);
95         return ret;
96 }
97
98 static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
99                                      unsigned int cmd, void __user *argp)
100 {
101         struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile;
102         struct nilfs_transaction_info ti;
103         struct nilfs_cpmode cpmode;
104         int ret;
105
106         if (!capable(CAP_SYS_ADMIN))
107                 return -EPERM;
108         if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
109                 return -EFAULT;
110
111         nilfs_transaction_begin(inode->i_sb, &ti, 0);
112         ret = nilfs_cpfile_change_cpmode(
113                 cpfile, cpmode.cm_cno, cpmode.cm_mode);
114         if (unlikely(ret < 0)) {
115                 nilfs_transaction_abort(inode->i_sb);
116                 return ret;
117         }
118         nilfs_transaction_commit(inode->i_sb); /* never fails */
119         return ret;
120 }
121
122 static int
123 nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
124                               unsigned int cmd, void __user *argp)
125 {
126         struct inode *cpfile = NILFS_SB(inode->i_sb)->s_nilfs->ns_cpfile;
127         struct nilfs_transaction_info ti;
128         __u64 cno;
129         int ret;
130
131         if (!capable(CAP_SYS_ADMIN))
132                 return -EPERM;
133         if (copy_from_user(&cno, argp, sizeof(cno)))
134                 return -EFAULT;
135
136         nilfs_transaction_begin(inode->i_sb, &ti, 0);
137         ret = nilfs_cpfile_delete_checkpoint(cpfile, cno);
138         if (unlikely(ret < 0)) {
139                 nilfs_transaction_abort(inode->i_sb);
140                 return ret;
141         }
142         nilfs_transaction_commit(inode->i_sb); /* never fails */
143         return ret;
144 }
145
146 static ssize_t
147 nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
148                           void *buf, size_t size, size_t nmembs)
149 {
150         int ret;
151
152         down_read(&nilfs->ns_segctor_sem);
153         ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
154                                       nmembs);
155         up_read(&nilfs->ns_segctor_sem);
156         return ret;
157 }
158
159 static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
160                                   unsigned int cmd, void __user *argp)
161 {
162         struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
163         struct nilfs_cpstat cpstat;
164         int ret;
165
166         down_read(&nilfs->ns_segctor_sem);
167         ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
168         up_read(&nilfs->ns_segctor_sem);
169         if (ret < 0)
170                 return ret;
171
172         if (copy_to_user(argp, &cpstat, sizeof(cpstat)))
173                 ret = -EFAULT;
174         return ret;
175 }
176
177 static ssize_t
178 nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
179                           void *buf, size_t size, size_t nmembs)
180 {
181         int ret;
182
183         down_read(&nilfs->ns_segctor_sem);
184         ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, nmembs);
185         up_read(&nilfs->ns_segctor_sem);
186         return ret;
187 }
188
189 static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
190                                   unsigned int cmd, void __user *argp)
191 {
192         struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
193         struct nilfs_sustat sustat;
194         int ret;
195
196         down_read(&nilfs->ns_segctor_sem);
197         ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
198         up_read(&nilfs->ns_segctor_sem);
199         if (ret < 0)
200                 return ret;
201
202         if (copy_to_user(argp, &sustat, sizeof(sustat)))
203                 ret = -EFAULT;
204         return ret;
205 }
206
207 static ssize_t
208 nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
209                          void *buf, size_t size, size_t nmembs)
210 {
211         int ret;
212
213         down_read(&nilfs->ns_segctor_sem);
214         ret = nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs);
215         up_read(&nilfs->ns_segctor_sem);
216         return ret;
217 }
218
219 static ssize_t
220 nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
221                           void *buf, size_t size, size_t nmembs)
222 {
223         struct inode *dat = nilfs_dat_inode(nilfs);
224         struct nilfs_bmap *bmap = NILFS_I(dat)->i_bmap;
225         struct nilfs_bdesc *bdescs = buf;
226         int ret, i;
227
228         down_read(&nilfs->ns_segctor_sem);
229         for (i = 0; i < nmembs; i++) {
230                 ret = nilfs_bmap_lookup_at_level(bmap,
231                                                  bdescs[i].bd_offset,
232                                                  bdescs[i].bd_level + 1,
233                                                  &bdescs[i].bd_blocknr);
234                 if (ret < 0) {
235                         if (ret != -ENOENT) {
236                                 up_read(&nilfs->ns_segctor_sem);
237                                 return ret;
238                         }
239                         bdescs[i].bd_blocknr = 0;
240                 }
241         }
242         up_read(&nilfs->ns_segctor_sem);
243         return nmembs;
244 }
245
246 static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
247                                   unsigned int cmd, void __user *argp)
248 {
249         struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
250         struct nilfs_argv argv;
251         int ret;
252
253         if (copy_from_user(&argv, argp, sizeof(argv)))
254                 return -EFAULT;
255
256         ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
257                                     nilfs_ioctl_do_get_bdescs);
258         if (ret < 0)
259                 return ret;
260
261         if (copy_to_user(argp, &argv, sizeof(argv)))
262                 ret = -EFAULT;
263         return ret;
264 }
265
266 static int nilfs_ioctl_move_inode_block(struct inode *inode,
267                                         struct nilfs_vdesc *vdesc,
268                                         struct list_head *buffers)
269 {
270         struct buffer_head *bh;
271         int ret;
272
273         if (vdesc->vd_flags == 0)
274                 ret = nilfs_gccache_submit_read_data(
275                         inode, vdesc->vd_offset, vdesc->vd_blocknr,
276                         vdesc->vd_vblocknr, &bh);
277         else
278                 ret = nilfs_gccache_submit_read_node(
279                         inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
280
281         if (unlikely(ret < 0)) {
282                 if (ret == -ENOENT)
283                         printk(KERN_CRIT
284                                "%s: invalid virtual block address (%s): "
285                                "ino=%llu, cno=%llu, offset=%llu, "
286                                "blocknr=%llu, vblocknr=%llu\n",
287                                __func__, vdesc->vd_flags ? "node" : "data",
288                                (unsigned long long)vdesc->vd_ino,
289                                (unsigned long long)vdesc->vd_cno,
290                                (unsigned long long)vdesc->vd_offset,
291                                (unsigned long long)vdesc->vd_blocknr,
292                                (unsigned long long)vdesc->vd_vblocknr);
293                 return ret;
294         }
295         bh->b_private = vdesc;
296         list_add_tail(&bh->b_assoc_buffers, buffers);
297         return 0;
298 }
299
300 static ssize_t
301 nilfs_ioctl_do_move_blocks(struct the_nilfs *nilfs, __u64 *posp, int flags,
302                            void *buf, size_t size, size_t nmembs)
303 {
304         struct inode *inode;
305         struct nilfs_vdesc *vdesc;
306         struct buffer_head *bh, *n;
307         LIST_HEAD(buffers);
308         ino_t ino;
309         __u64 cno;
310         int i, ret;
311
312         for (i = 0, vdesc = buf; i < nmembs; ) {
313                 ino = vdesc->vd_ino;
314                 cno = vdesc->vd_cno;
315                 inode = nilfs_gc_iget(nilfs, ino, cno);
316                 if (unlikely(inode == NULL)) {
317                         ret = -ENOMEM;
318                         goto failed;
319                 }
320                 do {
321                         ret = nilfs_ioctl_move_inode_block(inode, vdesc,
322                                                            &buffers);
323                         if (unlikely(ret < 0))
324                                 goto failed;
325                         vdesc++;
326                 } while (++i < nmembs &&
327                          vdesc->vd_ino == ino && vdesc->vd_cno == cno);
328         }
329
330         list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
331                 ret = nilfs_gccache_wait_and_mark_dirty(bh);
332                 if (unlikely(ret < 0)) {
333                         if (ret == -EEXIST) {
334                                 vdesc = bh->b_private;
335                                 printk(KERN_CRIT
336                                        "%s: conflicting %s buffer: "
337                                        "ino=%llu, cno=%llu, offset=%llu, "
338                                        "blocknr=%llu, vblocknr=%llu\n",
339                                        __func__,
340                                        vdesc->vd_flags ? "node" : "data",
341                                        (unsigned long long)vdesc->vd_ino,
342                                        (unsigned long long)vdesc->vd_cno,
343                                        (unsigned long long)vdesc->vd_offset,
344                                        (unsigned long long)vdesc->vd_blocknr,
345                                        (unsigned long long)vdesc->vd_vblocknr);
346                         }
347                         goto failed;
348                 }
349                 list_del_init(&bh->b_assoc_buffers);
350                 bh->b_private = NULL;
351                 brelse(bh);
352         }
353         return nmembs;
354
355  failed:
356         list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
357                 list_del_init(&bh->b_assoc_buffers);
358                 bh->b_private = NULL;
359                 brelse(bh);
360         }
361         return ret;
362 }
363
364 static inline int nilfs_ioctl_move_blocks(struct the_nilfs *nilfs,
365                                           struct nilfs_argv *argv,
366                                           int dir)
367 {
368         return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
369                                      nilfs_ioctl_do_move_blocks);
370 }
371
372 static ssize_t
373 nilfs_ioctl_do_delete_checkpoints(struct the_nilfs *nilfs, __u64 *posp,
374                                   int flags, void *buf, size_t size,
375                                   size_t nmembs)
376 {
377         struct inode *cpfile = nilfs->ns_cpfile;
378         struct nilfs_period *periods = buf;
379         int ret, i;
380
381         for (i = 0; i < nmembs; i++) {
382                 ret = nilfs_cpfile_delete_checkpoints(
383                         cpfile, periods[i].p_start, periods[i].p_end);
384                 if (ret < 0)
385                         return ret;
386         }
387         return nmembs;
388 }
389
390 static inline int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
391                                                  struct nilfs_argv *argv,
392                                                  int dir)
393 {
394         return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
395                                      nilfs_ioctl_do_delete_checkpoints);
396 }
397
398 static ssize_t
399 nilfs_ioctl_do_free_vblocknrs(struct the_nilfs *nilfs, __u64 *posp, int flags,
400                               void *buf, size_t size, size_t nmembs)
401 {
402         int ret = nilfs_dat_freev(nilfs_dat_inode(nilfs), buf, nmembs);
403
404         return (ret < 0) ? ret : nmembs;
405 }
406
407 static inline int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
408                                              struct nilfs_argv *argv,
409                                              int dir)
410 {
411         return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
412                                      nilfs_ioctl_do_free_vblocknrs);
413 }
414
415 static ssize_t
416 nilfs_ioctl_do_mark_blocks_dirty(struct the_nilfs *nilfs, __u64 *posp,
417                                  int flags, void *buf, size_t size,
418                                  size_t nmembs)
419 {
420         struct inode *dat = nilfs_dat_inode(nilfs);
421         struct nilfs_bmap *bmap = NILFS_I(dat)->i_bmap;
422         struct nilfs_bdesc *bdescs = buf;
423         int ret, i;
424
425         for (i = 0; i < nmembs; i++) {
426                 /* XXX: use macro or inline func to check liveness */
427                 ret = nilfs_bmap_lookup_at_level(bmap,
428                                                  bdescs[i].bd_offset,
429                                                  bdescs[i].bd_level + 1,
430                                                  &bdescs[i].bd_blocknr);
431                 if (ret < 0) {
432                         if (ret != -ENOENT)
433                                 return ret;
434                         bdescs[i].bd_blocknr = 0;
435                 }
436                 if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr)
437                         /* skip dead block */
438                         continue;
439                 if (bdescs[i].bd_level == 0) {
440                         ret = nilfs_mdt_mark_block_dirty(dat,
441                                                          bdescs[i].bd_offset);
442                         if (ret < 0) {
443                                 WARN_ON(ret == -ENOENT);
444                                 return ret;
445                         }
446                 } else {
447                         ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset,
448                                               bdescs[i].bd_level);
449                         if (ret < 0) {
450                                 WARN_ON(ret == -ENOENT);
451                                 return ret;
452                         }
453                 }
454         }
455         return nmembs;
456 }
457
458 static inline int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
459                                                 struct nilfs_argv *argv,
460                                                 int dir)
461 {
462         return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
463                                      nilfs_ioctl_do_mark_blocks_dirty);
464 }
465
466 static ssize_t
467 nilfs_ioctl_do_free_segments(struct the_nilfs *nilfs, __u64 *posp, int flags,
468                              void *buf, size_t size, size_t nmembs)
469 {
470         struct nilfs_sb_info *sbi = nilfs->ns_writer;
471         int ret;
472
473         if (unlikely(!sbi)) {
474                 /* never happens because called for a writable mount */
475                 WARN_ON(1);
476                 return -EROFS;
477         }
478         ret = nilfs_segctor_add_segments_to_be_freed(
479                 NILFS_SC(sbi), buf, nmembs);
480
481         return (ret < 0) ? ret : nmembs;
482 }
483
484 static inline int nilfs_ioctl_free_segments(struct the_nilfs *nilfs,
485                                              struct nilfs_argv *argv,
486                                              int dir)
487 {
488         return nilfs_ioctl_wrap_copy(nilfs, argv, dir,
489                                      nilfs_ioctl_do_free_segments);
490 }
491
492 int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
493                                        void __user *argp)
494 {
495         struct nilfs_argv argv[5];
496         const char *msg;
497         int dir, ret;
498
499         if (copy_from_user(argv, argp, sizeof(argv)))
500                 return -EFAULT;
501
502         dir = _IOC_WRITE;
503         ret = nilfs_ioctl_move_blocks(nilfs, &argv[0], dir);
504         if (ret < 0) {
505                 msg = "cannot read source blocks";
506                 goto failed;
507         }
508         ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], dir);
509         if (ret < 0) {
510                 /*
511                  * can safely abort because checkpoints can be removed
512                  * independently.
513                  */
514                 msg = "cannot delete checkpoints";
515                 goto failed;
516         }
517         ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], dir);
518         if (ret < 0) {
519                 /*
520                  * can safely abort because DAT file is updated atomically
521                  * using a copy-on-write technique.
522                  */
523                 msg = "cannot delete virtual blocks from DAT file";
524                 goto failed;
525         }
526         ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], dir);
527         if (ret < 0) {
528                 /*
529                  * can safely abort because the operation is nondestructive.
530                  */
531                 msg = "cannot mark copying blocks dirty";
532                 goto failed;
533         }
534         ret = nilfs_ioctl_free_segments(nilfs, &argv[4], dir);
535         if (ret < 0) {
536                 /*
537                  * can safely abort because this operation is atomic.
538                  */
539                 msg = "cannot set segments to be freed";
540                 goto failed;
541         }
542         return 0;
543
544  failed:
545         nilfs_remove_all_gcinode(nilfs);
546         printk(KERN_ERR "NILFS: GC failed during preparation: %s: err=%d\n",
547                msg, ret);
548         return ret;
549 }
550
551 static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
552                                       unsigned int cmd, void __user *argp)
553 {
554         if (!capable(CAP_SYS_ADMIN))
555                 return -EPERM;
556         return nilfs_clean_segments(inode->i_sb, argp);
557 }
558
559 static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
560                             unsigned int cmd, void __user *argp)
561 {
562         __u64 cno;
563         int ret;
564
565         ret = nilfs_construct_segment(inode->i_sb);
566         if (ret < 0)
567                 return ret;
568
569         if (argp != NULL) {
570                 cno = NILFS_SB(inode->i_sb)->s_nilfs->ns_cno - 1;
571                 if (copy_to_user(argp, &cno, sizeof(cno)))
572                         return -EFAULT;
573         }
574         return 0;
575 }
576
577 static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
578                                 unsigned int cmd, void __user *argp,
579                                 ssize_t (*dofunc)(struct the_nilfs *,
580                                                   __u64 *, int,
581                                                   void *, size_t, size_t))
582
583 {
584         struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
585         struct nilfs_argv argv;
586         int ret;
587
588         if (copy_from_user(&argv, argp, sizeof(argv)))
589                 return -EFAULT;
590
591         ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
592         if (ret < 0)
593                 return ret;
594
595         if (copy_to_user(argp, &argv, sizeof(argv)))
596                 ret = -EFAULT;
597         return ret;
598 }
599
600 long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
601 {
602         struct inode *inode = filp->f_dentry->d_inode;
603         void __user *argp = (void * __user *)arg;
604
605         switch (cmd) {
606         case NILFS_IOCTL_CHANGE_CPMODE:
607                 return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
608         case NILFS_IOCTL_DELETE_CHECKPOINT:
609                 return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
610         case NILFS_IOCTL_GET_CPINFO:
611                 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
612                                             nilfs_ioctl_do_get_cpinfo);
613         case NILFS_IOCTL_GET_CPSTAT:
614                 return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
615         case NILFS_IOCTL_GET_SUINFO:
616                 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
617                                             nilfs_ioctl_do_get_suinfo);
618         case NILFS_IOCTL_GET_SUSTAT:
619                 return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
620         case NILFS_IOCTL_GET_VINFO:
621                 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
622                                             nilfs_ioctl_do_get_vinfo);
623         case NILFS_IOCTL_GET_BDESCS:
624                 return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
625         case NILFS_IOCTL_CLEAN_SEGMENTS:
626                 return nilfs_ioctl_clean_segments(inode, filp, cmd, argp);
627         case NILFS_IOCTL_SYNC:
628                 return nilfs_ioctl_sync(inode, filp, cmd, argp);
629         default:
630                 return -ENOTTY;
631         }
632 }