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