ASoC: Merge v6.5-rc2
[platform/kernel/linux-starfive.git] / fs / super.c
index 04bc62a..e781226 100644 (file)
@@ -236,7 +236,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
                                        &type->s_writers_key[i]))
                        goto fail;
        }
-       init_waitqueue_head(&s->s_writers.wait_unfrozen);
        s->s_bdi = &noop_backing_dev_info;
        s->s_flags = flags;
        if (s->s_user_ns != &init_user_ns)
@@ -595,7 +594,7 @@ retry:
        fc->s_fs_info = NULL;
        s->s_type = fc->fs_type;
        s->s_iflags |= fc->s_iflags;
-       strlcpy(s->s_id, s->s_type->name, sizeof(s->s_id));
+       strscpy(s->s_id, s->s_type->name, sizeof(s->s_id));
        list_add_tail(&s->s_list, &super_blocks);
        hlist_add_head(&s->s_instances, &s->s_type->fs_supers);
        spin_unlock(&sb_lock);
@@ -674,7 +673,7 @@ retry:
                return ERR_PTR(err);
        }
        s->s_type = type;
-       strlcpy(s->s_id, type->name, sizeof(s->s_id));
+       strscpy(s->s_id, type->name, sizeof(s->s_id));
        list_add_tail(&s->s_list, &super_blocks);
        hlist_add_head(&s->s_instances, &type->fs_supers);
        spin_unlock(&sb_lock);
@@ -903,6 +902,7 @@ int reconfigure_super(struct fs_context *fc)
        struct super_block *sb = fc->root->d_sb;
        int retval;
        bool remount_ro = false;
+       bool remount_rw = false;
        bool force = fc->sb_flags & SB_FORCE;
 
        if (fc->sb_flags_mask & ~MS_RMT_MASK)
@@ -920,7 +920,7 @@ int reconfigure_super(struct fs_context *fc)
                    bdev_read_only(sb->s_bdev))
                        return -EACCES;
 #endif
-
+               remount_rw = !(fc->sb_flags & SB_RDONLY) && sb_rdonly(sb);
                remount_ro = (fc->sb_flags & SB_RDONLY) && !sb_rdonly(sb);
        }
 
@@ -943,13 +943,18 @@ int reconfigure_super(struct fs_context *fc)
         */
        if (remount_ro) {
                if (force) {
-                       sb->s_readonly_remount = 1;
-                       smp_wmb();
+                       sb_start_ro_state_change(sb);
                } else {
                        retval = sb_prepare_remount_readonly(sb);
                        if (retval)
                                return retval;
                }
+       } else if (remount_rw) {
+               /*
+                * Protect filesystem's reconfigure code from writes from
+                * userspace until reconfigure finishes.
+                */
+               sb_start_ro_state_change(sb);
        }
 
        if (fc->ops->reconfigure) {
@@ -965,9 +970,7 @@ int reconfigure_super(struct fs_context *fc)
 
        WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) |
                                 (fc->sb_flags & fc->sb_flags_mask)));
-       /* Needs to be ordered wrt mnt_is_readonly() */
-       smp_wmb();
-       sb->s_readonly_remount = 0;
+       sb_end_ro_state_change(sb);
 
        /*
         * Some filesystems modify their metadata via some other path than the
@@ -982,7 +985,7 @@ int reconfigure_super(struct fs_context *fc)
        return 0;
 
 cancel_readonly:
-       sb->s_readonly_remount = 0;
+       sb_end_ro_state_change(sb);
        return retval;
 }
 
@@ -1206,6 +1209,22 @@ int get_tree_keyed(struct fs_context *fc,
 EXPORT_SYMBOL(get_tree_keyed);
 
 #ifdef CONFIG_BLOCK
+static void fs_mark_dead(struct block_device *bdev)
+{
+       struct super_block *sb;
+
+       sb = get_super(bdev);
+       if (!sb)
+               return;
+
+       if (sb->s_op->shutdown)
+               sb->s_op->shutdown(sb);
+       drop_super(sb);
+}
+
+static const struct blk_holder_ops fs_holder_ops = {
+       .mark_dead              = fs_mark_dead,
+};
 
 static int set_bdev_super(struct super_block *s, void *data)
 {
@@ -1239,16 +1258,13 @@ int get_tree_bdev(struct fs_context *fc,
 {
        struct block_device *bdev;
        struct super_block *s;
-       fmode_t mode = FMODE_READ | FMODE_EXCL;
        int error = 0;
 
-       if (!(fc->sb_flags & SB_RDONLY))
-               mode |= FMODE_WRITE;
-
        if (!fc->source)
                return invalf(fc, "No source specified");
 
-       bdev = blkdev_get_by_path(fc->source, mode, fc->fs_type);
+       bdev = blkdev_get_by_path(fc->source, sb_open_mode(fc->sb_flags),
+                                 fc->fs_type, &fs_holder_ops);
        if (IS_ERR(bdev)) {
                errorf(fc, "%s: Can't open blockdev", fc->source);
                return PTR_ERR(bdev);
@@ -1262,7 +1278,7 @@ int get_tree_bdev(struct fs_context *fc,
        if (bdev->bd_fsfreeze_count > 0) {
                mutex_unlock(&bdev->bd_fsfreeze_mutex);
                warnf(fc, "%pg: Can't mount, blockdev is frozen", bdev);
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fc->fs_type);
                return -EBUSY;
        }
 
@@ -1271,7 +1287,7 @@ int get_tree_bdev(struct fs_context *fc,
        s = sget_fc(fc, test_bdev_super_fc, set_bdev_super_fc);
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        if (IS_ERR(s)) {
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fc->fs_type);
                return PTR_ERR(s);
        }
 
@@ -1280,7 +1296,7 @@ int get_tree_bdev(struct fs_context *fc,
                if ((fc->sb_flags ^ s->s_flags) & SB_RDONLY) {
                        warnf(fc, "%pg: Can't mount, would change RO state", bdev);
                        deactivate_locked_super(s);
-                       blkdev_put(bdev, mode);
+                       blkdev_put(bdev, fc->fs_type);
                        return -EBUSY;
                }
 
@@ -1292,10 +1308,9 @@ int get_tree_bdev(struct fs_context *fc,
                 * holding an active reference.
                 */
                up_write(&s->s_umount);
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fc->fs_type);
                down_write(&s->s_umount);
        } else {
-               s->s_mode = mode;
                snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
                shrinker_debugfs_rename(&s->s_shrink, "sb-%s:%s",
                                        fc->fs_type->name, s->s_id);
@@ -1327,13 +1342,10 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 {
        struct block_device *bdev;
        struct super_block *s;
-       fmode_t mode = FMODE_READ | FMODE_EXCL;
        int error = 0;
 
-       if (!(flags & SB_RDONLY))
-               mode |= FMODE_WRITE;
-
-       bdev = blkdev_get_by_path(dev_name, mode, fs_type);
+       bdev = blkdev_get_by_path(dev_name, sb_open_mode(flags), fs_type,
+                                 &fs_holder_ops);
        if (IS_ERR(bdev))
                return ERR_CAST(bdev);
 
@@ -1369,10 +1381,9 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
                 * holding an active reference.
                 */
                up_write(&s->s_umount);
-               blkdev_put(bdev, mode);
+               blkdev_put(bdev, fs_type);
                down_write(&s->s_umount);
        } else {
-               s->s_mode = mode;
                snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev);
                shrinker_debugfs_rename(&s->s_shrink, "sb-%s:%s",
                                        fs_type->name, s->s_id);
@@ -1392,7 +1403,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
 error_s:
        error = PTR_ERR(s);
 error_bdev:
-       blkdev_put(bdev, mode);
+       blkdev_put(bdev, fs_type);
 error:
        return ERR_PTR(error);
 }
@@ -1401,13 +1412,11 @@ EXPORT_SYMBOL(mount_bdev);
 void kill_block_super(struct super_block *sb)
 {
        struct block_device *bdev = sb->s_bdev;
-       fmode_t mode = sb->s_mode;
 
        bdev->bd_super = NULL;
        generic_shutdown_super(sb);
        sync_blockdev(bdev);
-       WARN_ON_ONCE(!(mode & FMODE_EXCL));
-       blkdev_put(bdev, mode | FMODE_EXCL);
+       blkdev_put(bdev, sb->s_type);
 }
 
 EXPORT_SYMBOL(kill_block_super);
@@ -1706,7 +1715,6 @@ int freeze_super(struct super_block *sb)
        if (ret) {
                sb->s_writers.frozen = SB_UNFROZEN;
                sb_freeze_unlock(sb, SB_FREEZE_PAGEFAULT);
-               wake_up(&sb->s_writers.wait_unfrozen);
                deactivate_locked_super(sb);
                return ret;
        }
@@ -1722,7 +1730,6 @@ int freeze_super(struct super_block *sb)
                                "VFS:Filesystem freeze failed\n");
                        sb->s_writers.frozen = SB_UNFROZEN;
                        sb_freeze_unlock(sb, SB_FREEZE_FS);
-                       wake_up(&sb->s_writers.wait_unfrozen);
                        deactivate_locked_super(sb);
                        return ret;
                }
@@ -1768,7 +1775,6 @@ static int thaw_super_locked(struct super_block *sb)
        sb->s_writers.frozen = SB_UNFROZEN;
        sb_freeze_unlock(sb, SB_FREEZE_FS);
 out:
-       wake_up(&sb->s_writers.wait_unfrozen);
        deactivate_locked_super(sb);
        return 0;
 }