qnx6: convert qnx6 to use the new mount api

Convert the qnx6 filesystem to use the new mount API.

Mostly untested, since there is no qnx6 fs image readily available.
Testing did include parsing of the mmi_fs option.

Signed-off-by: Bill O'Donnell <bodonnel@redhat.com>
Link: https://lore.kernel.org/r/20240302165714.859504-1-bodonnel@redhat.com
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Bill O'Donnell 2024-03-02 10:48:34 -06:00 committed by Christian Brauner
parent 4cece76496
commit 491681d44b
No known key found for this signature in database
GPG key ID: 91C61BC06578DCA2

View file

@ -19,11 +19,11 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/statfs.h> #include <linux/statfs.h>
#include <linux/parser.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/mount.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/mpage.h> #include <linux/mpage.h>
#include <linux/fs_parser.h>
#include <linux/fs_context.h>
#include "qnx6.h" #include "qnx6.h"
static const struct super_operations qnx6_sops; static const struct super_operations qnx6_sops;
@ -31,7 +31,7 @@ static const struct super_operations qnx6_sops;
static void qnx6_put_super(struct super_block *sb); static void qnx6_put_super(struct super_block *sb);
static struct inode *qnx6_alloc_inode(struct super_block *sb); static struct inode *qnx6_alloc_inode(struct super_block *sb);
static void qnx6_free_inode(struct inode *inode); static void qnx6_free_inode(struct inode *inode);
static int qnx6_remount(struct super_block *sb, int *flags, char *data); static int qnx6_reconfigure(struct fs_context *fc);
static int qnx6_statfs(struct dentry *dentry, struct kstatfs *buf); static int qnx6_statfs(struct dentry *dentry, struct kstatfs *buf);
static int qnx6_show_options(struct seq_file *seq, struct dentry *root); static int qnx6_show_options(struct seq_file *seq, struct dentry *root);
@ -40,7 +40,6 @@ static const struct super_operations qnx6_sops = {
.free_inode = qnx6_free_inode, .free_inode = qnx6_free_inode,
.put_super = qnx6_put_super, .put_super = qnx6_put_super,
.statfs = qnx6_statfs, .statfs = qnx6_statfs,
.remount_fs = qnx6_remount,
.show_options = qnx6_show_options, .show_options = qnx6_show_options,
}; };
@ -54,10 +53,12 @@ static int qnx6_show_options(struct seq_file *seq, struct dentry *root)
return 0; return 0;
} }
static int qnx6_remount(struct super_block *sb, int *flags, char *data) static int qnx6_reconfigure(struct fs_context *fc)
{ {
struct super_block *sb = fc->root->d_sb;
sync_filesystem(sb); sync_filesystem(sb);
*flags |= SB_RDONLY; fc->sb_flags |= SB_RDONLY;
return 0; return 0;
} }
@ -218,39 +219,36 @@ void qnx6_superblock_debug(struct qnx6_super_block *sb, struct super_block *s)
#endif #endif
enum { enum {
Opt_mmifs, Opt_mmifs
Opt_err
}; };
static const match_table_t tokens = { struct qnx6_context {
{Opt_mmifs, "mmi_fs"}, unsigned long s_mount_opts;
{Opt_err, NULL}
}; };
static int qnx6_parse_options(char *options, struct super_block *sb) static const struct fs_parameter_spec qnx6_param_spec[] = {
fsparam_flag ("mmi_fs", Opt_mmifs),
{}
};
static int qnx6_parse_param(struct fs_context *fc, struct fs_parameter *param)
{ {
char *p; struct qnx6_context *ctx = fc->fs_private;
struct qnx6_sb_info *sbi = QNX6_SB(sb); struct fs_parse_result result;
substring_t args[MAX_OPT_ARGS]; int opt;
if (!options) opt = fs_parse(fc, qnx6_param_spec, param, &result);
return 1; if (opt < 0)
return opt;
while ((p = strsep(&options, ",")) != NULL) { switch (opt) {
int token; case Opt_mmifs:
if (!*p) ctx->s_mount_opts |= QNX6_MOUNT_MMI_FS;
continue; break;
default:
token = match_token(p, tokens, args); return -EINVAL;
switch (token) {
case Opt_mmifs:
set_opt(sbi->s_mount_opt, MMI_FS);
break;
default:
return 0;
}
} }
return 1; return 0;
} }
static struct buffer_head *qnx6_check_first_superblock(struct super_block *s, static struct buffer_head *qnx6_check_first_superblock(struct super_block *s,
@ -293,22 +291,25 @@ static struct buffer_head *qnx6_check_first_superblock(struct super_block *s,
static struct inode *qnx6_private_inode(struct super_block *s, static struct inode *qnx6_private_inode(struct super_block *s,
struct qnx6_root_node *p); struct qnx6_root_node *p);
static int qnx6_fill_super(struct super_block *s, void *data, int silent) static int qnx6_fill_super(struct super_block *s, struct fs_context *fc)
{ {
struct buffer_head *bh1 = NULL, *bh2 = NULL; struct buffer_head *bh1 = NULL, *bh2 = NULL;
struct qnx6_super_block *sb1 = NULL, *sb2 = NULL; struct qnx6_super_block *sb1 = NULL, *sb2 = NULL;
struct qnx6_sb_info *sbi; struct qnx6_sb_info *sbi;
struct qnx6_context *ctx = fc->fs_private;
struct inode *root; struct inode *root;
const char *errmsg; const char *errmsg;
struct qnx6_sb_info *qs; struct qnx6_sb_info *qs;
int ret = -EINVAL; int ret = -EINVAL;
u64 offset; u64 offset;
int bootblock_offset = QNX6_BOOTBLOCK_SIZE; int bootblock_offset = QNX6_BOOTBLOCK_SIZE;
int silent = fc->sb_flags & SB_SILENT;
qs = kzalloc(sizeof(struct qnx6_sb_info), GFP_KERNEL); qs = kzalloc(sizeof(struct qnx6_sb_info), GFP_KERNEL);
if (!qs) if (!qs)
return -ENOMEM; return -ENOMEM;
s->s_fs_info = qs; s->s_fs_info = qs;
qs->s_mount_opt = ctx->s_mount_opts;
/* Superblock always is 512 Byte long */ /* Superblock always is 512 Byte long */
if (!sb_set_blocksize(s, QNX6_SUPERBLOCK_SIZE)) { if (!sb_set_blocksize(s, QNX6_SUPERBLOCK_SIZE)) {
@ -316,12 +317,7 @@ static int qnx6_fill_super(struct super_block *s, void *data, int silent)
goto outnobh; goto outnobh;
} }
/* parse the mount-options */ if (qs->s_mount_opt == QNX6_MOUNT_MMI_FS) {
if (!qnx6_parse_options((char *) data, s)) {
pr_err("invalid mount options.\n");
goto outnobh;
}
if (test_opt(s, MMI_FS)) {
sb1 = qnx6_mmi_fill_super(s, silent); sb1 = qnx6_mmi_fill_super(s, silent);
if (sb1) if (sb1)
goto mmi_success; goto mmi_success;
@ -632,18 +628,43 @@ static void destroy_inodecache(void)
kmem_cache_destroy(qnx6_inode_cachep); kmem_cache_destroy(qnx6_inode_cachep);
} }
static struct dentry *qnx6_mount(struct file_system_type *fs_type, static int qnx6_get_tree(struct fs_context *fc)
int flags, const char *dev_name, void *data)
{ {
return mount_bdev(fs_type, flags, dev_name, data, qnx6_fill_super); return get_tree_bdev(fc, qnx6_fill_super);
}
static void qnx6_free_fc(struct fs_context *fc)
{
kfree(fc->fs_private);
}
static const struct fs_context_operations qnx6_context_ops = {
.parse_param = qnx6_parse_param,
.get_tree = qnx6_get_tree,
.reconfigure = qnx6_reconfigure,
.free = qnx6_free_fc,
};
static int qnx6_init_fs_context(struct fs_context *fc)
{
struct qnx6_context *ctx;
ctx = kzalloc(sizeof(struct qnx6_context), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
fc->ops = &qnx6_context_ops;
fc->fs_private = ctx;
return 0;
} }
static struct file_system_type qnx6_fs_type = { static struct file_system_type qnx6_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "qnx6", .name = "qnx6",
.mount = qnx6_mount, .kill_sb = kill_block_super,
.kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV,
.fs_flags = FS_REQUIRES_DEV, .init_fs_context = qnx6_init_fs_context,
.parameters = qnx6_param_spec,
}; };
MODULE_ALIAS_FS("qnx6"); MODULE_ALIAS_FS("qnx6");