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