.. | .. |
---|
36 | 36 | #include <linux/fsnotify.h> |
---|
37 | 37 | #include <linux/lockdep.h> |
---|
38 | 38 | #include <linux/user_namespace.h> |
---|
| 39 | +#include <linux/fs_context.h> |
---|
| 40 | +#include <uapi/linux/mount.h> |
---|
39 | 41 | #include "internal.h" |
---|
40 | 42 | |
---|
41 | 43 | static int thaw_super_locked(struct super_block *sb); |
---|
.. | .. |
---|
256 | 258 | s->s_maxbytes = MAX_NON_LFS; |
---|
257 | 259 | s->s_op = &default_op; |
---|
258 | 260 | s->s_time_gran = 1000000000; |
---|
| 261 | + s->s_time_min = TIME64_MIN; |
---|
| 262 | + s->s_time_max = TIME64_MAX; |
---|
259 | 263 | s->cleancache_poolid = CLEANCACHE_NO_POOL; |
---|
260 | 264 | |
---|
261 | 265 | s->s_shrink.seeks = DEFAULT_SEEKS; |
---|
.. | .. |
---|
289 | 293 | WARN_ON(s->s_inode_lru.node); |
---|
290 | 294 | WARN_ON(!list_empty(&s->s_mounts)); |
---|
291 | 295 | security_sb_free(s); |
---|
292 | | - fscrypt_sb_free(s); |
---|
| 296 | + fscrypt_destroy_keyring(s); |
---|
293 | 297 | put_user_ns(s->s_user_ns); |
---|
294 | 298 | kfree(s->s_subtype); |
---|
295 | 299 | call_rcu(&s->rcu, destroy_super_rcu); |
---|
.. | .. |
---|
357 | 361 | */ |
---|
358 | 362 | void deactivate_super(struct super_block *s) |
---|
359 | 363 | { |
---|
360 | | - if (!atomic_add_unless(&s->s_active, -1, 1)) { |
---|
| 364 | + if (!atomic_add_unless(&s->s_active, -1, 1)) { |
---|
361 | 365 | down_write(&s->s_umount); |
---|
362 | 366 | deactivate_locked_super(s); |
---|
363 | 367 | } |
---|
.. | .. |
---|
444 | 448 | sync_filesystem(sb); |
---|
445 | 449 | sb->s_flags &= ~SB_ACTIVE; |
---|
446 | 450 | |
---|
447 | | - fsnotify_unmount_inodes(sb); |
---|
448 | 451 | cgroup_writeback_umount(); |
---|
449 | 452 | |
---|
| 453 | + /* evict all inodes with zero refcount */ |
---|
450 | 454 | evict_inodes(sb); |
---|
| 455 | + /* only nonzero refcount inodes can have marks */ |
---|
| 456 | + fsnotify_sb_delete(sb); |
---|
| 457 | + fscrypt_destroy_keyring(sb); |
---|
451 | 458 | |
---|
452 | 459 | if (sb->s_dio_done_wq) { |
---|
453 | 460 | destroy_workqueue(sb->s_dio_done_wq); |
---|
.. | .. |
---|
476 | 483 | |
---|
477 | 484 | EXPORT_SYMBOL(generic_shutdown_super); |
---|
478 | 485 | |
---|
| 486 | +bool mount_capable(struct fs_context *fc) |
---|
| 487 | +{ |
---|
| 488 | + if (!(fc->fs_type->fs_flags & FS_USERNS_MOUNT)) |
---|
| 489 | + return capable(CAP_SYS_ADMIN); |
---|
| 490 | + else |
---|
| 491 | + return ns_capable(fc->user_ns, CAP_SYS_ADMIN); |
---|
| 492 | +} |
---|
| 493 | + |
---|
479 | 494 | /** |
---|
480 | | - * sget_userns - find or create a superblock |
---|
481 | | - * @type: filesystem type superblock should belong to |
---|
482 | | - * @test: comparison callback |
---|
483 | | - * @set: setup callback |
---|
484 | | - * @flags: mount flags |
---|
485 | | - * @user_ns: User namespace for the super_block |
---|
486 | | - * @data: argument to each of them |
---|
| 495 | + * sget_fc - Find or create a superblock |
---|
| 496 | + * @fc: Filesystem context. |
---|
| 497 | + * @test: Comparison callback |
---|
| 498 | + * @set: Setup callback |
---|
| 499 | + * |
---|
| 500 | + * Find or create a superblock using the parameters stored in the filesystem |
---|
| 501 | + * context and the two callback functions. |
---|
| 502 | + * |
---|
| 503 | + * If an extant superblock is matched, then that will be returned with an |
---|
| 504 | + * elevated reference count that the caller must transfer or discard. |
---|
| 505 | + * |
---|
| 506 | + * If no match is made, a new superblock will be allocated and basic |
---|
| 507 | + * initialisation will be performed (s_type, s_fs_info and s_id will be set and |
---|
| 508 | + * the set() callback will be invoked), the superblock will be published and it |
---|
| 509 | + * will be returned in a partially constructed state with SB_BORN and SB_ACTIVE |
---|
| 510 | + * as yet unset. |
---|
487 | 511 | */ |
---|
488 | | -struct super_block *sget_userns(struct file_system_type *type, |
---|
| 512 | +struct super_block *sget_fc(struct fs_context *fc, |
---|
| 513 | + int (*test)(struct super_block *, struct fs_context *), |
---|
| 514 | + int (*set)(struct super_block *, struct fs_context *)) |
---|
| 515 | +{ |
---|
| 516 | + struct super_block *s = NULL; |
---|
| 517 | + struct super_block *old; |
---|
| 518 | + struct user_namespace *user_ns = fc->global ? &init_user_ns : fc->user_ns; |
---|
| 519 | + int err; |
---|
| 520 | + |
---|
| 521 | +retry: |
---|
| 522 | + spin_lock(&sb_lock); |
---|
| 523 | + if (test) { |
---|
| 524 | + hlist_for_each_entry(old, &fc->fs_type->fs_supers, s_instances) { |
---|
| 525 | + if (test(old, fc)) |
---|
| 526 | + goto share_extant_sb; |
---|
| 527 | + } |
---|
| 528 | + } |
---|
| 529 | + if (!s) { |
---|
| 530 | + spin_unlock(&sb_lock); |
---|
| 531 | + s = alloc_super(fc->fs_type, fc->sb_flags, user_ns); |
---|
| 532 | + if (!s) |
---|
| 533 | + return ERR_PTR(-ENOMEM); |
---|
| 534 | + goto retry; |
---|
| 535 | + } |
---|
| 536 | + |
---|
| 537 | + s->s_fs_info = fc->s_fs_info; |
---|
| 538 | + err = set(s, fc); |
---|
| 539 | + if (err) { |
---|
| 540 | + s->s_fs_info = NULL; |
---|
| 541 | + spin_unlock(&sb_lock); |
---|
| 542 | + destroy_unused_super(s); |
---|
| 543 | + return ERR_PTR(err); |
---|
| 544 | + } |
---|
| 545 | + fc->s_fs_info = NULL; |
---|
| 546 | + s->s_type = fc->fs_type; |
---|
| 547 | + s->s_iflags |= fc->s_iflags; |
---|
| 548 | + strlcpy(s->s_id, s->s_type->name, sizeof(s->s_id)); |
---|
| 549 | + list_add_tail(&s->s_list, &super_blocks); |
---|
| 550 | + hlist_add_head(&s->s_instances, &s->s_type->fs_supers); |
---|
| 551 | + spin_unlock(&sb_lock); |
---|
| 552 | + get_filesystem(s->s_type); |
---|
| 553 | + register_shrinker_prepared(&s->s_shrink); |
---|
| 554 | + return s; |
---|
| 555 | + |
---|
| 556 | +share_extant_sb: |
---|
| 557 | + if (user_ns != old->s_user_ns) { |
---|
| 558 | + spin_unlock(&sb_lock); |
---|
| 559 | + destroy_unused_super(s); |
---|
| 560 | + return ERR_PTR(-EBUSY); |
---|
| 561 | + } |
---|
| 562 | + if (!grab_super(old)) |
---|
| 563 | + goto retry; |
---|
| 564 | + destroy_unused_super(s); |
---|
| 565 | + return old; |
---|
| 566 | +} |
---|
| 567 | +EXPORT_SYMBOL(sget_fc); |
---|
| 568 | + |
---|
| 569 | +/** |
---|
| 570 | + * sget - find or create a superblock |
---|
| 571 | + * @type: filesystem type superblock should belong to |
---|
| 572 | + * @test: comparison callback |
---|
| 573 | + * @set: setup callback |
---|
| 574 | + * @flags: mount flags |
---|
| 575 | + * @data: argument to each of them |
---|
| 576 | + */ |
---|
| 577 | +struct super_block *sget(struct file_system_type *type, |
---|
489 | 578 | int (*test)(struct super_block *,void *), |
---|
490 | 579 | int (*set)(struct super_block *,void *), |
---|
491 | | - int flags, struct user_namespace *user_ns, |
---|
| 580 | + int flags, |
---|
492 | 581 | void *data) |
---|
493 | 582 | { |
---|
| 583 | + struct user_namespace *user_ns = current_user_ns(); |
---|
494 | 584 | struct super_block *s = NULL; |
---|
495 | 585 | struct super_block *old; |
---|
496 | 586 | int err; |
---|
497 | 587 | |
---|
498 | | - if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && |
---|
499 | | - !(type->fs_flags & FS_USERNS_MOUNT) && |
---|
500 | | - !capable(CAP_SYS_ADMIN)) |
---|
501 | | - return ERR_PTR(-EPERM); |
---|
| 588 | + /* We don't yet pass the user namespace of the parent |
---|
| 589 | + * mount through to here so always use &init_user_ns |
---|
| 590 | + * until that changes. |
---|
| 591 | + */ |
---|
| 592 | + if (flags & SB_SUBMOUNT) |
---|
| 593 | + user_ns = &init_user_ns; |
---|
| 594 | + |
---|
502 | 595 | retry: |
---|
503 | 596 | spin_lock(&sb_lock); |
---|
504 | 597 | if (test) { |
---|
.. | .. |
---|
539 | 632 | register_shrinker_prepared(&s->s_shrink); |
---|
540 | 633 | return s; |
---|
541 | 634 | } |
---|
542 | | - |
---|
543 | | -EXPORT_SYMBOL(sget_userns); |
---|
544 | | - |
---|
545 | | -/** |
---|
546 | | - * sget - find or create a superblock |
---|
547 | | - * @type: filesystem type superblock should belong to |
---|
548 | | - * @test: comparison callback |
---|
549 | | - * @set: setup callback |
---|
550 | | - * @flags: mount flags |
---|
551 | | - * @data: argument to each of them |
---|
552 | | - */ |
---|
553 | | -struct super_block *sget(struct file_system_type *type, |
---|
554 | | - int (*test)(struct super_block *,void *), |
---|
555 | | - int (*set)(struct super_block *,void *), |
---|
556 | | - int flags, |
---|
557 | | - void *data) |
---|
558 | | -{ |
---|
559 | | - struct user_namespace *user_ns = current_user_ns(); |
---|
560 | | - |
---|
561 | | - /* We don't yet pass the user namespace of the parent |
---|
562 | | - * mount through to here so always use &init_user_ns |
---|
563 | | - * until that changes. |
---|
564 | | - */ |
---|
565 | | - if (flags & SB_SUBMOUNT) |
---|
566 | | - user_ns = &init_user_ns; |
---|
567 | | - |
---|
568 | | - /* Ensure the requestor has permissions over the target filesystem */ |
---|
569 | | - if (!(flags & (SB_KERNMOUNT|SB_SUBMOUNT)) && !ns_capable(user_ns, CAP_SYS_ADMIN)) |
---|
570 | | - return ERR_PTR(-EPERM); |
---|
571 | | - |
---|
572 | | - return sget_userns(type, test, set, flags, user_ns, data); |
---|
573 | | -} |
---|
574 | | - |
---|
575 | 635 | EXPORT_SYMBOL(sget); |
---|
576 | 636 | |
---|
577 | 637 | void drop_super(struct super_block *sb) |
---|
.. | .. |
---|
836 | 896 | } |
---|
837 | 897 | |
---|
838 | 898 | /** |
---|
839 | | - * do_remount_sb2 - asks filesystem to change mount options. |
---|
840 | | - * @mnt: mount we are looking at |
---|
841 | | - * @sb: superblock in question |
---|
842 | | - * @sb_flags: revised superblock flags |
---|
843 | | - * @data: the rest of options |
---|
844 | | - * @force: whether or not to force the change |
---|
| 899 | + * reconfigure_super - asks filesystem to change superblock parameters |
---|
| 900 | + * @fc: The superblock and configuration |
---|
845 | 901 | * |
---|
846 | | - * Alters the mount options of a mounted file system. |
---|
| 902 | + * Alters the configuration parameters of a live superblock. |
---|
847 | 903 | */ |
---|
848 | | -int do_remount_sb2(struct vfsmount *mnt, struct super_block *sb, int sb_flags, void *data, int force) |
---|
| 904 | +int reconfigure_super(struct fs_context *fc) |
---|
849 | 905 | { |
---|
| 906 | + struct super_block *sb = fc->root->d_sb; |
---|
850 | 907 | int retval; |
---|
851 | | - int remount_ro; |
---|
| 908 | + bool remount_ro = false; |
---|
| 909 | + bool force = fc->sb_flags & SB_FORCE; |
---|
852 | 910 | |
---|
| 911 | + if (fc->sb_flags_mask & ~MS_RMT_MASK) |
---|
| 912 | + return -EINVAL; |
---|
853 | 913 | if (sb->s_writers.frozen != SB_UNFROZEN) |
---|
854 | 914 | return -EBUSY; |
---|
855 | 915 | |
---|
| 916 | + retval = security_sb_remount(sb, fc->security); |
---|
| 917 | + if (retval) |
---|
| 918 | + return retval; |
---|
| 919 | + |
---|
| 920 | + if (fc->sb_flags_mask & SB_RDONLY) { |
---|
856 | 921 | #ifdef CONFIG_BLOCK |
---|
857 | | - if (!(sb_flags & SB_RDONLY) && bdev_read_only(sb->s_bdev)) |
---|
858 | | - return -EACCES; |
---|
| 922 | + if (!(fc->sb_flags & SB_RDONLY) && bdev_read_only(sb->s_bdev)) |
---|
| 923 | + return -EACCES; |
---|
859 | 924 | #endif |
---|
860 | 925 | |
---|
861 | | - remount_ro = (sb_flags & SB_RDONLY) && !sb_rdonly(sb); |
---|
| 926 | + remount_ro = (fc->sb_flags & SB_RDONLY) && !sb_rdonly(sb); |
---|
| 927 | + } |
---|
862 | 928 | |
---|
863 | 929 | if (remount_ro) { |
---|
864 | 930 | if (!hlist_empty(&sb->s_pins)) { |
---|
.. | .. |
---|
869 | 935 | return 0; |
---|
870 | 936 | if (sb->s_writers.frozen != SB_UNFROZEN) |
---|
871 | 937 | return -EBUSY; |
---|
872 | | - remount_ro = (sb_flags & SB_RDONLY) && !sb_rdonly(sb); |
---|
| 938 | + remount_ro = !sb_rdonly(sb); |
---|
873 | 939 | } |
---|
874 | 940 | } |
---|
875 | 941 | shrink_dcache_sb(sb); |
---|
876 | 942 | |
---|
877 | | - /* If we are remounting RDONLY and current sb is read/write, |
---|
878 | | - make sure there are no rw files opened */ |
---|
| 943 | + /* If we are reconfiguring to RDONLY and current sb is read/write, |
---|
| 944 | + * make sure there are no files open for writing. |
---|
| 945 | + */ |
---|
879 | 946 | if (remount_ro) { |
---|
880 | 947 | if (force) { |
---|
881 | 948 | sb->s_readonly_remount = 1; |
---|
.. | .. |
---|
887 | 954 | } |
---|
888 | 955 | } |
---|
889 | 956 | |
---|
890 | | - if (mnt && sb->s_op->remount_fs2) { |
---|
891 | | - retval = sb->s_op->remount_fs2(mnt, sb, &sb_flags, data); |
---|
892 | | - if (retval) { |
---|
893 | | - if (!force) |
---|
894 | | - goto cancel_readonly; |
---|
895 | | - /* If forced remount, go ahead despite any errors */ |
---|
896 | | - WARN(1, "forced remount of a %s fs returned %i\n", |
---|
897 | | - sb->s_type->name, retval); |
---|
898 | | - } |
---|
899 | | - } else if (sb->s_op->remount_fs) { |
---|
900 | | - retval = sb->s_op->remount_fs(sb, &sb_flags, data); |
---|
| 957 | + if (fc->ops->reconfigure) { |
---|
| 958 | + retval = fc->ops->reconfigure(fc); |
---|
901 | 959 | if (retval) { |
---|
902 | 960 | if (!force) |
---|
903 | 961 | goto cancel_readonly; |
---|
.. | .. |
---|
906 | 964 | sb->s_type->name, retval); |
---|
907 | 965 | } |
---|
908 | 966 | } |
---|
909 | | - sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (sb_flags & MS_RMT_MASK); |
---|
| 967 | + |
---|
| 968 | + WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) | |
---|
| 969 | + (fc->sb_flags & fc->sb_flags_mask))); |
---|
910 | 970 | /* Needs to be ordered wrt mnt_is_readonly() */ |
---|
911 | 971 | smp_wmb(); |
---|
912 | 972 | sb->s_readonly_remount = 0; |
---|
.. | .. |
---|
928 | 988 | return retval; |
---|
929 | 989 | } |
---|
930 | 990 | |
---|
931 | | -int do_remount_sb(struct super_block *sb, int flags, void *data, int force) |
---|
932 | | -{ |
---|
933 | | - return do_remount_sb2(NULL, sb, flags, data, force); |
---|
934 | | -} |
---|
935 | | - |
---|
936 | 991 | static void do_emergency_remount_callback(struct super_block *sb) |
---|
937 | 992 | { |
---|
938 | 993 | down_write(&sb->s_umount); |
---|
939 | 994 | if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) && |
---|
940 | 995 | !sb_rdonly(sb)) { |
---|
941 | | - /* |
---|
942 | | - * What lock protects sb->s_flags?? |
---|
943 | | - */ |
---|
944 | | - do_remount_sb(sb, SB_RDONLY, NULL, 1); |
---|
| 996 | + struct fs_context *fc; |
---|
| 997 | + |
---|
| 998 | + fc = fs_context_for_reconfigure(sb->s_root, |
---|
| 999 | + SB_RDONLY | SB_FORCE, SB_RDONLY); |
---|
| 1000 | + if (!IS_ERR(fc)) { |
---|
| 1001 | + if (parse_monolithic_mount_data(fc, NULL) == 0) |
---|
| 1002 | + (void)reconfigure_super(fc); |
---|
| 1003 | + put_fs_context(fc); |
---|
| 1004 | + } |
---|
945 | 1005 | } |
---|
946 | 1006 | up_write(&sb->s_umount); |
---|
947 | 1007 | } |
---|
.. | .. |
---|
1059 | 1119 | } |
---|
1060 | 1120 | EXPORT_SYMBOL(kill_litter_super); |
---|
1061 | 1121 | |
---|
1062 | | -static int ns_test_super(struct super_block *sb, void *data) |
---|
| 1122 | +int set_anon_super_fc(struct super_block *sb, struct fs_context *fc) |
---|
1063 | 1123 | { |
---|
1064 | | - return sb->s_fs_info == data; |
---|
1065 | | -} |
---|
1066 | | - |
---|
1067 | | -static int ns_set_super(struct super_block *sb, void *data) |
---|
1068 | | -{ |
---|
1069 | | - sb->s_fs_info = data; |
---|
1070 | 1124 | return set_anon_super(sb, NULL); |
---|
1071 | 1125 | } |
---|
| 1126 | +EXPORT_SYMBOL(set_anon_super_fc); |
---|
1072 | 1127 | |
---|
1073 | | -struct dentry *mount_ns(struct file_system_type *fs_type, |
---|
1074 | | - int flags, void *data, void *ns, struct user_namespace *user_ns, |
---|
1075 | | - int (*fill_super)(struct super_block *, void *, int)) |
---|
| 1128 | +static int test_keyed_super(struct super_block *sb, struct fs_context *fc) |
---|
1076 | 1129 | { |
---|
1077 | | - struct super_block *sb; |
---|
1078 | | - |
---|
1079 | | - /* Don't allow mounting unless the caller has CAP_SYS_ADMIN |
---|
1080 | | - * over the namespace. |
---|
1081 | | - */ |
---|
1082 | | - if (!(flags & SB_KERNMOUNT) && !ns_capable(user_ns, CAP_SYS_ADMIN)) |
---|
1083 | | - return ERR_PTR(-EPERM); |
---|
1084 | | - |
---|
1085 | | - sb = sget_userns(fs_type, ns_test_super, ns_set_super, flags, |
---|
1086 | | - user_ns, ns); |
---|
1087 | | - if (IS_ERR(sb)) |
---|
1088 | | - return ERR_CAST(sb); |
---|
1089 | | - |
---|
1090 | | - if (!sb->s_root) { |
---|
1091 | | - int err; |
---|
1092 | | - err = fill_super(sb, data, flags & SB_SILENT ? 1 : 0); |
---|
1093 | | - if (err) { |
---|
1094 | | - deactivate_locked_super(sb); |
---|
1095 | | - return ERR_PTR(err); |
---|
1096 | | - } |
---|
1097 | | - |
---|
1098 | | - sb->s_flags |= SB_ACTIVE; |
---|
1099 | | - } |
---|
1100 | | - |
---|
1101 | | - return dget(sb->s_root); |
---|
| 1130 | + return sb->s_fs_info == fc->s_fs_info; |
---|
1102 | 1131 | } |
---|
1103 | 1132 | |
---|
1104 | | -EXPORT_SYMBOL(mount_ns); |
---|
| 1133 | +static int test_single_super(struct super_block *s, struct fs_context *fc) |
---|
| 1134 | +{ |
---|
| 1135 | + return 1; |
---|
| 1136 | +} |
---|
| 1137 | + |
---|
| 1138 | +/** |
---|
| 1139 | + * vfs_get_super - Get a superblock with a search key set in s_fs_info. |
---|
| 1140 | + * @fc: The filesystem context holding the parameters |
---|
| 1141 | + * @keying: How to distinguish superblocks |
---|
| 1142 | + * @fill_super: Helper to initialise a new superblock |
---|
| 1143 | + * |
---|
| 1144 | + * Search for a superblock and create a new one if not found. The search |
---|
| 1145 | + * criterion is controlled by @keying. If the search fails, a new superblock |
---|
| 1146 | + * is created and @fill_super() is called to initialise it. |
---|
| 1147 | + * |
---|
| 1148 | + * @keying can take one of a number of values: |
---|
| 1149 | + * |
---|
| 1150 | + * (1) vfs_get_single_super - Only one superblock of this type may exist on the |
---|
| 1151 | + * system. This is typically used for special system filesystems. |
---|
| 1152 | + * |
---|
| 1153 | + * (2) vfs_get_keyed_super - Multiple superblocks may exist, but they must have |
---|
| 1154 | + * distinct keys (where the key is in s_fs_info). Searching for the same |
---|
| 1155 | + * key again will turn up the superblock for that key. |
---|
| 1156 | + * |
---|
| 1157 | + * (3) vfs_get_independent_super - Multiple superblocks may exist and are |
---|
| 1158 | + * unkeyed. Each call will get a new superblock. |
---|
| 1159 | + * |
---|
| 1160 | + * A permissions check is made by sget_fc() unless we're getting a superblock |
---|
| 1161 | + * for a kernel-internal mount or a submount. |
---|
| 1162 | + */ |
---|
| 1163 | +int vfs_get_super(struct fs_context *fc, |
---|
| 1164 | + enum vfs_get_super_keying keying, |
---|
| 1165 | + int (*fill_super)(struct super_block *sb, |
---|
| 1166 | + struct fs_context *fc)) |
---|
| 1167 | +{ |
---|
| 1168 | + int (*test)(struct super_block *, struct fs_context *); |
---|
| 1169 | + struct super_block *sb; |
---|
| 1170 | + int err; |
---|
| 1171 | + |
---|
| 1172 | + switch (keying) { |
---|
| 1173 | + case vfs_get_single_super: |
---|
| 1174 | + case vfs_get_single_reconf_super: |
---|
| 1175 | + test = test_single_super; |
---|
| 1176 | + break; |
---|
| 1177 | + case vfs_get_keyed_super: |
---|
| 1178 | + test = test_keyed_super; |
---|
| 1179 | + break; |
---|
| 1180 | + case vfs_get_independent_super: |
---|
| 1181 | + test = NULL; |
---|
| 1182 | + break; |
---|
| 1183 | + default: |
---|
| 1184 | + BUG(); |
---|
| 1185 | + } |
---|
| 1186 | + |
---|
| 1187 | + sb = sget_fc(fc, test, set_anon_super_fc); |
---|
| 1188 | + if (IS_ERR(sb)) |
---|
| 1189 | + return PTR_ERR(sb); |
---|
| 1190 | + |
---|
| 1191 | + if (!sb->s_root) { |
---|
| 1192 | + err = fill_super(sb, fc); |
---|
| 1193 | + if (err) |
---|
| 1194 | + goto error; |
---|
| 1195 | + |
---|
| 1196 | + sb->s_flags |= SB_ACTIVE; |
---|
| 1197 | + fc->root = dget(sb->s_root); |
---|
| 1198 | + } else { |
---|
| 1199 | + fc->root = dget(sb->s_root); |
---|
| 1200 | + if (keying == vfs_get_single_reconf_super) { |
---|
| 1201 | + err = reconfigure_super(fc); |
---|
| 1202 | + if (err < 0) { |
---|
| 1203 | + dput(fc->root); |
---|
| 1204 | + fc->root = NULL; |
---|
| 1205 | + goto error; |
---|
| 1206 | + } |
---|
| 1207 | + } |
---|
| 1208 | + } |
---|
| 1209 | + |
---|
| 1210 | + return 0; |
---|
| 1211 | + |
---|
| 1212 | +error: |
---|
| 1213 | + deactivate_locked_super(sb); |
---|
| 1214 | + return err; |
---|
| 1215 | +} |
---|
| 1216 | +EXPORT_SYMBOL(vfs_get_super); |
---|
| 1217 | + |
---|
| 1218 | +int get_tree_nodev(struct fs_context *fc, |
---|
| 1219 | + int (*fill_super)(struct super_block *sb, |
---|
| 1220 | + struct fs_context *fc)) |
---|
| 1221 | +{ |
---|
| 1222 | + return vfs_get_super(fc, vfs_get_independent_super, fill_super); |
---|
| 1223 | +} |
---|
| 1224 | +EXPORT_SYMBOL(get_tree_nodev); |
---|
| 1225 | + |
---|
| 1226 | +int get_tree_single(struct fs_context *fc, |
---|
| 1227 | + int (*fill_super)(struct super_block *sb, |
---|
| 1228 | + struct fs_context *fc)) |
---|
| 1229 | +{ |
---|
| 1230 | + return vfs_get_super(fc, vfs_get_single_super, fill_super); |
---|
| 1231 | +} |
---|
| 1232 | +EXPORT_SYMBOL(get_tree_single); |
---|
| 1233 | + |
---|
| 1234 | +int get_tree_single_reconf(struct fs_context *fc, |
---|
| 1235 | + int (*fill_super)(struct super_block *sb, |
---|
| 1236 | + struct fs_context *fc)) |
---|
| 1237 | +{ |
---|
| 1238 | + return vfs_get_super(fc, vfs_get_single_reconf_super, fill_super); |
---|
| 1239 | +} |
---|
| 1240 | +EXPORT_SYMBOL(get_tree_single_reconf); |
---|
| 1241 | + |
---|
| 1242 | +int get_tree_keyed(struct fs_context *fc, |
---|
| 1243 | + int (*fill_super)(struct super_block *sb, |
---|
| 1244 | + struct fs_context *fc), |
---|
| 1245 | + void *key) |
---|
| 1246 | +{ |
---|
| 1247 | + fc->s_fs_info = key; |
---|
| 1248 | + return vfs_get_super(fc, vfs_get_keyed_super, fill_super); |
---|
| 1249 | +} |
---|
| 1250 | +EXPORT_SYMBOL(get_tree_keyed); |
---|
1105 | 1251 | |
---|
1106 | 1252 | #ifdef CONFIG_BLOCK |
---|
| 1253 | + |
---|
1107 | 1254 | static int set_bdev_super(struct super_block *s, void *data) |
---|
1108 | 1255 | { |
---|
1109 | 1256 | s->s_bdev = data; |
---|
1110 | 1257 | s->s_dev = s->s_bdev->bd_dev; |
---|
1111 | 1258 | s->s_bdi = bdi_get(s->s_bdev->bd_bdi); |
---|
1112 | 1259 | |
---|
| 1260 | + if (blk_queue_stable_writes(s->s_bdev->bd_disk->queue)) |
---|
| 1261 | + s->s_iflags |= SB_I_STABLE_WRITES; |
---|
1113 | 1262 | return 0; |
---|
1114 | 1263 | } |
---|
| 1264 | + |
---|
| 1265 | +static int set_bdev_super_fc(struct super_block *s, struct fs_context *fc) |
---|
| 1266 | +{ |
---|
| 1267 | + return set_bdev_super(s, fc->sget_key); |
---|
| 1268 | +} |
---|
| 1269 | + |
---|
| 1270 | +static int test_bdev_super_fc(struct super_block *s, struct fs_context *fc) |
---|
| 1271 | +{ |
---|
| 1272 | + return s->s_bdev == fc->sget_key; |
---|
| 1273 | +} |
---|
| 1274 | + |
---|
| 1275 | +/** |
---|
| 1276 | + * get_tree_bdev - Get a superblock based on a single block device |
---|
| 1277 | + * @fc: The filesystem context holding the parameters |
---|
| 1278 | + * @fill_super: Helper to initialise a new superblock |
---|
| 1279 | + */ |
---|
| 1280 | +int get_tree_bdev(struct fs_context *fc, |
---|
| 1281 | + int (*fill_super)(struct super_block *, |
---|
| 1282 | + struct fs_context *)) |
---|
| 1283 | +{ |
---|
| 1284 | + struct block_device *bdev; |
---|
| 1285 | + struct super_block *s; |
---|
| 1286 | + fmode_t mode = FMODE_READ | FMODE_EXCL; |
---|
| 1287 | + int error = 0; |
---|
| 1288 | + |
---|
| 1289 | + if (!(fc->sb_flags & SB_RDONLY)) |
---|
| 1290 | + mode |= FMODE_WRITE; |
---|
| 1291 | + |
---|
| 1292 | + if (!fc->source) |
---|
| 1293 | + return invalf(fc, "No source specified"); |
---|
| 1294 | + |
---|
| 1295 | + bdev = blkdev_get_by_path(fc->source, mode, fc->fs_type); |
---|
| 1296 | + if (IS_ERR(bdev)) { |
---|
| 1297 | + errorf(fc, "%s: Can't open blockdev", fc->source); |
---|
| 1298 | + return PTR_ERR(bdev); |
---|
| 1299 | + } |
---|
| 1300 | + |
---|
| 1301 | + /* Once the superblock is inserted into the list by sget_fc(), s_umount |
---|
| 1302 | + * will protect the lockfs code from trying to start a snapshot while |
---|
| 1303 | + * we are mounting |
---|
| 1304 | + */ |
---|
| 1305 | + mutex_lock(&bdev->bd_fsfreeze_mutex); |
---|
| 1306 | + if (bdev->bd_fsfreeze_count > 0) { |
---|
| 1307 | + mutex_unlock(&bdev->bd_fsfreeze_mutex); |
---|
| 1308 | + warnf(fc, "%pg: Can't mount, blockdev is frozen", bdev); |
---|
| 1309 | + blkdev_put(bdev, mode); |
---|
| 1310 | + return -EBUSY; |
---|
| 1311 | + } |
---|
| 1312 | + |
---|
| 1313 | + fc->sb_flags |= SB_NOSEC; |
---|
| 1314 | + fc->sget_key = bdev; |
---|
| 1315 | + s = sget_fc(fc, test_bdev_super_fc, set_bdev_super_fc); |
---|
| 1316 | + mutex_unlock(&bdev->bd_fsfreeze_mutex); |
---|
| 1317 | + if (IS_ERR(s)) { |
---|
| 1318 | + blkdev_put(bdev, mode); |
---|
| 1319 | + return PTR_ERR(s); |
---|
| 1320 | + } |
---|
| 1321 | + |
---|
| 1322 | + if (s->s_root) { |
---|
| 1323 | + /* Don't summarily change the RO/RW state. */ |
---|
| 1324 | + if ((fc->sb_flags ^ s->s_flags) & SB_RDONLY) { |
---|
| 1325 | + warnf(fc, "%pg: Can't mount, would change RO state", bdev); |
---|
| 1326 | + deactivate_locked_super(s); |
---|
| 1327 | + blkdev_put(bdev, mode); |
---|
| 1328 | + return -EBUSY; |
---|
| 1329 | + } |
---|
| 1330 | + |
---|
| 1331 | + /* |
---|
| 1332 | + * s_umount nests inside bd_mutex during |
---|
| 1333 | + * __invalidate_device(). blkdev_put() acquires |
---|
| 1334 | + * bd_mutex and can't be called under s_umount. Drop |
---|
| 1335 | + * s_umount temporarily. This is safe as we're |
---|
| 1336 | + * holding an active reference. |
---|
| 1337 | + */ |
---|
| 1338 | + up_write(&s->s_umount); |
---|
| 1339 | + blkdev_put(bdev, mode); |
---|
| 1340 | + down_write(&s->s_umount); |
---|
| 1341 | + } else { |
---|
| 1342 | + s->s_mode = mode; |
---|
| 1343 | + snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev); |
---|
| 1344 | + sb_set_blocksize(s, block_size(bdev)); |
---|
| 1345 | + error = fill_super(s, fc); |
---|
| 1346 | + if (error) { |
---|
| 1347 | + deactivate_locked_super(s); |
---|
| 1348 | + return error; |
---|
| 1349 | + } |
---|
| 1350 | + |
---|
| 1351 | + s->s_flags |= SB_ACTIVE; |
---|
| 1352 | + bdev->bd_super = s; |
---|
| 1353 | + } |
---|
| 1354 | + |
---|
| 1355 | + BUG_ON(fc->root); |
---|
| 1356 | + fc->root = dget(s->s_root); |
---|
| 1357 | + return 0; |
---|
| 1358 | +} |
---|
| 1359 | +EXPORT_SYMBOL(get_tree_bdev); |
---|
1115 | 1360 | |
---|
1116 | 1361 | static int test_bdev_super(struct super_block *s, void *data) |
---|
1117 | 1362 | { |
---|
.. | .. |
---|
1191 | 1436 | error: |
---|
1192 | 1437 | return ERR_PTR(error); |
---|
1193 | 1438 | } |
---|
1194 | | -EXPORT_SYMBOL(mount_bdev); |
---|
| 1439 | +EXPORT_SYMBOL_NS(mount_bdev, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
1195 | 1440 | |
---|
1196 | 1441 | void kill_block_super(struct super_block *sb) |
---|
1197 | 1442 | { |
---|
.. | .. |
---|
1205 | 1450 | blkdev_put(bdev, mode | FMODE_EXCL); |
---|
1206 | 1451 | } |
---|
1207 | 1452 | |
---|
1208 | | -EXPORT_SYMBOL(kill_block_super); |
---|
| 1453 | +EXPORT_SYMBOL_NS(kill_block_super, ANDROID_GKI_VFS_EXPORT_ONLY); |
---|
1209 | 1454 | #endif |
---|
1210 | 1455 | |
---|
1211 | 1456 | struct dentry *mount_nodev(struct file_system_type *fs_type, |
---|
.. | .. |
---|
1228 | 1473 | } |
---|
1229 | 1474 | EXPORT_SYMBOL(mount_nodev); |
---|
1230 | 1475 | |
---|
| 1476 | +int reconfigure_single(struct super_block *s, |
---|
| 1477 | + int flags, void *data) |
---|
| 1478 | +{ |
---|
| 1479 | + struct fs_context *fc; |
---|
| 1480 | + int ret; |
---|
| 1481 | + |
---|
| 1482 | + /* The caller really need to be passing fc down into mount_single(), |
---|
| 1483 | + * then a chunk of this can be removed. [Bollocks -- AV] |
---|
| 1484 | + * Better yet, reconfiguration shouldn't happen, but rather the second |
---|
| 1485 | + * mount should be rejected if the parameters are not compatible. |
---|
| 1486 | + */ |
---|
| 1487 | + fc = fs_context_for_reconfigure(s->s_root, flags, MS_RMT_MASK); |
---|
| 1488 | + if (IS_ERR(fc)) |
---|
| 1489 | + return PTR_ERR(fc); |
---|
| 1490 | + |
---|
| 1491 | + ret = parse_monolithic_mount_data(fc, data); |
---|
| 1492 | + if (ret < 0) |
---|
| 1493 | + goto out; |
---|
| 1494 | + |
---|
| 1495 | + ret = reconfigure_super(fc); |
---|
| 1496 | +out: |
---|
| 1497 | + put_fs_context(fc); |
---|
| 1498 | + return ret; |
---|
| 1499 | +} |
---|
| 1500 | + |
---|
1231 | 1501 | static int compare_single(struct super_block *s, void *p) |
---|
1232 | 1502 | { |
---|
1233 | 1503 | return 1; |
---|
.. | .. |
---|
1245 | 1515 | return ERR_CAST(s); |
---|
1246 | 1516 | if (!s->s_root) { |
---|
1247 | 1517 | error = fill_super(s, data, flags & SB_SILENT ? 1 : 0); |
---|
1248 | | - if (error) { |
---|
1249 | | - deactivate_locked_super(s); |
---|
1250 | | - return ERR_PTR(error); |
---|
1251 | | - } |
---|
1252 | | - s->s_flags |= SB_ACTIVE; |
---|
| 1518 | + if (!error) |
---|
| 1519 | + s->s_flags |= SB_ACTIVE; |
---|
1253 | 1520 | } else { |
---|
1254 | | - do_remount_sb(s, flags, data, 0); |
---|
| 1521 | + error = reconfigure_single(s, flags, data); |
---|
| 1522 | + } |
---|
| 1523 | + if (unlikely(error)) { |
---|
| 1524 | + deactivate_locked_super(s); |
---|
| 1525 | + return ERR_PTR(error); |
---|
1255 | 1526 | } |
---|
1256 | 1527 | return dget(s->s_root); |
---|
1257 | 1528 | } |
---|
1258 | 1529 | EXPORT_SYMBOL(mount_single); |
---|
1259 | 1530 | |
---|
1260 | | -struct dentry * |
---|
1261 | | -mount_fs(struct file_system_type *type, int flags, const char *name, struct vfsmount *mnt, void *data) |
---|
| 1531 | +/** |
---|
| 1532 | + * vfs_get_tree - Get the mountable root |
---|
| 1533 | + * @fc: The superblock configuration context. |
---|
| 1534 | + * |
---|
| 1535 | + * The filesystem is invoked to get or create a superblock which can then later |
---|
| 1536 | + * be used for mounting. The filesystem places a pointer to the root to be |
---|
| 1537 | + * used for mounting in @fc->root. |
---|
| 1538 | + */ |
---|
| 1539 | +int vfs_get_tree(struct fs_context *fc) |
---|
1262 | 1540 | { |
---|
1263 | | - struct dentry *root; |
---|
1264 | 1541 | struct super_block *sb; |
---|
1265 | | - char *secdata = NULL; |
---|
1266 | | - int error = -ENOMEM; |
---|
| 1542 | + int error; |
---|
1267 | 1543 | |
---|
1268 | | - if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { |
---|
1269 | | - secdata = alloc_secdata(); |
---|
1270 | | - if (!secdata) |
---|
1271 | | - goto out; |
---|
| 1544 | + if (fc->root) |
---|
| 1545 | + return -EBUSY; |
---|
1272 | 1546 | |
---|
1273 | | - error = security_sb_copy_data(data, secdata); |
---|
1274 | | - if (error) |
---|
1275 | | - goto out_free_secdata; |
---|
| 1547 | + /* Get the mountable root in fc->root, with a ref on the root and a ref |
---|
| 1548 | + * on the superblock. |
---|
| 1549 | + */ |
---|
| 1550 | + error = fc->ops->get_tree(fc); |
---|
| 1551 | + if (error < 0) |
---|
| 1552 | + return error; |
---|
| 1553 | + |
---|
| 1554 | + if (!fc->root) { |
---|
| 1555 | + pr_err("Filesystem %s get_tree() didn't set fc->root\n", |
---|
| 1556 | + fc->fs_type->name); |
---|
| 1557 | + /* We don't know what the locking state of the superblock is - |
---|
| 1558 | + * if there is a superblock. |
---|
| 1559 | + */ |
---|
| 1560 | + BUG(); |
---|
1276 | 1561 | } |
---|
1277 | 1562 | |
---|
1278 | | - if (type->mount2) |
---|
1279 | | - root = type->mount2(mnt, type, flags, name, data); |
---|
1280 | | - else |
---|
1281 | | - root = type->mount(type, flags, name, data); |
---|
1282 | | - if (IS_ERR(root)) { |
---|
1283 | | - error = PTR_ERR(root); |
---|
1284 | | - goto out_free_secdata; |
---|
1285 | | - } |
---|
1286 | | - sb = root->d_sb; |
---|
1287 | | - BUG_ON(!sb); |
---|
| 1563 | + sb = fc->root->d_sb; |
---|
1288 | 1564 | WARN_ON(!sb->s_bdi); |
---|
1289 | 1565 | |
---|
1290 | 1566 | /* |
---|
.. | .. |
---|
1296 | 1572 | smp_wmb(); |
---|
1297 | 1573 | sb->s_flags |= SB_BORN; |
---|
1298 | 1574 | |
---|
1299 | | - error = security_sb_kern_mount(sb, flags, secdata); |
---|
1300 | | - if (error) |
---|
1301 | | - goto out_sb; |
---|
| 1575 | + error = security_sb_set_mnt_opts(sb, fc->security, 0, NULL); |
---|
| 1576 | + if (unlikely(error)) { |
---|
| 1577 | + fc_drop_locked(fc); |
---|
| 1578 | + return error; |
---|
| 1579 | + } |
---|
1302 | 1580 | |
---|
1303 | 1581 | /* |
---|
1304 | 1582 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE |
---|
.. | .. |
---|
1307 | 1585 | * violate this rule. |
---|
1308 | 1586 | */ |
---|
1309 | 1587 | WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " |
---|
1310 | | - "negative value (%lld)\n", type->name, sb->s_maxbytes); |
---|
| 1588 | + "negative value (%lld)\n", fc->fs_type->name, sb->s_maxbytes); |
---|
1311 | 1589 | |
---|
1312 | | - up_write(&sb->s_umount); |
---|
1313 | | - free_secdata(secdata); |
---|
1314 | | - return root; |
---|
1315 | | -out_sb: |
---|
1316 | | - dput(root); |
---|
1317 | | - deactivate_locked_super(sb); |
---|
1318 | | -out_free_secdata: |
---|
1319 | | - free_secdata(secdata); |
---|
1320 | | -out: |
---|
1321 | | - return ERR_PTR(error); |
---|
| 1590 | + return 0; |
---|
1322 | 1591 | } |
---|
| 1592 | +EXPORT_SYMBOL(vfs_get_tree); |
---|
1323 | 1593 | |
---|
1324 | 1594 | /* |
---|
1325 | 1595 | * Setup private BDI for given superblock. It gets automatically cleaned up |
---|
.. | .. |
---|
1331 | 1601 | int err; |
---|
1332 | 1602 | va_list args; |
---|
1333 | 1603 | |
---|
1334 | | - bdi = bdi_alloc(GFP_KERNEL); |
---|
| 1604 | + bdi = bdi_alloc(NUMA_NO_NODE); |
---|
1335 | 1605 | if (!bdi) |
---|
1336 | 1606 | return -ENOMEM; |
---|
1337 | | - |
---|
1338 | | - bdi->name = sb->s_type->name; |
---|
1339 | 1607 | |
---|
1340 | 1608 | va_start(args, fmt); |
---|
1341 | 1609 | err = bdi_register_va(bdi, fmt, args); |
---|
.. | .. |
---|
1363 | 1631 | atomic_long_inc_return(&bdi_seq)); |
---|
1364 | 1632 | } |
---|
1365 | 1633 | EXPORT_SYMBOL(super_setup_bdi); |
---|
1366 | | - |
---|
1367 | | -/* |
---|
1368 | | - * This is an internal function, please use sb_end_{write,pagefault,intwrite} |
---|
1369 | | - * instead. |
---|
1370 | | - */ |
---|
1371 | | -void __sb_end_write(struct super_block *sb, int level) |
---|
1372 | | -{ |
---|
1373 | | - percpu_up_read(sb->s_writers.rw_sem + level-1); |
---|
1374 | | -} |
---|
1375 | | -EXPORT_SYMBOL(__sb_end_write); |
---|
1376 | | - |
---|
1377 | | -/* |
---|
1378 | | - * This is an internal function, please use sb_start_{write,pagefault,intwrite} |
---|
1379 | | - * instead. |
---|
1380 | | - */ |
---|
1381 | | -int __sb_start_write(struct super_block *sb, int level, bool wait) |
---|
1382 | | -{ |
---|
1383 | | - if (!wait) |
---|
1384 | | - return percpu_down_read_trylock(sb->s_writers.rw_sem + level-1); |
---|
1385 | | - |
---|
1386 | | - percpu_down_read(sb->s_writers.rw_sem + level-1); |
---|
1387 | | - return 1; |
---|
1388 | | -} |
---|
1389 | | -EXPORT_SYMBOL(__sb_start_write); |
---|
1390 | 1634 | |
---|
1391 | 1635 | /** |
---|
1392 | 1636 | * sb_wait_write - wait until all writers to given file system finish |
---|