@@ -42,6 +42,7 @@ struct legacy_fs_context {
enum legacy_fs_param param_type;
};
+static int legacy_init_fs_context(struct fs_context *fc, struct dentry *dentry);
static const struct fs_context_operations legacy_fs_context_ops;
static const match_table_t common_set_sb_flag = {
@@ -239,6 +240,7 @@ struct fs_context *vfs_new_fs_context(struct file_system_type *fs_type,
unsigned int sb_flags,
enum fs_context_purpose purpose)
{
+ int (*init_fs_context)(struct fs_context *, struct dentry *);
struct fs_context *fc;
int ret = -ENOMEM;
@@ -246,15 +248,6 @@ struct fs_context *vfs_new_fs_context(struct file_system_type *fs_type,
if (!fc)
return ERR_PTR(-ENOMEM);
- if (!fs_type->init_fs_context) {
- fc->fs_private = kzalloc(sizeof(struct legacy_fs_context),
- GFP_KERNEL);
- if (!fc->fs_private)
- goto err_fc;
-
- fc->ops = &legacy_fs_context_ops;
- }
-
fc->purpose = purpose;
fc->sb_flags = sb_flags;
fc->fs_type = get_filesystem(fs_type);
@@ -285,11 +278,13 @@ struct fs_context *vfs_new_fs_context(struct file_system_type *fs_type,
/* TODO: Make all filesystems support this unconditionally */
- if (fc->fs_type->init_fs_context) {
- ret = fc->fs_type->init_fs_context(fc, reference);
- if (ret < 0)
- goto err_fc;
- }
+ 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, reference);
+ if (ret < 0)
+ goto err_fc;
/* Do the security check last because ->init_fs_context may change the
* namespace subscriptions.
@@ -499,19 +494,21 @@ static void legacy_fs_context_free(struct fs_context *fc)
{
struct legacy_fs_context *ctx = fc->fs_private;
- free_secdata(ctx->secdata);
- switch (ctx->param_type) {
- case LEGACY_FS_UNSET_PARAMS:
- case LEGACY_FS_NO_PARAMS:
- break;
- case LEGACY_FS_MAGIC_PARAMS:
- break; /* ctx->data is a weird pointer */
- default:
- kfree(ctx->legacy_data);
- break;
- }
+ if (ctx) {
+ free_secdata(ctx->secdata);
+ switch (ctx->param_type) {
+ case LEGACY_FS_UNSET_PARAMS:
+ case LEGACY_FS_NO_PARAMS:
+ break;
+ case LEGACY_FS_MAGIC_PARAMS:
+ break; /* ctx->data is a weird pointer */
+ default:
+ kfree(ctx->legacy_data);
+ break;
+ }
- kfree(ctx);
+ kfree(ctx);
+ }
}
/*
@@ -707,3 +704,18 @@ static const struct fs_context_operations legacy_fs_context_ops = {
.validate = legacy_validate,
.get_tree = legacy_get_tree,
};
+
+/*
+ * Initialise a legacy context for a filesystem that doesn't support
+ * fs_context.
+ */
+static int legacy_init_fs_context(struct fs_context *fc, struct dentry *dentry)
+{
+
+ fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL);
+ if (!fc->fs_private)
+ return -ENOMEM;
+
+ fc->ops = &legacy_fs_context_ops;
+ return 0;
+}