summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-11-04 09:28:36 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2019-01-30 17:44:26 -0500
commit8d0347f6c3a9d4953ddd636a31c6584da082e084 (patch)
treea8dec0e9d854bad8732ae41084e6f7c980713758 /fs/super.c
parentc9ce29ed795fae86e594844857fad1b0d3be85f4 (diff)
convert do_remount_sb() to fs_context
Replace do_remount_sb() with a function, reconfigure_super(), that's fs_context aware. The fs_context is expected to be parameterised already and have ->root pointing to the superblock to be reconfigured. A legacy wrapper is provided that is intended to be called from the fs_context ops when those appear, but for now is called directly from reconfigure_super(). This wrapper invokes the ->remount_fs() superblock op for the moment. It is intended that the remount_fs() op will be phased out. The fs_context->purpose is set to FS_CONTEXT_FOR_RECONFIGURE to indicate that the context is being used for reconfiguration. do_umount_root() is provided to consolidate remount-to-R/O for umount and emergency remount by creating a context and invoking reconfiguration. do_remount(), do_umount() and do_emergency_remount_callback() are switched to use the new process. [AV -- fold UMOUNT and EMERGENCY_REMOUNT in; fixes the umount / bug, gets rid of pointless complexity] [AV -- set ->net_ns in all cases; nfs remount will need that] [AV -- shift security_sb_remount() call into reconfigure_super(); the callers that didn't do security_sb_remount() have NULL fc->security anyway, so it's a no-op for them] Signed-off-by: David Howells <dhowells@redhat.com> Co-developed-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c107
1 files changed, 73 insertions, 34 deletions
diff --git a/fs/super.c b/fs/super.c
index 11e2a6cb3baf..50553233dd15 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -836,28 +836,35 @@ rescan:
836} 836}
837 837
838/** 838/**
839 * do_remount_sb - asks filesystem to change mount options. 839 * reconfigure_super - asks filesystem to change superblock parameters
840 * @sb: superblock in question 840 * @fc: The superblock and configuration
841 * @sb_flags: revised superblock flags
842 * @data: the rest of options
843 * @force: whether or not to force the change
844 * 841 *
845 * Alters the mount options of a mounted file system. 842 * Alters the configuration parameters of a live superblock.
846 */ 843 */
847int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force) 844int reconfigure_super(struct fs_context *fc)
848{ 845{
846 struct super_block *sb = fc->root->d_sb;
849 int retval; 847 int retval;
850 int remount_ro; 848 bool remount_ro = false;
849 bool force = fc->sb_flags & SB_FORCE;
851 850
851 if (fc->sb_flags_mask & ~MS_RMT_MASK)
852 return -EINVAL;
852 if (sb->s_writers.frozen != SB_UNFROZEN) 853 if (sb->s_writers.frozen != SB_UNFROZEN)
853 return -EBUSY; 854 return -EBUSY;
854 855
856 retval = security_sb_remount(sb, fc->security);
857 if (retval)
858 return retval;
859
860 if (fc->sb_flags_mask & SB_RDONLY) {
855#ifdef CONFIG_BLOCK 861#ifdef CONFIG_BLOCK
856 if (!(sb_flags & SB_RDONLY) && bdev_read_only(sb->s_bdev)) 862 if (!(fc->sb_flags & SB_RDONLY) && bdev_read_only(sb->s_bdev))
857 return -EACCES; 863 return -EACCES;
858#endif 864#endif
859 865
860 remount_ro = (sb_flags & SB_RDONLY) && !sb_rdonly(sb); 866 remount_ro = (fc->sb_flags & SB_RDONLY) && !sb_rdonly(sb);
867 }
861 868
862 if (remount_ro) { 869 if (remount_ro) {
863 if (!hlist_empty(&sb->s_pins)) { 870 if (!hlist_empty(&sb->s_pins)) {
@@ -868,13 +875,14 @@ int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force)
868 return 0; 875 return 0;
869 if (sb->s_writers.frozen != SB_UNFROZEN) 876 if (sb->s_writers.frozen != SB_UNFROZEN)
870 return -EBUSY; 877 return -EBUSY;
871 remount_ro = (sb_flags & SB_RDONLY) && !sb_rdonly(sb); 878 remount_ro = !sb_rdonly(sb);
872 } 879 }
873 } 880 }
874 shrink_dcache_sb(sb); 881 shrink_dcache_sb(sb);
875 882
876 /* If we are remounting RDONLY and current sb is read/write, 883 /* If we are reconfiguring to RDONLY and current sb is read/write,
877 make sure there are no rw files opened */ 884 * make sure there are no files open for writing.
885 */
878 if (remount_ro) { 886 if (remount_ro) {
879 if (force) { 887 if (force) {
880 sb->s_readonly_remount = 1; 888 sb->s_readonly_remount = 1;
@@ -886,17 +894,17 @@ int do_remount_sb(struct super_block *sb, int sb_flags, void *data, int force)
886 } 894 }
887 } 895 }
888 896
889 if (sb->s_op->remount_fs) { 897 retval = legacy_reconfigure(fc);
890 retval = sb->s_op->remount_fs(sb, &sb_flags, data); 898 if (retval) {
891 if (retval) { 899 if (!force)
892 if (!force) 900 goto cancel_readonly;
893 goto cancel_readonly; 901 /* If forced remount, go ahead despite any errors */
894 /* If forced remount, go ahead despite any errors */ 902 WARN(1, "forced remount of a %s fs returned %i\n",
895 WARN(1, "forced remount of a %s fs returned %i\n", 903 sb->s_type->name, retval);
896 sb->s_type->name, retval);
897 }
898 } 904 }
899 sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (sb_flags & MS_RMT_MASK); 905
906 WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) |
907 (fc->sb_flags & fc->sb_flags_mask)));
900 /* Needs to be ordered wrt mnt_is_readonly() */ 908 /* Needs to be ordered wrt mnt_is_readonly() */
901 smp_wmb(); 909 smp_wmb();
902 sb->s_readonly_remount = 0; 910 sb->s_readonly_remount = 0;
@@ -923,10 +931,15 @@ static void do_emergency_remount_callback(struct super_block *sb)
923 down_write(&sb->s_umount); 931 down_write(&sb->s_umount);
924 if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) && 932 if (sb->s_root && sb->s_bdev && (sb->s_flags & SB_BORN) &&
925 !sb_rdonly(sb)) { 933 !sb_rdonly(sb)) {
926 /* 934 struct fs_context *fc;
927 * What lock protects sb->s_flags?? 935
928 */ 936 fc = fs_context_for_reconfigure(sb->s_root,
929 do_remount_sb(sb, SB_RDONLY, NULL, 1); 937 SB_RDONLY | SB_FORCE, SB_RDONLY);
938 if (!IS_ERR(fc)) {
939 if (parse_monolithic_mount_data(fc, NULL) == 0)
940 (void)reconfigure_super(fc);
941 put_fs_context(fc);
942 }
930 } 943 }
931 up_write(&sb->s_umount); 944 up_write(&sb->s_umount);
932} 945}
@@ -1213,6 +1226,31 @@ struct dentry *mount_nodev(struct file_system_type *fs_type,
1213} 1226}
1214EXPORT_SYMBOL(mount_nodev); 1227EXPORT_SYMBOL(mount_nodev);
1215 1228
1229static int reconfigure_single(struct super_block *s,
1230 int flags, void *data)
1231{
1232 struct fs_context *fc;
1233 int ret;
1234
1235 /* The caller really need to be passing fc down into mount_single(),
1236 * then a chunk of this can be removed. [Bollocks -- AV]
1237 * Better yet, reconfiguration shouldn't happen, but rather the second
1238 * mount should be rejected if the parameters are not compatible.
1239 */
1240 fc = fs_context_for_reconfigure(s->s_root, flags, MS_RMT_MASK);
1241 if (IS_ERR(fc))
1242 return PTR_ERR(fc);
1243
1244 ret = parse_monolithic_mount_data(fc, data);
1245 if (ret < 0)
1246 goto out;
1247
1248 ret = reconfigure_super(fc);
1249out:
1250 put_fs_context(fc);
1251 return ret;
1252}
1253
1216static int compare_single(struct super_block *s, void *p) 1254static int compare_single(struct super_block *s, void *p)
1217{ 1255{
1218 return 1; 1256 return 1;
@@ -1230,13 +1268,14 @@ struct dentry *mount_single(struct file_system_type *fs_type,
1230 return ERR_CAST(s); 1268 return ERR_CAST(s);
1231 if (!s->s_root) { 1269 if (!s->s_root) {
1232 error = fill_super(s, data, flags & SB_SILENT ? 1 : 0); 1270 error = fill_super(s, data, flags & SB_SILENT ? 1 : 0);
1233 if (error) { 1271 if (!error)
1234 deactivate_locked_super(s); 1272 s->s_flags |= SB_ACTIVE;
1235 return ERR_PTR(error);
1236 }
1237 s->s_flags |= SB_ACTIVE;
1238 } else { 1273 } else {
1239 do_remount_sb(s, flags, data, 0); 1274 error = reconfigure_single(s, flags, data);
1275 }
1276 if (unlikely(error)) {
1277 deactivate_locked_super(s);
1278 return ERR_PTR(error);
1240 } 1279 }
1241 return dget(s->s_root); 1280 return dget(s->s_root);
1242} 1281}