Commit f3a09c92 authored by Al Viro's avatar Al Viro

introduce fs_context methods

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent e1a91586
...@@ -51,6 +51,7 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type, ...@@ -51,6 +51,7 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
unsigned int sb_flags_mask, unsigned int sb_flags_mask,
enum fs_context_purpose purpose) enum fs_context_purpose purpose)
{ {
int (*init_fs_context)(struct fs_context *);
struct fs_context *fc; struct fs_context *fc;
int ret = -ENOMEM; int ret = -ENOMEM;
...@@ -81,7 +82,12 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type, ...@@ -81,7 +82,12 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
break; break;
} }
ret = legacy_init_fs_context(fc); /* TODO: Make all filesystems support this unconditionally */
init_fs_context = fc->fs_type->init_fs_context;
if (!init_fs_context)
init_fs_context = legacy_init_fs_context;
ret = init_fs_context(fc);
if (ret < 0) if (ret < 0)
goto err_fc; goto err_fc;
fc->need_free = true; fc->need_free = true;
...@@ -141,8 +147,8 @@ void put_fs_context(struct fs_context *fc) ...@@ -141,8 +147,8 @@ void put_fs_context(struct fs_context *fc)
deactivate_super(sb); deactivate_super(sb);
} }
if (fc->need_free) if (fc->need_free && fc->ops && fc->ops->free)
legacy_fs_context_free(fc); fc->ops->free(fc);
security_free_mnt_opts(&fc->security); security_free_mnt_opts(&fc->security);
put_net(fc->net_ns); put_net(fc->net_ns);
...@@ -180,7 +186,7 @@ static int legacy_parse_monolithic(struct fs_context *fc, void *data) ...@@ -180,7 +186,7 @@ static int legacy_parse_monolithic(struct fs_context *fc, void *data)
/* /*
* Get a mountable root with the legacy mount command. * Get a mountable root with the legacy mount command.
*/ */
int legacy_get_tree(struct fs_context *fc) static int legacy_get_tree(struct fs_context *fc)
{ {
struct legacy_fs_context *ctx = fc->fs_private; struct legacy_fs_context *ctx = fc->fs_private;
struct super_block *sb; struct super_block *sb;
...@@ -201,7 +207,7 @@ int legacy_get_tree(struct fs_context *fc) ...@@ -201,7 +207,7 @@ int legacy_get_tree(struct fs_context *fc)
/* /*
* Handle remount. * Handle remount.
*/ */
int legacy_reconfigure(struct fs_context *fc) static int legacy_reconfigure(struct fs_context *fc)
{ {
struct legacy_fs_context *ctx = fc->fs_private; struct legacy_fs_context *ctx = fc->fs_private;
struct super_block *sb = fc->root->d_sb; struct super_block *sb = fc->root->d_sb;
...@@ -213,6 +219,13 @@ int legacy_reconfigure(struct fs_context *fc) ...@@ -213,6 +219,13 @@ int legacy_reconfigure(struct fs_context *fc)
ctx ? ctx->legacy_data : NULL); ctx ? ctx->legacy_data : NULL);
} }
const struct fs_context_operations legacy_fs_context_ops = {
.free = legacy_fs_context_free,
.parse_monolithic = legacy_parse_monolithic,
.get_tree = legacy_get_tree,
.reconfigure = legacy_reconfigure,
};
/* /*
* Initialise a legacy context for a filesystem that doesn't support * Initialise a legacy context for a filesystem that doesn't support
* fs_context. * fs_context.
...@@ -222,10 +235,13 @@ static int legacy_init_fs_context(struct fs_context *fc) ...@@ -222,10 +235,13 @@ static int legacy_init_fs_context(struct fs_context *fc)
fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL); fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL);
if (!fc->fs_private) if (!fc->fs_private)
return -ENOMEM; return -ENOMEM;
fc->ops = &legacy_fs_context_ops;
return 0; return 0;
} }
int parse_monolithic_mount_data(struct fs_context *fc, void *data) int parse_monolithic_mount_data(struct fs_context *fc, void *data)
{ {
return legacy_parse_monolithic(fc, data); int (*monolithic_mount_data)(struct fs_context *, void *);
monolithic_mount_data = fc->ops->parse_monolithic;
return monolithic_mount_data(fc, data);
} }
...@@ -55,8 +55,6 @@ extern void __init chrdev_init(void); ...@@ -55,8 +55,6 @@ extern void __init chrdev_init(void);
/* /*
* fs_context.c * fs_context.c
*/ */
extern int legacy_get_tree(struct fs_context *fc);
extern int legacy_reconfigure(struct fs_context *fc);
extern int parse_monolithic_mount_data(struct fs_context *, void *); extern int parse_monolithic_mount_data(struct fs_context *, void *);
extern void fc_drop_locked(struct fs_context *); extern void fc_drop_locked(struct fs_context *);
......
...@@ -894,13 +894,15 @@ int reconfigure_super(struct fs_context *fc) ...@@ -894,13 +894,15 @@ int reconfigure_super(struct fs_context *fc)
} }
} }
retval = legacy_reconfigure(fc); if (fc->ops->reconfigure) {
if (retval) { retval = fc->ops->reconfigure(fc);
if (!force) if (retval) {
goto cancel_readonly; if (!force)
/* If forced remount, go ahead despite any errors */ goto cancel_readonly;
WARN(1, "forced remount of a %s fs returned %i\n", /* If forced remount, go ahead despite any errors */
sb->s_type->name, retval); WARN(1, "forced remount of a %s fs returned %i\n",
sb->s_type->name, retval);
}
} }
WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) | WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) |
...@@ -1294,10 +1296,28 @@ int vfs_get_tree(struct fs_context *fc) ...@@ -1294,10 +1296,28 @@ int vfs_get_tree(struct fs_context *fc)
struct super_block *sb; struct super_block *sb;
int error; int error;
error = legacy_get_tree(fc); if (fc->fs_type->fs_flags & FS_REQUIRES_DEV && !fc->source)
return -ENOENT;
if (fc->root)
return -EBUSY;
/* Get the mountable root in fc->root, with a ref on the root and a ref
* on the superblock.
*/
error = fc->ops->get_tree(fc);
if (error < 0) if (error < 0)
return error; return error;
if (!fc->root) {
pr_err("Filesystem %s get_tree() didn't set fc->root\n",
fc->fs_type->name);
/* We don't know what the locking state of the superblock is -
* if there is a superblock.
*/
BUG();
}
sb = fc->root->d_sb; sb = fc->root->d_sb;
WARN_ON(!sb->s_bdi); WARN_ON(!sb->s_bdi);
......
...@@ -61,6 +61,7 @@ struct workqueue_struct; ...@@ -61,6 +61,7 @@ struct workqueue_struct;
struct iov_iter; struct iov_iter;
struct fscrypt_info; struct fscrypt_info;
struct fscrypt_operations; struct fscrypt_operations;
struct fs_context;
extern void __init inode_init(void); extern void __init inode_init(void);
extern void __init inode_init_early(void); extern void __init inode_init_early(void);
...@@ -2173,6 +2174,7 @@ struct file_system_type { ...@@ -2173,6 +2174,7 @@ struct file_system_type {
#define FS_HAS_SUBTYPE 4 #define FS_HAS_SUBTYPE 4
#define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */ #define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */
#define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */
int (*init_fs_context)(struct fs_context *);
struct dentry *(*mount) (struct file_system_type *, int, struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *); const char *, void *);
void (*kill_sb) (struct super_block *); void (*kill_sb) (struct super_block *);
......
...@@ -20,8 +20,13 @@ struct cred; ...@@ -20,8 +20,13 @@ struct cred;
struct dentry; struct dentry;
struct file_operations; struct file_operations;
struct file_system_type; struct file_system_type;
struct mnt_namespace;
struct net; struct net;
struct pid_namespace;
struct super_block;
struct user_namespace; struct user_namespace;
struct vfsmount;
struct path;
enum fs_context_purpose { enum fs_context_purpose {
FS_CONTEXT_FOR_MOUNT, /* New superblock for explicit mount */ FS_CONTEXT_FOR_MOUNT, /* New superblock for explicit mount */
...@@ -39,6 +44,7 @@ enum fs_context_purpose { ...@@ -39,6 +44,7 @@ enum fs_context_purpose {
* See Documentation/filesystems/mounting.txt * See Documentation/filesystems/mounting.txt
*/ */
struct fs_context { struct fs_context {
const struct fs_context_operations *ops;
struct file_system_type *fs_type; struct file_system_type *fs_type;
void *fs_private; /* The filesystem's context */ void *fs_private; /* The filesystem's context */
struct dentry *root; /* The root and superblock */ struct dentry *root; /* The root and superblock */
...@@ -54,6 +60,13 @@ struct fs_context { ...@@ -54,6 +60,13 @@ struct fs_context {
bool need_free:1; /* Need to call ops->free() */ bool need_free:1; /* Need to call ops->free() */
}; };
struct fs_context_operations {
void (*free)(struct fs_context *fc);
int (*parse_monolithic)(struct fs_context *fc, void *data);
int (*get_tree)(struct fs_context *fc);
int (*reconfigure)(struct fs_context *fc);
};
/* /*
* fs_context manipulation functions. * fs_context manipulation functions.
*/ */
......
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