Merge branch 'work.mount2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Sep 2019 17:06:57 +0000 (10:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 Sep 2019 17:06:57 +0000 (10:06 -0700)
Pull misc mount API conversions from Al Viro:
 "Conversions to new API for shmem and friends and for mount_mtd()-using
  filesystems.

  As for the rest of the mount API conversions in -next, some of them
  belong in the individual trees (e.g. binderfs one should definitely go
  through android folks, after getting redone on top of their changes).
  I'm going to drop those and send the rest (trivial ones + stuff ACKed
  by maintainers) in a separate series - by that point they are
  independent from each other.

  Some stuff has already migrated into individual trees (NFS conversion,
  for example, or FUSE stuff, etc.); those presumably will go through
  the regular merges from corresponding trees."

* 'work.mount2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  vfs: Make fs_parse() handle fs_param_is_fd-type params better
  vfs: Convert ramfs, shmem, tmpfs, devtmpfs, rootfs to use the new mount API
  shmem_parse_one(): switch to use of fs_parse()
  shmem_parse_options(): take handling a single option into a helper
  shmem_parse_options(): don't bother with mpol in separate variable
  shmem_parse_options(): use a separate structure to keep the results
  make shmem_fill_super() static
  make ramfs_fill_super() static
  devtmpfs: don't mix {ramfs,shmem}_fill_super() with mount_single()
  vfs: Convert squashfs to use the new mount API
  mtd: Kill mount_mtd()
  vfs: Convert jffs2 to use the new mount API
  vfs: Convert cramfs to use the new mount API
  vfs: Convert romfs to use the new mount API
  vfs: Add a single-or-reconfig keying to vfs_get_super()

1  2 
fs/cramfs/inode.c
fs/jffs2/fs.c
fs/romfs/super.c
fs/squashfs/super.c
fs/super.c

diff --combined fs/cramfs/inode.c
index 4d1d8b7761ed0f06622981bbe2dd66e5f37ce079,e1cf433ac982fbab6890afff23609dcc4ad28351..d12ea28836a549cf6fbd034dff882de17d36537b
@@@ -24,6 -24,7 +24,7 @@@
  #include <linux/blkdev.h>
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/super.h>
+ #include <linux/fs_context.h>
  #include <linux/slab.h>
  #include <linux/vfs.h>
  #include <linux/mutex.h>
@@@ -506,18 -507,19 +507,19 @@@ static void cramfs_kill_sb(struct super
        kfree(sbi);
  }
  
- static int cramfs_remount(struct super_block *sb, int *flags, char *data)
+ static int cramfs_reconfigure(struct fs_context *fc)
  {
-       sync_filesystem(sb);
-       *flags |= SB_RDONLY;
+       sync_filesystem(fc->root->d_sb);
+       fc->sb_flags |= SB_RDONLY;
        return 0;
  }
  
- static int cramfs_read_super(struct super_block *sb,
-                            struct cramfs_super *super, int silent)
+ static int cramfs_read_super(struct super_block *sb, struct fs_context *fc,
+                            struct cramfs_super *super)
  {
        struct cramfs_sb_info *sbi = CRAMFS_SB(sb);
        unsigned long root_offset;
+       bool silent = fc->sb_flags & SB_SILENT;
  
        /* We don't know the real size yet */
        sbi->size = PAGE_SIZE;
                /* check for wrong endianness */
                if (super->magic == CRAMFS_MAGIC_WEND) {
                        if (!silent)
-                               pr_err("wrong endianness\n");
+                               errorf(fc, "cramfs: wrong endianness");
                        return -EINVAL;
                }
  
                mutex_unlock(&read_mutex);
                if (super->magic != CRAMFS_MAGIC) {
                        if (super->magic == CRAMFS_MAGIC_WEND && !silent)
-                               pr_err("wrong endianness\n");
+                               errorf(fc, "cramfs: wrong endianness");
                        else if (!silent)
-                               pr_err("wrong magic\n");
+                               errorf(fc, "cramfs: wrong magic");
                        return -EINVAL;
                }
        }
  
        /* get feature flags first */
        if (super->flags & ~CRAMFS_SUPPORTED_FLAGS) {
-               pr_err("unsupported filesystem features\n");
+               errorf(fc, "cramfs: unsupported filesystem features");
                return -EINVAL;
        }
  
        /* Check that the root inode is in a sane state */
        if (!S_ISDIR(super->root.mode)) {
-               pr_err("root is not a directory\n");
+               errorf(fc, "cramfs: root is not a directory");
                return -EINVAL;
        }
        /* correct strange, hard-coded permissions of mkcramfs */
        sbi->magic = super->magic;
        sbi->flags = super->flags;
        if (root_offset == 0)
-               pr_info("empty filesystem");
+               infof(fc, "cramfs: empty filesystem");
        else if (!(super->flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) &&
                 ((root_offset != sizeof(struct cramfs_super)) &&
                  (root_offset != 512 + sizeof(struct cramfs_super))))
        {
-               pr_err("bad root offset %lu\n", root_offset);
+               errorf(fc, "cramfs: bad root offset %lu", root_offset);
                return -EINVAL;
        }
  
@@@ -597,8 -599,6 +599,8 @@@ static int cramfs_finalize_super(struc
  
        /* Set it all up.. */
        sb->s_flags |= SB_RDONLY;
 +      sb->s_time_min = 0;
 +      sb->s_time_max = 0;
        sb->s_op = &cramfs_ops;
        root = get_cramfs_inode(sb, cramfs_root, 0);
        if (IS_ERR(root))
        return 0;
  }
  
- static int cramfs_blkdev_fill_super(struct super_block *sb, void *data,
-                                   int silent)
+ static int cramfs_blkdev_fill_super(struct super_block *sb, struct fs_context *fc)
  {
        struct cramfs_sb_info *sbi;
        struct cramfs_super super;
        for (i = 0; i < READ_BUFFERS; i++)
                buffer_blocknr[i] = -1;
  
-       err = cramfs_read_super(sb, &super, silent);
+       err = cramfs_read_super(sb, fc, &super);
        if (err)
                return err;
        return cramfs_finalize_super(sb, &super.root);
  }
  
- static int cramfs_mtd_fill_super(struct super_block *sb, void *data,
-                                int silent)
+ static int cramfs_mtd_fill_super(struct super_block *sb, struct fs_context *fc)
  {
        struct cramfs_sb_info *sbi;
        struct cramfs_super super;
  
        pr_info("checking physical address %pap for linear cramfs image\n",
                &sbi->linear_phys_addr);
-       err = cramfs_read_super(sb, &super, silent);
+       err = cramfs_read_super(sb, fc, &super);
        if (err)
                return err;
  
@@@ -949,32 -947,41 +949,41 @@@ static const struct inode_operations cr
  };
  
  static const struct super_operations cramfs_ops = {
-       .remount_fs     = cramfs_remount,
        .statfs         = cramfs_statfs,
  };
  
- static struct dentry *cramfs_mount(struct file_system_type *fs_type, int flags,
-                                  const char *dev_name, void *data)
+ static int cramfs_get_tree(struct fs_context *fc)
  {
-       struct dentry *ret = ERR_PTR(-ENOPROTOOPT);
+       int ret = -ENOPROTOOPT;
  
        if (IS_ENABLED(CONFIG_CRAMFS_MTD)) {
-               ret = mount_mtd(fs_type, flags, dev_name, data,
-                               cramfs_mtd_fill_super);
-               if (!IS_ERR(ret))
+               ret = get_tree_mtd(fc, cramfs_mtd_fill_super);
+               if (ret < 0)
                        return ret;
        }
-       if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV)) {
-               ret = mount_bdev(fs_type, flags, dev_name, data,
-                                cramfs_blkdev_fill_super);
-       }
+       if (IS_ENABLED(CONFIG_CRAMFS_BLOCKDEV))
+               ret = get_tree_bdev(fc, cramfs_blkdev_fill_super);
        return ret;
  }
  
+ static const struct fs_context_operations cramfs_context_ops = {
+       .get_tree       = cramfs_get_tree,
+       .reconfigure    = cramfs_reconfigure,
+ };
+ /*
+  * Set up the filesystem mount context.
+  */
+ static int cramfs_init_fs_context(struct fs_context *fc)
+ {
+       fc->ops = &cramfs_context_ops;
+       return 0;
+ }
  static struct file_system_type cramfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "cramfs",
-       .mount          = cramfs_mount,
+       .init_fs_context = cramfs_init_fs_context,
        .kill_sb        = cramfs_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
  };
diff --combined fs/jffs2/fs.c
index d0b59d03a7a992f6370e598ec69671fbaa1a43bb,25736676a4565fc3bbdb714b664b644f7b63f415..05fe6cf5f1ac3ba5d2470c43ec38b880c21bfcd3
@@@ -17,6 -17,7 +17,7 @@@
  #include <linux/sched.h>
  #include <linux/cred.h>
  #include <linux/fs.h>
+ #include <linux/fs_context.h>
  #include <linux/list.h>
  #include <linux/mtd/mtd.h>
  #include <linux/pagemap.h>
@@@ -184,7 -185,7 +185,7 @@@ int jffs2_do_setattr (struct inode *ino
        if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
                truncate_setsize(inode, iattr->ia_size);
                inode->i_blocks = (inode->i_size + 511) >> 9;
-       }       
+       }
  
        return 0;
  }
@@@ -391,7 -392,7 +392,7 @@@ void jffs2_dirty_inode(struct inode *in
        jffs2_do_setattr(inode, &iattr);
  }
  
- int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data)
+ int jffs2_do_remount_fs(struct super_block *sb, struct fs_context *fc)
  {
        struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
  
                mutex_unlock(&c->alloc_sem);
        }
  
-       if (!(*flags & SB_RDONLY))
+       if (!(fc->sb_flags & SB_RDONLY))
                jffs2_start_garbage_collect_thread(c);
  
-       *flags |= SB_NOATIME;
+       fc->sb_flags |= SB_NOATIME;
        return 0;
  }
  
@@@ -509,7 -510,7 +510,7 @@@ static int calculate_inocache_hashsize(
        return hashsize;
  }
  
- int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
+ int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc)
  {
        struct jffs2_sb_info *c;
        struct inode *root_i;
  
  #ifndef CONFIG_JFFS2_FS_WRITEBUFFER
        if (c->mtd->type == MTD_NANDFLASH) {
-               pr_err("Cannot operate on NAND flash unless jffs2 NAND support is compiled in\n");
+               errorf(fc, "Cannot operate on NAND flash unless jffs2 NAND support is compiled in");
                return -EINVAL;
        }
        if (c->mtd->type == MTD_DATAFLASH) {
-               pr_err("Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in\n");
+               errorf(fc, "Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in");
                return -EINVAL;
        }
  #endif
         */
        if ((c->sector_size * blocks) != c->flash_size) {
                c->flash_size = c->sector_size * blocks;
-               pr_info("Flash size not aligned to erasesize, reducing to %dKiB\n",
-                       c->flash_size / 1024);
+               infof(fc, "Flash size not aligned to erasesize, reducing to %dKiB",
+                     c->flash_size / 1024);
        }
  
        if (c->flash_size < 5*c->sector_size) {
-               pr_err("Too few erase blocks (%d)\n",
+               errorf(fc, "Too few erase blocks (%d)",
                       c->flash_size / c->sector_size);
                return -EINVAL;
        }
        sb->s_blocksize = PAGE_SIZE;
        sb->s_blocksize_bits = PAGE_SHIFT;
        sb->s_magic = JFFS2_SUPER_MAGIC;
 +      sb->s_time_min = 0;
 +      sb->s_time_max = U32_MAX;
 +
        if (!sb_rdonly(sb))
                jffs2_start_garbage_collect_thread(c);
        return 0;
diff --combined fs/romfs/super.c
index a42c0e3079dc0705c7ac49de4fbc88ab74313417,8d198b9ecf8a6b502365b02ed8679fb526818afd..e582d001f792eb317257d9e1c2ff20691b8f27fc
@@@ -65,7 -65,7 +65,7 @@@
  #include <linux/slab.h>
  #include <linux/init.h>
  #include <linux/blkdev.h>
- #include <linux/parser.h>
+ #include <linux/fs_context.h>
  #include <linux/mount.h>
  #include <linux/namei.h>
  #include <linux/statfs.h>
@@@ -423,10 -423,10 +423,10 @@@ static int romfs_statfs(struct dentry *
  /*
   * remounting must involve read-only
   */
- static int romfs_remount(struct super_block *sb, int *flags, char *data)
+ static int romfs_reconfigure(struct fs_context *fc)
  {
-       sync_filesystem(sb);
-       *flags |= SB_RDONLY;
+       sync_filesystem(fc->root->d_sb);
+       fc->sb_flags |= SB_RDONLY;
        return 0;
  }
  
@@@ -434,7 -434,6 +434,6 @@@ static const struct super_operations ro
        .alloc_inode    = romfs_alloc_inode,
        .free_inode     = romfs_free_inode,
        .statfs         = romfs_statfs,
-       .remount_fs     = romfs_remount,
  };
  
  /*
@@@ -457,7 -456,7 +456,7 @@@ static __u32 romfs_checksum(const void 
  /*
   * fill in the superblock
   */
- static int romfs_fill_super(struct super_block *sb, void *data, int silent)
+ static int romfs_fill_super(struct super_block *sb, struct fs_context *fc)
  {
        struct romfs_super_block *rsb;
        struct inode *root;
        sb->s_maxbytes = 0xFFFFFFFF;
        sb->s_magic = ROMFS_MAGIC;
        sb->s_flags |= SB_RDONLY | SB_NOATIME;
 +      sb->s_time_min = 0;
 +      sb->s_time_max = 0;
        sb->s_op = &romfs_super_ops;
  
  #ifdef CONFIG_ROMFS_ON_MTD
  
        if (rsb->word0 != ROMSB_WORD0 || rsb->word1 != ROMSB_WORD1 ||
            img_size < ROMFH_SIZE) {
-               if (!silent)
-                       pr_warn("VFS: Can't find a romfs filesystem on dev %s.\n",
+               if (!(fc->sb_flags & SB_SILENT))
+                       errorf(fc, "VFS: Can't find a romfs filesystem on dev %s.\n",
                               sb->s_id);
                goto error_rsb_inval;
        }
        storage = sb->s_mtd ? "MTD" : "the block layer";
  
        len = strnlen(rsb->name, ROMFS_MAXFN);
-       if (!silent)
+       if (!(fc->sb_flags & SB_SILENT))
                pr_notice("Mounting image '%*.*s' through %s\n",
                          (unsigned) len, (unsigned) len, rsb->name, storage);
  
@@@ -550,23 -547,34 +549,34 @@@ error_rsb
  /*
   * get a superblock for mounting
   */
- static struct dentry *romfs_mount(struct file_system_type *fs_type,
-                       int flags, const char *dev_name,
-                       void *data)
+ static int romfs_get_tree(struct fs_context *fc)
  {
-       struct dentry *ret = ERR_PTR(-EINVAL);
+       int ret = -EINVAL;
  
  #ifdef CONFIG_ROMFS_ON_MTD
-       ret = mount_mtd(fs_type, flags, dev_name, data, romfs_fill_super);
+       ret = get_tree_mtd(fc, romfs_fill_super);
  #endif
  #ifdef CONFIG_ROMFS_ON_BLOCK
-       if (ret == ERR_PTR(-EINVAL))
-               ret = mount_bdev(fs_type, flags, dev_name, data,
-                                 romfs_fill_super);
+       if (ret == -EINVAL)
+               ret = get_tree_bdev(fc, romfs_fill_super);
  #endif
        return ret;
  }
  
+ static const struct fs_context_operations romfs_context_ops = {
+       .get_tree       = romfs_get_tree,
+       .reconfigure    = romfs_reconfigure,
+ };
+ /*
+  * Set up the filesystem mount context.
+  */
+ static int romfs_init_fs_context(struct fs_context *fc)
+ {
+       fc->ops = &romfs_context_ops;
+       return 0;
+ }
  /*
   * destroy a romfs superblock in the appropriate manner
   */
@@@ -589,7 -597,7 +599,7 @@@ static void romfs_kill_sb(struct super_
  static struct file_system_type romfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "romfs",
-       .mount          = romfs_mount,
+       .init_fs_context = romfs_init_fs_context,
        .kill_sb        = romfs_kill_sb,
        .fs_flags       = FS_REQUIRES_DEV,
  };
diff --combined fs/squashfs/super.c
index a9e9837617a9fd7399e5e21d9c1dca9d77c8b005,f908c6eb1b395eec42965a94757256e0fe8d88e0..0cc4ceec056247a22515b55189b21fd9b5db4b5e
@@@ -17,6 -17,7 +17,7 @@@
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/fs.h>
+ #include <linux/fs_context.h>
  #include <linux/vfs.h>
  #include <linux/slab.h>
  #include <linux/mutex.h>
  static struct file_system_type squashfs_fs_type;
  static const struct super_operations squashfs_super_ops;
  
- static const struct squashfs_decompressor *supported_squashfs_filesystem(short
-       major, short minor, short id)
+ static const struct squashfs_decompressor *supported_squashfs_filesystem(
+       struct fs_context *fc,
+       short major, short minor, short id)
  {
        const struct squashfs_decompressor *decompressor;
  
        if (major < SQUASHFS_MAJOR) {
-               ERROR("Major/Minor mismatch, older Squashfs %d.%d "
-                       "filesystems are unsupported\n", major, minor);
+               errorf(fc, "Major/Minor mismatch, older Squashfs %d.%d "
+                      "filesystems are unsupported", major, minor);
                return NULL;
        } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
-               ERROR("Major/Minor mismatch, trying to mount newer "
-                       "%d.%d filesystem\n", major, minor);
-               ERROR("Please update your kernel\n");
+               errorf(fc, "Major/Minor mismatch, trying to mount newer "
+                      "%d.%d filesystem", major, minor);
+               errorf(fc, "Please update your kernel");
                return NULL;
        }
  
        decompressor = squashfs_lookup_decompressor(id);
        if (!decompressor->supported) {
-               ERROR("Filesystem uses \"%s\" compression. This is not "
-                       "supported\n", decompressor->name);
+               errorf(fc, "Filesystem uses \"%s\" compression. This is not supported",
+                      decompressor->name);
                return NULL;
        }
  
@@@ -63,7 -65,7 +65,7 @@@
  }
  
  
- static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
+ static int squashfs_fill_super(struct super_block *sb, struct fs_context *fc)
  {
        struct squashfs_sb_info *msblk;
        struct squashfs_super_block *sblk = NULL;
        sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk));
  
        if (IS_ERR(sblk)) {
-               ERROR("unable to read squashfs_super_block\n");
+               errorf(fc, "unable to read squashfs_super_block");
                err = PTR_ERR(sblk);
                sblk = NULL;
                goto failed_mount;
        /* Check it is a SQUASHFS superblock */
        sb->s_magic = le32_to_cpu(sblk->s_magic);
        if (sb->s_magic != SQUASHFS_MAGIC) {
-               if (!silent)
-                       ERROR("Can't find a SQUASHFS superblock on %pg\n",
-                                               sb->s_bdev);
+               if (!(fc->sb_flags & SB_SILENT))
+                       errorf(fc, "Can't find a SQUASHFS superblock on %pg",
+                              sb->s_bdev);
                goto failed_mount;
        }
  
        /* Check the MAJOR & MINOR versions and lookup compression type */
        msblk->decompressor = supported_squashfs_filesystem(
+                       fc,
                        le16_to_cpu(sblk->s_major),
                        le16_to_cpu(sblk->s_minor),
                        le16_to_cpu(sblk->compression));
        /* Check block size for sanity */
        msblk->block_size = le32_to_cpu(sblk->block_size);
        if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
-               goto failed_mount;
+               goto insanity;
  
        /*
         * Check the system page size is not larger than the filesystem
         * block size (by default 128K).  This is currently not supported.
         */
        if (PAGE_SIZE > msblk->block_size) {
-               ERROR("Page size > filesystem block size (%d).  This is "
-                       "currently not supported!\n", msblk->block_size);
+               errorf(fc, "Page size > filesystem block size (%d).  This is "
+                      "currently not supported!", msblk->block_size);
                goto failed_mount;
        }
  
  
        /* Check that block_size and block_log match */
        if (msblk->block_size != (1 << msblk->block_log))
-               goto failed_mount;
+               goto insanity;
  
        /* Check the root inode for sanity */
        root_inode = le64_to_cpu(sblk->root_inode);
        if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE)
-               goto failed_mount;
+               goto insanity;
  
        msblk->inode_table = le64_to_cpu(sblk->inode_table_start);
        msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
                (u64) le64_to_cpu(sblk->id_table_start));
  
        sb->s_maxbytes = MAX_LFS_FILESIZE;
 +      sb->s_time_min = 0;
 +      sb->s_time_max = U32_MAX;
        sb->s_flags |= SB_RDONLY;
        sb->s_op = &squashfs_super_ops;
  
        msblk->read_page = squashfs_cache_init("data",
                squashfs_max_decompressors(), msblk->block_size);
        if (msblk->read_page == NULL) {
-               ERROR("Failed to allocate read_page block\n");
+               errorf(fc, "Failed to allocate read_page block");
                goto failed_mount;
        }
  
        if (IS_ERR(msblk->stream)) {
                err = PTR_ERR(msblk->stream);
                msblk->stream = NULL;
-               goto failed_mount;
+               goto insanity;
        }
  
        /* Handle xattrs */
        msblk->xattr_id_table = squashfs_read_xattr_id_table(sb,
                xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids);
        if (IS_ERR(msblk->xattr_id_table)) {
-               ERROR("unable to read xattr id index table\n");
+               errorf(fc, "unable to read xattr id index table");
                err = PTR_ERR(msblk->xattr_id_table);
                msblk->xattr_id_table = NULL;
                if (err != -ENOTSUPP)
@@@ -236,7 -237,7 +239,7 @@@ allocate_id_index_table
                le64_to_cpu(sblk->id_table_start), next_table,
                le16_to_cpu(sblk->no_ids));
        if (IS_ERR(msblk->id_table)) {
-               ERROR("unable to read id index table\n");
+               errorf(fc, "unable to read id index table");
                err = PTR_ERR(msblk->id_table);
                msblk->id_table = NULL;
                goto failed_mount;
        msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
                lookup_table_start, next_table, msblk->inodes);
        if (IS_ERR(msblk->inode_lookup_table)) {
-               ERROR("unable to read inode lookup table\n");
+               errorf(fc, "unable to read inode lookup table");
                err = PTR_ERR(msblk->inode_lookup_table);
                msblk->inode_lookup_table = NULL;
                goto failed_mount;
@@@ -277,7 -278,7 +280,7 @@@ handle_fragments
        msblk->fragment_index = squashfs_read_fragment_index_table(sb,
                le64_to_cpu(sblk->fragment_table_start), next_table, fragments);
        if (IS_ERR(msblk->fragment_index)) {
-               ERROR("unable to read fragment index table\n");
+               errorf(fc, "unable to read fragment index table");
                err = PTR_ERR(msblk->fragment_index);
                msblk->fragment_index = NULL;
                goto failed_mount;
@@@ -288,13 -289,13 +291,13 @@@ check_directory_table
        /* Sanity check directory_table */
        if (msblk->directory_table > next_table) {
                err = -EINVAL;
-               goto failed_mount;
+               goto insanity;
        }
  
        /* Sanity check inode_table */
        if (msblk->inode_table >= msblk->directory_table) {
                err = -EINVAL;
-               goto failed_mount;
+               goto insanity;
        }
  
        /* allocate root */
        kfree(sblk);
        return 0;
  
+ insanity:
+       errorf(fc, "squashfs image failed sanity check");
  failed_mount:
        squashfs_cache_delete(msblk->block_cache);
        squashfs_cache_delete(msblk->fragment_cache);
        return err;
  }
  
+ static int squashfs_get_tree(struct fs_context *fc)
+ {
+       return get_tree_bdev(fc, squashfs_fill_super);
+ }
+ static int squashfs_reconfigure(struct fs_context *fc)
+ {
+       sync_filesystem(fc->root->d_sb);
+       fc->sb_flags |= SB_RDONLY;
+       return 0;
+ }
+ static const struct fs_context_operations squashfs_context_ops = {
+       .get_tree       = squashfs_get_tree,
+       .reconfigure    = squashfs_reconfigure,
+ };
+ static int squashfs_init_fs_context(struct fs_context *fc)
+ {
+       fc->ops = &squashfs_context_ops;
+       return 0;
+ }
  
  static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
  {
  }
  
  
- static int squashfs_remount(struct super_block *sb, int *flags, char *data)
- {
-       sync_filesystem(sb);
-       *flags |= SB_RDONLY;
-       return 0;
- }
  static void squashfs_put_super(struct super_block *sb)
  {
        if (sb->s_fs_info) {
        }
  }
  
- static struct dentry *squashfs_mount(struct file_system_type *fs_type,
-                               int flags, const char *dev_name, void *data)
- {
-       return mount_bdev(fs_type, flags, dev_name, data, squashfs_fill_super);
- }
  static struct kmem_cache *squashfs_inode_cachep;
  
  
@@@ -470,7 -479,7 +481,7 @@@ static void squashfs_free_inode(struct 
  static struct file_system_type squashfs_fs_type = {
        .owner = THIS_MODULE,
        .name = "squashfs",
-       .mount = squashfs_mount,
+       .init_fs_context = squashfs_init_fs_context,
        .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV
  };
@@@ -481,7 -490,6 +492,6 @@@ static const struct super_operations sq
        .free_inode = squashfs_free_inode,
        .statfs = squashfs_statfs,
        .put_super = squashfs_put_super,
-       .remount_fs = squashfs_remount
  };
  
  module_init(init_squashfs_fs);
diff --combined fs/super.c
index 2d679db9e8c7b64783f34e32e299b8e2d74ed2af,beaf076d97339a0f1fc041d5f52a8dedcc5fbcfa..8020974b2a685e196d0f7c9077f2c3334e46fbd3
@@@ -32,7 -32,6 +32,7 @@@
  #include <linux/backing-dev.h>
  #include <linux/rculist_bl.h>
  #include <linux/cleancache.h>
 +#include <linux/fscrypt.h>
  #include <linux/fsnotify.h>
  #include <linux/lockdep.h>
  #include <linux/user_namespace.h>
@@@ -258,8 -257,6 +258,8 @@@ static struct super_block *alloc_super(
        s->s_maxbytes = MAX_NON_LFS;
        s->s_op = &default_op;
        s->s_time_gran = 1000000000;
 +      s->s_time_min = TIME64_MIN;
 +      s->s_time_max = TIME64_MAX;
        s->cleancache_poolid = CLEANCACHE_NO_POOL;
  
        s->s_shrink.seeks = DEFAULT_SEEKS;
@@@ -293,7 -290,6 +293,7 @@@ static void __put_super(struct super_bl
                WARN_ON(s->s_inode_lru.node);
                WARN_ON(!list_empty(&s->s_mounts));
                security_sb_free(s);
 +              fscrypt_sb_free(s);
                put_user_ns(s->s_user_ns);
                kfree(s->s_subtype);
                call_rcu(&s->rcu, destroy_super_rcu);
@@@ -1164,9 -1160,11 +1164,11 @@@ int vfs_get_super(struct fs_context *fc
  {
        int (*test)(struct super_block *, struct fs_context *);
        struct super_block *sb;
+       int err;
  
        switch (keying) {
        case vfs_get_single_super:
+       case vfs_get_single_reconf_super:
                test = test_single_super;
                break;
        case vfs_get_keyed_super:
                return PTR_ERR(sb);
  
        if (!sb->s_root) {
-               int err = fill_super(sb, fc);
-               if (err) {
-                       deactivate_locked_super(sb);
-                       return err;
-               }
+               err = fill_super(sb, fc);
+               if (err)
+                       goto error;
  
                sb->s_flags |= SB_ACTIVE;
+               fc->root = dget(sb->s_root);
+       } else {
+               fc->root = dget(sb->s_root);
+               if (keying == vfs_get_single_reconf_super) {
+                       err = reconfigure_super(fc);
+                       if (err < 0) {
+                               dput(fc->root);
+                               fc->root = NULL;
+                               goto error;
+                       }
+               }
        }
  
-       BUG_ON(fc->root);
-       fc->root = dget(sb->s_root);
        return 0;
+ error:
+       deactivate_locked_super(sb);
+       return err;
  }
  EXPORT_SYMBOL(vfs_get_super);
  
@@@ -1215,6 -1224,14 +1228,14 @@@ int get_tree_single(struct fs_context *
  }
  EXPORT_SYMBOL(get_tree_single);
  
+ int get_tree_single_reconf(struct fs_context *fc,
+                 int (*fill_super)(struct super_block *sb,
+                                   struct fs_context *fc))
+ {
+       return vfs_get_super(fc, vfs_get_single_reconf_super, fill_super);
+ }
+ EXPORT_SYMBOL(get_tree_single_reconf);
  int get_tree_keyed(struct fs_context *fc,
                  int (*fill_super)(struct super_block *sb,
                                    struct fs_context *fc),