Commit 5a2be128 authored by David Howells's avatar David Howells Committed by Al Viro

vfs: Convert squashfs to use the new mount API

Convert the squashfs filesystem to the new internal mount API as the old
one will be obsoleted and removed.  This allows greater flexibility in
communication of mount parameters between userspace, the VFS and the
filesystem.

See Documentation/filesystems/mount_api.txt for more information.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Phillip Lougher <phillip@squashfs.org.uk>
cc: squashfs-devel@lists.sourceforge.net
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 6d56e418
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/fs_context.h>
#include <linux/vfs.h> #include <linux/vfs.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -36,26 +37,27 @@ ...@@ -36,26 +37,27 @@
static struct file_system_type squashfs_fs_type; static struct file_system_type squashfs_fs_type;
static const struct super_operations squashfs_super_ops; static const struct super_operations squashfs_super_ops;
static const struct squashfs_decompressor *supported_squashfs_filesystem(short static const struct squashfs_decompressor *supported_squashfs_filesystem(
major, short minor, short id) struct fs_context *fc,
short major, short minor, short id)
{ {
const struct squashfs_decompressor *decompressor; const struct squashfs_decompressor *decompressor;
if (major < SQUASHFS_MAJOR) { if (major < SQUASHFS_MAJOR) {
ERROR("Major/Minor mismatch, older Squashfs %d.%d " errorf(fc, "Major/Minor mismatch, older Squashfs %d.%d "
"filesystems are unsupported\n", major, minor); "filesystems are unsupported", major, minor);
return NULL; return NULL;
} else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) { } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
ERROR("Major/Minor mismatch, trying to mount newer " errorf(fc, "Major/Minor mismatch, trying to mount newer "
"%d.%d filesystem\n", major, minor); "%d.%d filesystem", major, minor);
ERROR("Please update your kernel\n"); errorf(fc, "Please update your kernel");
return NULL; return NULL;
} }
decompressor = squashfs_lookup_decompressor(id); decompressor = squashfs_lookup_decompressor(id);
if (!decompressor->supported) { if (!decompressor->supported) {
ERROR("Filesystem uses \"%s\" compression. This is not " errorf(fc, "Filesystem uses \"%s\" compression. This is not supported",
"supported\n", decompressor->name); decompressor->name);
return NULL; return NULL;
} }
...@@ -63,7 +65,7 @@ static const struct squashfs_decompressor *supported_squashfs_filesystem(short ...@@ -63,7 +65,7 @@ static const struct squashfs_decompressor *supported_squashfs_filesystem(short
} }
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_sb_info *msblk;
struct squashfs_super_block *sblk = NULL; struct squashfs_super_block *sblk = NULL;
...@@ -98,7 +100,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -98,7 +100,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk)); sblk = squashfs_read_table(sb, SQUASHFS_START, sizeof(*sblk));
if (IS_ERR(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); err = PTR_ERR(sblk);
sblk = NULL; sblk = NULL;
goto failed_mount; goto failed_mount;
...@@ -109,14 +111,15 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -109,14 +111,15 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
/* Check it is a SQUASHFS superblock */ /* Check it is a SQUASHFS superblock */
sb->s_magic = le32_to_cpu(sblk->s_magic); sb->s_magic = le32_to_cpu(sblk->s_magic);
if (sb->s_magic != SQUASHFS_MAGIC) { if (sb->s_magic != SQUASHFS_MAGIC) {
if (!silent) if (!(fc->sb_flags & SB_SILENT))
ERROR("Can't find a SQUASHFS superblock on %pg\n", errorf(fc, "Can't find a SQUASHFS superblock on %pg",
sb->s_bdev); sb->s_bdev);
goto failed_mount; goto failed_mount;
} }
/* Check the MAJOR & MINOR versions and lookup compression type */ /* Check the MAJOR & MINOR versions and lookup compression type */
msblk->decompressor = supported_squashfs_filesystem( msblk->decompressor = supported_squashfs_filesystem(
fc,
le16_to_cpu(sblk->s_major), le16_to_cpu(sblk->s_major),
le16_to_cpu(sblk->s_minor), le16_to_cpu(sblk->s_minor),
le16_to_cpu(sblk->compression)); le16_to_cpu(sblk->compression));
...@@ -133,15 +136,15 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -133,15 +136,15 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
/* Check block size for sanity */ /* Check block size for sanity */
msblk->block_size = le32_to_cpu(sblk->block_size); msblk->block_size = le32_to_cpu(sblk->block_size);
if (msblk->block_size > SQUASHFS_FILE_MAX_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 * Check the system page size is not larger than the filesystem
* block size (by default 128K). This is currently not supported. * block size (by default 128K). This is currently not supported.
*/ */
if (PAGE_SIZE > msblk->block_size) { if (PAGE_SIZE > msblk->block_size) {
ERROR("Page size > filesystem block size (%d). This is " errorf(fc, "Page size > filesystem block size (%d). This is "
"currently not supported!\n", msblk->block_size); "currently not supported!", msblk->block_size);
goto failed_mount; goto failed_mount;
} }
...@@ -152,12 +155,12 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -152,12 +155,12 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
/* Check that block_size and block_log match */ /* Check that block_size and block_log match */
if (msblk->block_size != (1 << msblk->block_log)) if (msblk->block_size != (1 << msblk->block_log))
goto failed_mount; goto insanity;
/* Check the root inode for sanity */ /* Check the root inode for sanity */
root_inode = le64_to_cpu(sblk->root_inode); root_inode = le64_to_cpu(sblk->root_inode);
if (SQUASHFS_INODE_OFFSET(root_inode) > SQUASHFS_METADATA_SIZE) 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->inode_table = le64_to_cpu(sblk->inode_table_start);
msblk->directory_table = le64_to_cpu(sblk->directory_table_start); msblk->directory_table = le64_to_cpu(sblk->directory_table_start);
...@@ -197,7 +200,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -197,7 +200,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
msblk->read_page = squashfs_cache_init("data", msblk->read_page = squashfs_cache_init("data",
squashfs_max_decompressors(), msblk->block_size); squashfs_max_decompressors(), msblk->block_size);
if (msblk->read_page == NULL) { if (msblk->read_page == NULL) {
ERROR("Failed to allocate read_page block\n"); errorf(fc, "Failed to allocate read_page block");
goto failed_mount; goto failed_mount;
} }
...@@ -205,7 +208,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -205,7 +208,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
if (IS_ERR(msblk->stream)) { if (IS_ERR(msblk->stream)) {
err = PTR_ERR(msblk->stream); err = PTR_ERR(msblk->stream);
msblk->stream = NULL; msblk->stream = NULL;
goto failed_mount; goto insanity;
} }
/* Handle xattrs */ /* Handle xattrs */
...@@ -220,7 +223,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -220,7 +223,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
msblk->xattr_id_table = squashfs_read_xattr_id_table(sb, msblk->xattr_id_table = squashfs_read_xattr_id_table(sb,
xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids); xattr_id_table_start, &msblk->xattr_table, &msblk->xattr_ids);
if (IS_ERR(msblk->xattr_id_table)) { 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); err = PTR_ERR(msblk->xattr_id_table);
msblk->xattr_id_table = NULL; msblk->xattr_id_table = NULL;
if (err != -ENOTSUPP) if (err != -ENOTSUPP)
...@@ -234,7 +237,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -234,7 +237,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
le64_to_cpu(sblk->id_table_start), next_table, le64_to_cpu(sblk->id_table_start), next_table,
le16_to_cpu(sblk->no_ids)); le16_to_cpu(sblk->no_ids));
if (IS_ERR(msblk->id_table)) { 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); err = PTR_ERR(msblk->id_table);
msblk->id_table = NULL; msblk->id_table = NULL;
goto failed_mount; goto failed_mount;
...@@ -250,7 +253,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -250,7 +253,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb, msblk->inode_lookup_table = squashfs_read_inode_lookup_table(sb,
lookup_table_start, next_table, msblk->inodes); lookup_table_start, next_table, msblk->inodes);
if (IS_ERR(msblk->inode_lookup_table)) { 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); err = PTR_ERR(msblk->inode_lookup_table);
msblk->inode_lookup_table = NULL; msblk->inode_lookup_table = NULL;
goto failed_mount; goto failed_mount;
...@@ -275,7 +278,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -275,7 +278,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
msblk->fragment_index = squashfs_read_fragment_index_table(sb, msblk->fragment_index = squashfs_read_fragment_index_table(sb,
le64_to_cpu(sblk->fragment_table_start), next_table, fragments); le64_to_cpu(sblk->fragment_table_start), next_table, fragments);
if (IS_ERR(msblk->fragment_index)) { 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); err = PTR_ERR(msblk->fragment_index);
msblk->fragment_index = NULL; msblk->fragment_index = NULL;
goto failed_mount; goto failed_mount;
...@@ -286,13 +289,13 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -286,13 +289,13 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
/* Sanity check directory_table */ /* Sanity check directory_table */
if (msblk->directory_table > next_table) { if (msblk->directory_table > next_table) {
err = -EINVAL; err = -EINVAL;
goto failed_mount; goto insanity;
} }
/* Sanity check inode_table */ /* Sanity check inode_table */
if (msblk->inode_table >= msblk->directory_table) { if (msblk->inode_table >= msblk->directory_table) {
err = -EINVAL; err = -EINVAL;
goto failed_mount; goto insanity;
} }
/* allocate root */ /* allocate root */
...@@ -321,6 +324,8 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -321,6 +324,8 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
kfree(sblk); kfree(sblk);
return 0; return 0;
insanity:
errorf(fc, "squashfs image failed sanity check");
failed_mount: failed_mount:
squashfs_cache_delete(msblk->block_cache); squashfs_cache_delete(msblk->block_cache);
squashfs_cache_delete(msblk->fragment_cache); squashfs_cache_delete(msblk->fragment_cache);
...@@ -336,6 +341,28 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -336,6 +341,28 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent)
return err; 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_statfs(struct dentry *dentry, struct kstatfs *buf)
{ {
...@@ -358,14 +385,6 @@ static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) ...@@ -358,14 +385,6 @@ 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) static void squashfs_put_super(struct super_block *sb)
{ {
if (sb->s_fs_info) { if (sb->s_fs_info) {
...@@ -384,14 +403,6 @@ static void squashfs_put_super(struct super_block *sb) ...@@ -384,14 +403,6 @@ static void squashfs_put_super(struct super_block *sb)
} }
} }
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; static struct kmem_cache *squashfs_inode_cachep;
...@@ -468,7 +479,7 @@ static void squashfs_free_inode(struct inode *inode) ...@@ -468,7 +479,7 @@ static void squashfs_free_inode(struct inode *inode)
static struct file_system_type squashfs_fs_type = { static struct file_system_type squashfs_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "squashfs", .name = "squashfs",
.mount = squashfs_mount, .init_fs_context = squashfs_init_fs_context,
.kill_sb = kill_block_super, .kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV .fs_flags = FS_REQUIRES_DEV
}; };
...@@ -479,7 +490,6 @@ static const struct super_operations squashfs_super_ops = { ...@@ -479,7 +490,6 @@ static const struct super_operations squashfs_super_ops = {
.free_inode = squashfs_free_inode, .free_inode = squashfs_free_inode,
.statfs = squashfs_statfs, .statfs = squashfs_statfs,
.put_super = squashfs_put_super, .put_super = squashfs_put_super,
.remount_fs = squashfs_remount
}; };
module_init(init_squashfs_fs); module_init(init_squashfs_fs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment