introduce fs_context methods
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
e1a91586d5
commit
f3a09c9201
|
@ -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,
|
||||||
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)
|
||||||
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)
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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)
|
||||||
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);
|
||||||
/*
|
/*
|
||||||
* 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 *);
|
||||||
|
|
||||||
|
|
36
fs/super.c
36
fs/super.c
|
@ -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)
|
||||||
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;
|
||||||
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 {
|
||||||
#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;
|
||||||
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 {
|
||||||
* 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 {
|
||||||
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.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue