Commit 634440b6 authored by Eric Sandeen's avatar Eric Sandeen Committed by Christian Brauner

fat: Convert to new mount api

vfat and msdos share a common set of options, with additional, unique
options for each filesystem.

Each filesystem calls common fc initialization and parsing routines,
with an "is_vfat" parameter. For parsing, if the option is not found
in the common parameter_spec, parsing is retried with the fs-specific
parameter_spec.

This patch leaves nls loading to fill_super, so the codepage and charset
options are not validated as they are requested. This matches current
behavior. It would be possible to test-load as each option is parsed,
but that would make i.e.

mount -o "iocharset=nope,iocharset=iso8859-1"

fail, where it does not fail today because only the last iocharset
option is considered.

The obsolete "conv=" option is set up with an enum of acceptable values;
currently invalid "conv=" options are rejected as such, even though the
option is obsolete, so this patch preserves that behavior.
Signed-off-by: default avatarEric Sandeen <sandeen@redhat.com>
Link: https://lore.kernel.org/r/a9411b02-5f8e-4e1e-90aa-0c032d66c312@redhat.comAcked-by: default avatarOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: default avatarChristian Brauner <brauner@kernel.org>
parent 206d3d8e
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <linux/hash.h> #include <linux/hash.h>
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/msdos_fs.h> #include <linux/msdos_fs.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
/* /*
* vfat shortname flags * vfat shortname flags
...@@ -416,12 +418,21 @@ extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); ...@@ -416,12 +418,21 @@ extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
extern struct inode *fat_build_inode(struct super_block *sb, extern struct inode *fat_build_inode(struct super_block *sb,
struct msdos_dir_entry *de, loff_t i_pos); struct msdos_dir_entry *de, loff_t i_pos);
extern int fat_sync_inode(struct inode *inode); extern int fat_sync_inode(struct inode *inode);
extern int fat_fill_super(struct super_block *sb, void *data, int silent, extern int fat_fill_super(struct super_block *sb, struct fs_context *fc,
int isvfat, void (*setup)(struct super_block *)); void (*setup)(struct super_block *));
extern int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de); extern int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de);
extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
struct inode *i2); struct inode *i2);
extern const struct fs_parameter_spec fat_param_spec[];
int fat_init_fs_context(struct fs_context *fc, bool is_vfat);
void fat_free_fc(struct fs_context *fc);
int fat_parse_param(struct fs_context *fc, struct fs_parameter *param,
bool is_vfat);
int fat_reconfigure(struct fs_context *fc);
static inline unsigned long fat_dir_hash(int logstart) static inline unsigned long fat_dir_hash(int logstart)
{ {
return hash_32(logstart, FAT_HASH_BITS); return hash_32(logstart, FAT_HASH_BITS);
......
This diff is collapsed.
...@@ -650,24 +650,48 @@ static void setup(struct super_block *sb) ...@@ -650,24 +650,48 @@ static void setup(struct super_block *sb)
sb->s_flags |= SB_NOATIME; sb->s_flags |= SB_NOATIME;
} }
static int msdos_fill_super(struct super_block *sb, void *data, int silent) static int msdos_fill_super(struct super_block *sb, struct fs_context *fc)
{ {
return fat_fill_super(sb, data, silent, 0, setup); return fat_fill_super(sb, fc, setup);
} }
static struct dentry *msdos_mount(struct file_system_type *fs_type, static int msdos_get_tree(struct fs_context *fc)
int flags, const char *dev_name,
void *data)
{ {
return mount_bdev(fs_type, flags, dev_name, data, msdos_fill_super); return get_tree_bdev(fc, msdos_fill_super);
}
static int msdos_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
return fat_parse_param(fc, param, false);
}
static const struct fs_context_operations msdos_context_ops = {
.parse_param = msdos_parse_param,
.get_tree = msdos_get_tree,
.reconfigure = fat_reconfigure,
.free = fat_free_fc,
};
static int msdos_init_fs_context(struct fs_context *fc)
{
int err;
/* Initialize with is_vfat == false */
err = fat_init_fs_context(fc, false);
if (err)
return err;
fc->ops = &msdos_context_ops;
return 0;
} }
static struct file_system_type msdos_fs_type = { static struct file_system_type msdos_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "msdos", .name = "msdos",
.mount = msdos_mount,
.kill_sb = kill_block_super, .kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
.init_fs_context = msdos_init_fs_context,
.parameters = fat_param_spec,
}; };
MODULE_ALIAS_FS("msdos"); MODULE_ALIAS_FS("msdos");
......
...@@ -1195,24 +1195,48 @@ static void setup(struct super_block *sb) ...@@ -1195,24 +1195,48 @@ static void setup(struct super_block *sb)
sb->s_d_op = &vfat_dentry_ops; sb->s_d_op = &vfat_dentry_ops;
} }
static int vfat_fill_super(struct super_block *sb, void *data, int silent) static int vfat_fill_super(struct super_block *sb, struct fs_context *fc)
{ {
return fat_fill_super(sb, data, silent, 1, setup); return fat_fill_super(sb, fc, setup);
} }
static struct dentry *vfat_mount(struct file_system_type *fs_type, static int vfat_get_tree(struct fs_context *fc)
int flags, const char *dev_name,
void *data)
{ {
return mount_bdev(fs_type, flags, dev_name, data, vfat_fill_super); return get_tree_bdev(fc, vfat_fill_super);
}
static int vfat_parse_param(struct fs_context *fc, struct fs_parameter *param)
{
return fat_parse_param(fc, param, true);
}
static const struct fs_context_operations vfat_context_ops = {
.parse_param = vfat_parse_param,
.get_tree = vfat_get_tree,
.reconfigure = fat_reconfigure,
.free = fat_free_fc,
};
static int vfat_init_fs_context(struct fs_context *fc)
{
int err;
/* Initialize with is_vfat == true */
err = fat_init_fs_context(fc, true);
if (err)
return err;
fc->ops = &vfat_context_ops;
return 0;
} }
static struct file_system_type vfat_fs_type = { static struct file_system_type vfat_fs_type = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "vfat", .name = "vfat",
.mount = vfat_mount,
.kill_sb = kill_block_super, .kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
.init_fs_context = vfat_init_fs_context,
.parameters = fat_param_spec,
}; };
MODULE_ALIAS_FS("vfat"); MODULE_ALIAS_FS("vfat");
......
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