1
2
3
4
5
6
7
8
9
10#include <linux/fs.h>
11#include <linux/wait.h>
12#include <linux/slab.h>
13#include <linux/capability.h>
14#include <linux/uaccess.h>
15#include <linux/vmalloc.h>
16#include <linux/compat.h>
17#include <linux/mount.h>
18#include <linux/buffer_head.h>
19#include "nilfs.h"
20#include "segment.h"
21#include "bmap.h"
22#include "cpfile.h"
23#include "sufile.h"
24#include "dat.h"
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
47 struct nilfs_argv *argv, int dir,
48 ssize_t (*dofunc)(struct the_nilfs *,
49 __u64 *, int,
50 void *, size_t, size_t))
51{
52 void *buf;
53 void __user *base = (void __user *)(unsigned long)argv->v_base;
54 size_t maxmembs, total, n;
55 ssize_t nr;
56 int ret, i;
57 __u64 pos, ppos;
58
59 if (argv->v_nmembs == 0)
60 return 0;
61
62 if (argv->v_size > PAGE_SIZE)
63 return -EINVAL;
64
65
66
67
68
69
70 if (argv->v_index > ~(__u64)0 - argv->v_nmembs)
71 return -EINVAL;
72
73 buf = (void *)__get_free_pages(GFP_NOFS, 0);
74 if (unlikely(!buf))
75 return -ENOMEM;
76 maxmembs = PAGE_SIZE / argv->v_size;
77
78 ret = 0;
79 total = 0;
80 pos = argv->v_index;
81 for (i = 0; i < argv->v_nmembs; i += n) {
82 n = (argv->v_nmembs - i < maxmembs) ?
83 argv->v_nmembs - i : maxmembs;
84 if ((dir & _IOC_WRITE) &&
85 copy_from_user(buf, base + argv->v_size * i,
86 argv->v_size * n)) {
87 ret = -EFAULT;
88 break;
89 }
90 ppos = pos;
91 nr = dofunc(nilfs, &pos, argv->v_flags, buf, argv->v_size,
92 n);
93 if (nr < 0) {
94 ret = nr;
95 break;
96 }
97 if ((dir & _IOC_READ) &&
98 copy_to_user(base + argv->v_size * i, buf,
99 argv->v_size * nr)) {
100 ret = -EFAULT;
101 break;
102 }
103 total += nr;
104 if ((size_t)nr < n)
105 break;
106 if (pos == ppos)
107 pos += n;
108 }
109 argv->v_nmembs = total;
110
111 free_pages((unsigned long)buf, 0);
112 return ret;
113}
114
115
116
117
118static int nilfs_ioctl_getflags(struct inode *inode, void __user *argp)
119{
120 unsigned int flags = NILFS_I(inode)->i_flags & FS_FL_USER_VISIBLE;
121
122 return put_user(flags, (int __user *)argp);
123}
124
125
126
127
128static int nilfs_ioctl_setflags(struct inode *inode, struct file *filp,
129 void __user *argp)
130{
131 struct nilfs_transaction_info ti;
132 unsigned int flags, oldflags;
133 int ret;
134
135 if (!inode_owner_or_capable(inode))
136 return -EACCES;
137
138 if (get_user(flags, (int __user *)argp))
139 return -EFAULT;
140
141 ret = mnt_want_write_file(filp);
142 if (ret)
143 return ret;
144
145 flags = nilfs_mask_flags(inode->i_mode, flags);
146
147 inode_lock(inode);
148
149 oldflags = NILFS_I(inode)->i_flags;
150
151
152
153
154
155 ret = -EPERM;
156 if (((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) &&
157 !capable(CAP_LINUX_IMMUTABLE))
158 goto out;
159
160 ret = nilfs_transaction_begin(inode->i_sb, &ti, 0);
161 if (ret)
162 goto out;
163
164 NILFS_I(inode)->i_flags = (oldflags & ~FS_FL_USER_MODIFIABLE) |
165 (flags & FS_FL_USER_MODIFIABLE);
166
167 nilfs_set_inode_flags(inode);
168 inode->i_ctime = current_time(inode);
169 if (IS_SYNC(inode))
170 nilfs_set_transaction_flag(NILFS_TI_SYNC);
171
172 nilfs_mark_inode_dirty(inode);
173 ret = nilfs_transaction_commit(inode->i_sb);
174out:
175 inode_unlock(inode);
176 mnt_drop_write_file(filp);
177 return ret;
178}
179
180
181
182
183static int nilfs_ioctl_getversion(struct inode *inode, void __user *argp)
184{
185 return put_user(inode->i_generation, (int __user *)argp);
186}
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp,
208 unsigned int cmd, void __user *argp)
209{
210 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
211 struct nilfs_transaction_info ti;
212 struct nilfs_cpmode cpmode;
213 int ret;
214
215 if (!capable(CAP_SYS_ADMIN))
216 return -EPERM;
217
218 ret = mnt_want_write_file(filp);
219 if (ret)
220 return ret;
221
222 ret = -EFAULT;
223 if (copy_from_user(&cpmode, argp, sizeof(cpmode)))
224 goto out;
225
226 mutex_lock(&nilfs->ns_snapshot_mount_mutex);
227
228 nilfs_transaction_begin(inode->i_sb, &ti, 0);
229 ret = nilfs_cpfile_change_cpmode(
230 nilfs->ns_cpfile, cpmode.cm_cno, cpmode.cm_mode);
231 if (unlikely(ret < 0))
232 nilfs_transaction_abort(inode->i_sb);
233 else
234 nilfs_transaction_commit(inode->i_sb);
235
236 mutex_unlock(&nilfs->ns_snapshot_mount_mutex);
237out:
238 mnt_drop_write_file(filp);
239 return ret;
240}
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261static int
262nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
263 unsigned int cmd, void __user *argp)
264{
265 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
266 struct nilfs_transaction_info ti;
267 __u64 cno;
268 int ret;
269
270 if (!capable(CAP_SYS_ADMIN))
271 return -EPERM;
272
273 ret = mnt_want_write_file(filp);
274 if (ret)
275 return ret;
276
277 ret = -EFAULT;
278 if (copy_from_user(&cno, argp, sizeof(cno)))
279 goto out;
280
281 nilfs_transaction_begin(inode->i_sb, &ti, 0);
282 ret = nilfs_cpfile_delete_checkpoint(nilfs->ns_cpfile, cno);
283 if (unlikely(ret < 0))
284 nilfs_transaction_abort(inode->i_sb);
285 else
286 nilfs_transaction_commit(inode->i_sb);
287out:
288 mnt_drop_write_file(filp);
289 return ret;
290}
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307static ssize_t
308nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
309 void *buf, size_t size, size_t nmembs)
310{
311 int ret;
312
313 down_read(&nilfs->ns_segctor_sem);
314 ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
315 size, nmembs);
316 up_read(&nilfs->ns_segctor_sem);
317 return ret;
318}
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341static int nilfs_ioctl_get_cpstat(struct inode *inode, struct file *filp,
342 unsigned int cmd, void __user *argp)
343{
344 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
345 struct nilfs_cpstat cpstat;
346 int ret;
347
348 down_read(&nilfs->ns_segctor_sem);
349 ret = nilfs_cpfile_get_stat(nilfs->ns_cpfile, &cpstat);
350 up_read(&nilfs->ns_segctor_sem);
351 if (ret < 0)
352 return ret;
353
354 if (copy_to_user(argp, &cpstat, sizeof(cpstat)))
355 ret = -EFAULT;
356 return ret;
357}
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374static ssize_t
375nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
376 void *buf, size_t size, size_t nmembs)
377{
378 int ret;
379
380 down_read(&nilfs->ns_segctor_sem);
381 ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
382 nmembs);
383 up_read(&nilfs->ns_segctor_sem);
384 return ret;
385}
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408static int nilfs_ioctl_get_sustat(struct inode *inode, struct file *filp,
409 unsigned int cmd, void __user *argp)
410{
411 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
412 struct nilfs_sustat sustat;
413 int ret;
414
415 down_read(&nilfs->ns_segctor_sem);
416 ret = nilfs_sufile_get_stat(nilfs->ns_sufile, &sustat);
417 up_read(&nilfs->ns_segctor_sem);
418 if (ret < 0)
419 return ret;
420
421 if (copy_to_user(argp, &sustat, sizeof(sustat)))
422 ret = -EFAULT;
423 return ret;
424}
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441static ssize_t
442nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
443 void *buf, size_t size, size_t nmembs)
444{
445 int ret;
446
447 down_read(&nilfs->ns_segctor_sem);
448 ret = nilfs_dat_get_vinfo(nilfs->ns_dat, buf, size, nmembs);
449 up_read(&nilfs->ns_segctor_sem);
450 return ret;
451}
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468static ssize_t
469nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
470 void *buf, size_t size, size_t nmembs)
471{
472 struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
473 struct nilfs_bdesc *bdescs = buf;
474 int ret, i;
475
476 down_read(&nilfs->ns_segctor_sem);
477 for (i = 0; i < nmembs; i++) {
478 ret = nilfs_bmap_lookup_at_level(bmap,
479 bdescs[i].bd_offset,
480 bdescs[i].bd_level + 1,
481 &bdescs[i].bd_blocknr);
482 if (ret < 0) {
483 if (ret != -ENOENT) {
484 up_read(&nilfs->ns_segctor_sem);
485 return ret;
486 }
487 bdescs[i].bd_blocknr = 0;
488 }
489 }
490 up_read(&nilfs->ns_segctor_sem);
491 return nmembs;
492}
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517static int nilfs_ioctl_get_bdescs(struct inode *inode, struct file *filp,
518 unsigned int cmd, void __user *argp)
519{
520 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
521 struct nilfs_argv argv;
522 int ret;
523
524 if (copy_from_user(&argv, argp, sizeof(argv)))
525 return -EFAULT;
526
527 if (argv.v_size != sizeof(struct nilfs_bdesc))
528 return -EINVAL;
529
530 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd),
531 nilfs_ioctl_do_get_bdescs);
532 if (ret < 0)
533 return ret;
534
535 if (copy_to_user(argp, &argv, sizeof(argv)))
536 ret = -EFAULT;
537 return ret;
538}
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560static int nilfs_ioctl_move_inode_block(struct inode *inode,
561 struct nilfs_vdesc *vdesc,
562 struct list_head *buffers)
563{
564 struct buffer_head *bh;
565 int ret;
566
567 if (vdesc->vd_flags == 0)
568 ret = nilfs_gccache_submit_read_data(
569 inode, vdesc->vd_offset, vdesc->vd_blocknr,
570 vdesc->vd_vblocknr, &bh);
571 else
572 ret = nilfs_gccache_submit_read_node(
573 inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh);
574
575 if (unlikely(ret < 0)) {
576 if (ret == -ENOENT)
577 nilfs_msg(inode->i_sb, KERN_CRIT,
578 "%s: invalid virtual block address (%s): ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu",
579 __func__, vdesc->vd_flags ? "node" : "data",
580 (unsigned long long)vdesc->vd_ino,
581 (unsigned long long)vdesc->vd_cno,
582 (unsigned long long)vdesc->vd_offset,
583 (unsigned long long)vdesc->vd_blocknr,
584 (unsigned long long)vdesc->vd_vblocknr);
585 return ret;
586 }
587 if (unlikely(!list_empty(&bh->b_assoc_buffers))) {
588 nilfs_msg(inode->i_sb, KERN_CRIT,
589 "%s: conflicting %s buffer: ino=%llu, cno=%llu, offset=%llu, blocknr=%llu, vblocknr=%llu",
590 __func__, vdesc->vd_flags ? "node" : "data",
591 (unsigned long long)vdesc->vd_ino,
592 (unsigned long long)vdesc->vd_cno,
593 (unsigned long long)vdesc->vd_offset,
594 (unsigned long long)vdesc->vd_blocknr,
595 (unsigned long long)vdesc->vd_vblocknr);
596 brelse(bh);
597 return -EEXIST;
598 }
599 list_add_tail(&bh->b_assoc_buffers, buffers);
600 return 0;
601}
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616static int nilfs_ioctl_move_blocks(struct super_block *sb,
617 struct nilfs_argv *argv, void *buf)
618{
619 size_t nmembs = argv->v_nmembs;
620 struct the_nilfs *nilfs = sb->s_fs_info;
621 struct inode *inode;
622 struct nilfs_vdesc *vdesc;
623 struct buffer_head *bh, *n;
624 LIST_HEAD(buffers);
625 ino_t ino;
626 __u64 cno;
627 int i, ret;
628
629 for (i = 0, vdesc = buf; i < nmembs; ) {
630 ino = vdesc->vd_ino;
631 cno = vdesc->vd_cno;
632 inode = nilfs_iget_for_gc(sb, ino, cno);
633 if (IS_ERR(inode)) {
634 ret = PTR_ERR(inode);
635 goto failed;
636 }
637 if (list_empty(&NILFS_I(inode)->i_dirty)) {
638
639
640
641
642
643 igrab(inode);
644 list_add(&NILFS_I(inode)->i_dirty,
645 &nilfs->ns_gc_inodes);
646 }
647
648 do {
649 ret = nilfs_ioctl_move_inode_block(inode, vdesc,
650 &buffers);
651 if (unlikely(ret < 0)) {
652 iput(inode);
653 goto failed;
654 }
655 vdesc++;
656 } while (++i < nmembs &&
657 vdesc->vd_ino == ino && vdesc->vd_cno == cno);
658
659 iput(inode);
660 }
661
662 list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
663 ret = nilfs_gccache_wait_and_mark_dirty(bh);
664 if (unlikely(ret < 0)) {
665 WARN_ON(ret == -EEXIST);
666 goto failed;
667 }
668 list_del_init(&bh->b_assoc_buffers);
669 brelse(bh);
670 }
671 return nmembs;
672
673 failed:
674 list_for_each_entry_safe(bh, n, &buffers, b_assoc_buffers) {
675 list_del_init(&bh->b_assoc_buffers);
676 brelse(bh);
677 }
678 return ret;
679}
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700static int nilfs_ioctl_delete_checkpoints(struct the_nilfs *nilfs,
701 struct nilfs_argv *argv, void *buf)
702{
703 size_t nmembs = argv->v_nmembs;
704 struct inode *cpfile = nilfs->ns_cpfile;
705 struct nilfs_period *periods = buf;
706 int ret, i;
707
708 for (i = 0; i < nmembs; i++) {
709 ret = nilfs_cpfile_delete_checkpoints(
710 cpfile, periods[i].p_start, periods[i].p_end);
711 if (ret < 0)
712 return ret;
713 }
714 return nmembs;
715}
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735static int nilfs_ioctl_free_vblocknrs(struct the_nilfs *nilfs,
736 struct nilfs_argv *argv, void *buf)
737{
738 size_t nmembs = argv->v_nmembs;
739 int ret;
740
741 ret = nilfs_dat_freev(nilfs->ns_dat, buf, nmembs);
742
743 return (ret < 0) ? ret : nmembs;
744}
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
765 struct nilfs_argv *argv, void *buf)
766{
767 size_t nmembs = argv->v_nmembs;
768 struct nilfs_bmap *bmap = NILFS_I(nilfs->ns_dat)->i_bmap;
769 struct nilfs_bdesc *bdescs = buf;
770 struct buffer_head *bh;
771 int ret, i;
772
773 for (i = 0; i < nmembs; i++) {
774
775 ret = nilfs_bmap_lookup_at_level(bmap,
776 bdescs[i].bd_offset,
777 bdescs[i].bd_level + 1,
778 &bdescs[i].bd_blocknr);
779 if (ret < 0) {
780 if (ret != -ENOENT)
781 return ret;
782 bdescs[i].bd_blocknr = 0;
783 }
784 if (bdescs[i].bd_blocknr != bdescs[i].bd_oblocknr)
785
786 continue;
787 if (bdescs[i].bd_level == 0) {
788 ret = nilfs_mdt_get_block(nilfs->ns_dat,
789 bdescs[i].bd_offset,
790 false, NULL, &bh);
791 if (unlikely(ret)) {
792 WARN_ON(ret == -ENOENT);
793 return ret;
794 }
795 mark_buffer_dirty(bh);
796 nilfs_mdt_mark_dirty(nilfs->ns_dat);
797 put_bh(bh);
798 } else {
799 ret = nilfs_bmap_mark(bmap, bdescs[i].bd_offset,
800 bdescs[i].bd_level);
801 if (ret < 0) {
802 WARN_ON(ret == -ENOENT);
803 return ret;
804 }
805 }
806 }
807 return nmembs;
808}
809
810int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
811 struct nilfs_argv *argv, void **kbufs)
812{
813 const char *msg;
814 int ret;
815
816 ret = nilfs_ioctl_delete_checkpoints(nilfs, &argv[1], kbufs[1]);
817 if (ret < 0) {
818
819
820
821
822 msg = "cannot delete checkpoints";
823 goto failed;
824 }
825 ret = nilfs_ioctl_free_vblocknrs(nilfs, &argv[2], kbufs[2]);
826 if (ret < 0) {
827
828
829
830
831 msg = "cannot delete virtual blocks from DAT file";
832 goto failed;
833 }
834 ret = nilfs_ioctl_mark_blocks_dirty(nilfs, &argv[3], kbufs[3]);
835 if (ret < 0) {
836
837
838
839 msg = "cannot mark copying blocks dirty";
840 goto failed;
841 }
842 return 0;
843
844 failed:
845 nilfs_msg(nilfs->ns_sb, KERN_ERR, "error %d preparing GC: %s", ret,
846 msg);
847 return ret;
848}
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp,
865 unsigned int cmd, void __user *argp)
866{
867 struct nilfs_argv argv[5];
868 static const size_t argsz[5] = {
869 sizeof(struct nilfs_vdesc),
870 sizeof(struct nilfs_period),
871 sizeof(__u64),
872 sizeof(struct nilfs_bdesc),
873 sizeof(__u64),
874 };
875 void __user *base;
876 void *kbufs[5];
877 struct the_nilfs *nilfs;
878 size_t len, nsegs;
879 int n, ret;
880
881 if (!capable(CAP_SYS_ADMIN))
882 return -EPERM;
883
884 ret = mnt_want_write_file(filp);
885 if (ret)
886 return ret;
887
888 ret = -EFAULT;
889 if (copy_from_user(argv, argp, sizeof(argv)))
890 goto out;
891
892 ret = -EINVAL;
893 nsegs = argv[4].v_nmembs;
894 if (argv[4].v_size != argsz[4])
895 goto out;
896 if (nsegs > UINT_MAX / sizeof(__u64))
897 goto out;
898
899
900
901
902
903
904 kbufs[4] = memdup_user((void __user *)(unsigned long)argv[4].v_base,
905 nsegs * sizeof(__u64));
906 if (IS_ERR(kbufs[4])) {
907 ret = PTR_ERR(kbufs[4]);
908 goto out;
909 }
910 nilfs = inode->i_sb->s_fs_info;
911
912 for (n = 0; n < 4; n++) {
913 ret = -EINVAL;
914 if (argv[n].v_size != argsz[n])
915 goto out_free;
916
917 if (argv[n].v_nmembs > nsegs * nilfs->ns_blocks_per_segment)
918 goto out_free;
919
920 if (argv[n].v_nmembs >= UINT_MAX / argv[n].v_size)
921 goto out_free;
922
923 len = argv[n].v_size * argv[n].v_nmembs;
924 base = (void __user *)(unsigned long)argv[n].v_base;
925 if (len == 0) {
926 kbufs[n] = NULL;
927 continue;
928 }
929
930 kbufs[n] = vmalloc(len);
931 if (!kbufs[n]) {
932 ret = -ENOMEM;
933 goto out_free;
934 }
935 if (copy_from_user(kbufs[n], base, len)) {
936 ret = -EFAULT;
937 vfree(kbufs[n]);
938 goto out_free;
939 }
940 }
941
942
943
944
945
946
947
948 if (test_and_set_bit(THE_NILFS_GC_RUNNING, &nilfs->ns_flags)) {
949 ret = -EBUSY;
950 goto out_free;
951 }
952
953 ret = nilfs_ioctl_move_blocks(inode->i_sb, &argv[0], kbufs[0]);
954 if (ret < 0) {
955 nilfs_msg(inode->i_sb, KERN_ERR,
956 "error %d preparing GC: cannot read source blocks",
957 ret);
958 } else {
959 if (nilfs_sb_need_update(nilfs))
960 set_nilfs_discontinued(nilfs);
961 ret = nilfs_clean_segments(inode->i_sb, argv, kbufs);
962 }
963
964 nilfs_remove_all_gcinodes(nilfs);
965 clear_nilfs_gc_running(nilfs);
966
967out_free:
968 while (--n >= 0)
969 vfree(kbufs[n]);
970 kfree(kbufs[4]);
971out:
972 mnt_drop_write_file(filp);
973 return ret;
974}
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003static int nilfs_ioctl_sync(struct inode *inode, struct file *filp,
1004 unsigned int cmd, void __user *argp)
1005{
1006 __u64 cno;
1007 int ret;
1008 struct the_nilfs *nilfs;
1009
1010 ret = nilfs_construct_segment(inode->i_sb);
1011 if (ret < 0)
1012 return ret;
1013
1014 nilfs = inode->i_sb->s_fs_info;
1015 ret = nilfs_flush_device(nilfs);
1016 if (ret < 0)
1017 return ret;
1018
1019 if (argp != NULL) {
1020 down_read(&nilfs->ns_segctor_sem);
1021 cno = nilfs->ns_cno - 1;
1022 up_read(&nilfs->ns_segctor_sem);
1023 if (copy_to_user(argp, &cno, sizeof(cno)))
1024 return -EFAULT;
1025 }
1026 return 0;
1027}
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037static int nilfs_ioctl_resize(struct inode *inode, struct file *filp,
1038 void __user *argp)
1039{
1040 __u64 newsize;
1041 int ret = -EPERM;
1042
1043 if (!capable(CAP_SYS_ADMIN))
1044 goto out;
1045
1046 ret = mnt_want_write_file(filp);
1047 if (ret)
1048 goto out;
1049
1050 ret = -EFAULT;
1051 if (copy_from_user(&newsize, argp, sizeof(newsize)))
1052 goto out_drop_write;
1053
1054 ret = nilfs_resize_fs(inode->i_sb, newsize);
1055
1056out_drop_write:
1057 mnt_drop_write_file(filp);
1058out:
1059 return ret;
1060}
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073static int nilfs_ioctl_trim_fs(struct inode *inode, void __user *argp)
1074{
1075 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1076 struct request_queue *q = bdev_get_queue(nilfs->ns_bdev);
1077 struct fstrim_range range;
1078 int ret;
1079
1080 if (!capable(CAP_SYS_ADMIN))
1081 return -EPERM;
1082
1083 if (!blk_queue_discard(q))
1084 return -EOPNOTSUPP;
1085
1086 if (copy_from_user(&range, argp, sizeof(range)))
1087 return -EFAULT;
1088
1089 range.minlen = max_t(u64, range.minlen, q->limits.discard_granularity);
1090
1091 down_read(&nilfs->ns_segctor_sem);
1092 ret = nilfs_sufile_trim_fs(nilfs->ns_sufile, &range);
1093 up_read(&nilfs->ns_segctor_sem);
1094
1095 if (ret < 0)
1096 return ret;
1097
1098 if (copy_to_user(argp, &range, sizeof(range)))
1099 return -EFAULT;
1100
1101 return 0;
1102}
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115static int nilfs_ioctl_set_alloc_range(struct inode *inode, void __user *argp)
1116{
1117 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1118 __u64 range[2];
1119 __u64 minseg, maxseg;
1120 unsigned long segbytes;
1121 int ret = -EPERM;
1122
1123 if (!capable(CAP_SYS_ADMIN))
1124 goto out;
1125
1126 ret = -EFAULT;
1127 if (copy_from_user(range, argp, sizeof(__u64[2])))
1128 goto out;
1129
1130 ret = -ERANGE;
1131 if (range[1] > i_size_read(inode->i_sb->s_bdev->bd_inode))
1132 goto out;
1133
1134 segbytes = nilfs->ns_blocks_per_segment * nilfs->ns_blocksize;
1135
1136 minseg = range[0] + segbytes - 1;
1137 do_div(minseg, segbytes);
1138 maxseg = NILFS_SB2_OFFSET_BYTES(range[1]);
1139 do_div(maxseg, segbytes);
1140 maxseg--;
1141
1142 ret = nilfs_sufile_set_alloc_range(nilfs->ns_sufile, minseg, maxseg);
1143out:
1144 return ret;
1145}
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
1170 unsigned int cmd, void __user *argp,
1171 size_t membsz,
1172 ssize_t (*dofunc)(struct the_nilfs *,
1173 __u64 *, int,
1174 void *, size_t, size_t))
1175
1176{
1177 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1178 struct nilfs_argv argv;
1179 int ret;
1180
1181 if (copy_from_user(&argv, argp, sizeof(argv)))
1182 return -EFAULT;
1183
1184 if (argv.v_size < membsz)
1185 return -EINVAL;
1186
1187 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
1188 if (ret < 0)
1189 return ret;
1190
1191 if (copy_to_user(argp, &argv, sizeof(argv)))
1192 ret = -EFAULT;
1193 return ret;
1194}
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220static int nilfs_ioctl_set_suinfo(struct inode *inode, struct file *filp,
1221 unsigned int cmd, void __user *argp)
1222{
1223 struct the_nilfs *nilfs = inode->i_sb->s_fs_info;
1224 struct nilfs_transaction_info ti;
1225 struct nilfs_argv argv;
1226 size_t len;
1227 void __user *base;
1228 void *kbuf;
1229 int ret;
1230
1231 if (!capable(CAP_SYS_ADMIN))
1232 return -EPERM;
1233
1234 ret = mnt_want_write_file(filp);
1235 if (ret)
1236 return ret;
1237
1238 ret = -EFAULT;
1239 if (copy_from_user(&argv, argp, sizeof(argv)))
1240 goto out;
1241
1242 ret = -EINVAL;
1243 if (argv.v_size < sizeof(struct nilfs_suinfo_update))
1244 goto out;
1245
1246 if (argv.v_nmembs > nilfs->ns_nsegments)
1247 goto out;
1248
1249 if (argv.v_nmembs >= UINT_MAX / argv.v_size)
1250 goto out;
1251
1252 len = argv.v_size * argv.v_nmembs;
1253 if (!len) {
1254 ret = 0;
1255 goto out;
1256 }
1257
1258 base = (void __user *)(unsigned long)argv.v_base;
1259 kbuf = vmalloc(len);
1260 if (!kbuf) {
1261 ret = -ENOMEM;
1262 goto out;
1263 }
1264
1265 if (copy_from_user(kbuf, base, len)) {
1266 ret = -EFAULT;
1267 goto out_free;
1268 }
1269
1270 nilfs_transaction_begin(inode->i_sb, &ti, 0);
1271 ret = nilfs_sufile_set_suinfo(nilfs->ns_sufile, kbuf, argv.v_size,
1272 argv.v_nmembs);
1273 if (unlikely(ret < 0))
1274 nilfs_transaction_abort(inode->i_sb);
1275 else
1276 nilfs_transaction_commit(inode->i_sb);
1277
1278out_free:
1279 vfree(kbuf);
1280out:
1281 mnt_drop_write_file(filp);
1282 return ret;
1283}
1284
1285long nilfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1286{
1287 struct inode *inode = file_inode(filp);
1288 void __user *argp = (void __user *)arg;
1289
1290 switch (cmd) {
1291 case FS_IOC_GETFLAGS:
1292 return nilfs_ioctl_getflags(inode, argp);
1293 case FS_IOC_SETFLAGS:
1294 return nilfs_ioctl_setflags(inode, filp, argp);
1295 case FS_IOC_GETVERSION:
1296 return nilfs_ioctl_getversion(inode, argp);
1297 case NILFS_IOCTL_CHANGE_CPMODE:
1298 return nilfs_ioctl_change_cpmode(inode, filp, cmd, argp);
1299 case NILFS_IOCTL_DELETE_CHECKPOINT:
1300 return nilfs_ioctl_delete_checkpoint(inode, filp, cmd, argp);
1301 case NILFS_IOCTL_GET_CPINFO:
1302 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1303 sizeof(struct nilfs_cpinfo),
1304 nilfs_ioctl_do_get_cpinfo);
1305 case NILFS_IOCTL_GET_CPSTAT:
1306 return nilfs_ioctl_get_cpstat(inode, filp, cmd, argp);
1307 case NILFS_IOCTL_GET_SUINFO:
1308 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1309 sizeof(struct nilfs_suinfo),
1310 nilfs_ioctl_do_get_suinfo);
1311 case NILFS_IOCTL_SET_SUINFO:
1312 return nilfs_ioctl_set_suinfo(inode, filp, cmd, argp);
1313 case NILFS_IOCTL_GET_SUSTAT:
1314 return nilfs_ioctl_get_sustat(inode, filp, cmd, argp);
1315 case NILFS_IOCTL_GET_VINFO:
1316 return nilfs_ioctl_get_info(inode, filp, cmd, argp,
1317 sizeof(struct nilfs_vinfo),
1318 nilfs_ioctl_do_get_vinfo);
1319 case NILFS_IOCTL_GET_BDESCS:
1320 return nilfs_ioctl_get_bdescs(inode, filp, cmd, argp);
1321 case NILFS_IOCTL_CLEAN_SEGMENTS:
1322 return nilfs_ioctl_clean_segments(inode, filp, cmd, argp);
1323 case NILFS_IOCTL_SYNC:
1324 return nilfs_ioctl_sync(inode, filp, cmd, argp);
1325 case NILFS_IOCTL_RESIZE:
1326 return nilfs_ioctl_resize(inode, filp, argp);
1327 case NILFS_IOCTL_SET_ALLOC_RANGE:
1328 return nilfs_ioctl_set_alloc_range(inode, argp);
1329 case FITRIM:
1330 return nilfs_ioctl_trim_fs(inode, argp);
1331 default:
1332 return -ENOTTY;
1333 }
1334}
1335
1336#ifdef CONFIG_COMPAT
1337long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1338{
1339 switch (cmd) {
1340 case FS_IOC32_GETFLAGS:
1341 cmd = FS_IOC_GETFLAGS;
1342 break;
1343 case FS_IOC32_SETFLAGS:
1344 cmd = FS_IOC_SETFLAGS;
1345 break;
1346 case FS_IOC32_GETVERSION:
1347 cmd = FS_IOC_GETVERSION;
1348 break;
1349 case NILFS_IOCTL_CHANGE_CPMODE:
1350 case NILFS_IOCTL_DELETE_CHECKPOINT:
1351 case NILFS_IOCTL_GET_CPINFO:
1352 case NILFS_IOCTL_GET_CPSTAT:
1353 case NILFS_IOCTL_GET_SUINFO:
1354 case NILFS_IOCTL_SET_SUINFO:
1355 case NILFS_IOCTL_GET_SUSTAT:
1356 case NILFS_IOCTL_GET_VINFO:
1357 case NILFS_IOCTL_GET_BDESCS:
1358 case NILFS_IOCTL_CLEAN_SEGMENTS:
1359 case NILFS_IOCTL_SYNC:
1360 case NILFS_IOCTL_RESIZE:
1361 case NILFS_IOCTL_SET_ALLOC_RANGE:
1362 break;
1363 default:
1364 return -ENOIOCTLCMD;
1365 }
1366 return nilfs_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
1367}
1368#endif
1369