cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fs_context.c (18110B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* Provide a way to create a superblock configuration context within the kernel
      3 * that allows a superblock to be set up prior to mounting.
      4 *
      5 * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.
      6 * Written by David Howells (dhowells@redhat.com)
      7 */
      8
      9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
     10#include <linux/module.h>
     11#include <linux/fs_context.h>
     12#include <linux/fs_parser.h>
     13#include <linux/fs.h>
     14#include <linux/mount.h>
     15#include <linux/nsproxy.h>
     16#include <linux/slab.h>
     17#include <linux/magic.h>
     18#include <linux/security.h>
     19#include <linux/mnt_namespace.h>
     20#include <linux/pid_namespace.h>
     21#include <linux/user_namespace.h>
     22#include <net/net_namespace.h>
     23#include <asm/sections.h>
     24#include "mount.h"
     25#include "internal.h"
     26
     27enum legacy_fs_param {
     28	LEGACY_FS_UNSET_PARAMS,
     29	LEGACY_FS_MONOLITHIC_PARAMS,
     30	LEGACY_FS_INDIVIDUAL_PARAMS,
     31};
     32
     33struct legacy_fs_context {
     34	char			*legacy_data;	/* Data page for legacy filesystems */
     35	size_t			data_size;
     36	enum legacy_fs_param	param_type;
     37};
     38
     39static int legacy_init_fs_context(struct fs_context *fc);
     40
     41static const struct constant_table common_set_sb_flag[] = {
     42	{ "dirsync",	SB_DIRSYNC },
     43	{ "lazytime",	SB_LAZYTIME },
     44	{ "mand",	SB_MANDLOCK },
     45	{ "ro",		SB_RDONLY },
     46	{ "sync",	SB_SYNCHRONOUS },
     47	{ },
     48};
     49
     50static const struct constant_table common_clear_sb_flag[] = {
     51	{ "async",	SB_SYNCHRONOUS },
     52	{ "nolazytime",	SB_LAZYTIME },
     53	{ "nomand",	SB_MANDLOCK },
     54	{ "rw",		SB_RDONLY },
     55	{ },
     56};
     57
     58/*
     59 * Check for a common mount option that manipulates s_flags.
     60 */
     61static int vfs_parse_sb_flag(struct fs_context *fc, const char *key)
     62{
     63	unsigned int token;
     64
     65	token = lookup_constant(common_set_sb_flag, key, 0);
     66	if (token) {
     67		fc->sb_flags |= token;
     68		fc->sb_flags_mask |= token;
     69		return 0;
     70	}
     71
     72	token = lookup_constant(common_clear_sb_flag, key, 0);
     73	if (token) {
     74		fc->sb_flags &= ~token;
     75		fc->sb_flags_mask |= token;
     76		return 0;
     77	}
     78
     79	return -ENOPARAM;
     80}
     81
     82/**
     83 * vfs_parse_fs_param_source - Handle setting "source" via parameter
     84 * @fc: The filesystem context to modify
     85 * @param: The parameter
     86 *
     87 * This is a simple helper for filesystems to verify that the "source" they
     88 * accept is sane.
     89 *
     90 * Returns 0 on success, -ENOPARAM if this is not  "source" parameter, and
     91 * -EINVAL otherwise. In the event of failure, supplementary error information
     92 *  is logged.
     93 */
     94int vfs_parse_fs_param_source(struct fs_context *fc, struct fs_parameter *param)
     95{
     96	if (strcmp(param->key, "source") != 0)
     97		return -ENOPARAM;
     98
     99	if (param->type != fs_value_is_string)
    100		return invalf(fc, "Non-string source");
    101
    102	if (fc->source)
    103		return invalf(fc, "Multiple sources");
    104
    105	fc->source = param->string;
    106	param->string = NULL;
    107	return 0;
    108}
    109EXPORT_SYMBOL(vfs_parse_fs_param_source);
    110
    111/**
    112 * vfs_parse_fs_param - Add a single parameter to a superblock config
    113 * @fc: The filesystem context to modify
    114 * @param: The parameter
    115 *
    116 * A single mount option in string form is applied to the filesystem context
    117 * being set up.  Certain standard options (for example "ro") are translated
    118 * into flag bits without going to the filesystem.  The active security module
    119 * is allowed to observe and poach options.  Any other options are passed over
    120 * to the filesystem to parse.
    121 *
    122 * This may be called multiple times for a context.
    123 *
    124 * Returns 0 on success and a negative error code on failure.  In the event of
    125 * failure, supplementary error information may have been set.
    126 */
    127int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param)
    128{
    129	int ret;
    130
    131	if (!param->key)
    132		return invalf(fc, "Unnamed parameter\n");
    133
    134	ret = vfs_parse_sb_flag(fc, param->key);
    135	if (ret != -ENOPARAM)
    136		return ret;
    137
    138	ret = security_fs_context_parse_param(fc, param);
    139	if (ret != -ENOPARAM)
    140		/* Param belongs to the LSM or is disallowed by the LSM; so
    141		 * don't pass to the FS.
    142		 */
    143		return ret;
    144
    145	if (fc->ops->parse_param) {
    146		ret = fc->ops->parse_param(fc, param);
    147		if (ret != -ENOPARAM)
    148			return ret;
    149	}
    150
    151	/* If the filesystem doesn't take any arguments, give it the
    152	 * default handling of source.
    153	 */
    154	ret = vfs_parse_fs_param_source(fc, param);
    155	if (ret != -ENOPARAM)
    156		return ret;
    157
    158	return invalf(fc, "%s: Unknown parameter '%s'",
    159		      fc->fs_type->name, param->key);
    160}
    161EXPORT_SYMBOL(vfs_parse_fs_param);
    162
    163/**
    164 * vfs_parse_fs_string - Convenience function to just parse a string.
    165 */
    166int vfs_parse_fs_string(struct fs_context *fc, const char *key,
    167			const char *value, size_t v_size)
    168{
    169	int ret;
    170
    171	struct fs_parameter param = {
    172		.key	= key,
    173		.type	= fs_value_is_flag,
    174		.size	= v_size,
    175	};
    176
    177	if (value) {
    178		param.string = kmemdup_nul(value, v_size, GFP_KERNEL);
    179		if (!param.string)
    180			return -ENOMEM;
    181		param.type = fs_value_is_string;
    182	}
    183
    184	ret = vfs_parse_fs_param(fc, &param);
    185	kfree(param.string);
    186	return ret;
    187}
    188EXPORT_SYMBOL(vfs_parse_fs_string);
    189
    190/**
    191 * generic_parse_monolithic - Parse key[=val][,key[=val]]* mount data
    192 * @ctx: The superblock configuration to fill in.
    193 * @data: The data to parse
    194 *
    195 * Parse a blob of data that's in key[=val][,key[=val]]* form.  This can be
    196 * called from the ->monolithic_mount_data() fs_context operation.
    197 *
    198 * Returns 0 on success or the error returned by the ->parse_option() fs_context
    199 * operation on failure.
    200 */
    201int generic_parse_monolithic(struct fs_context *fc, void *data)
    202{
    203	char *options = data, *key;
    204	int ret = 0;
    205
    206	if (!options)
    207		return 0;
    208
    209	ret = security_sb_eat_lsm_opts(options, &fc->security);
    210	if (ret)
    211		return ret;
    212
    213	while ((key = strsep(&options, ",")) != NULL) {
    214		if (*key) {
    215			size_t v_len = 0;
    216			char *value = strchr(key, '=');
    217
    218			if (value) {
    219				if (value == key)
    220					continue;
    221				*value++ = 0;
    222				v_len = strlen(value);
    223			}
    224			ret = vfs_parse_fs_string(fc, key, value, v_len);
    225			if (ret < 0)
    226				break;
    227		}
    228	}
    229
    230	return ret;
    231}
    232EXPORT_SYMBOL(generic_parse_monolithic);
    233
    234/**
    235 * alloc_fs_context - Create a filesystem context.
    236 * @fs_type: The filesystem type.
    237 * @reference: The dentry from which this one derives (or NULL)
    238 * @sb_flags: Filesystem/superblock flags (SB_*)
    239 * @sb_flags_mask: Applicable members of @sb_flags
    240 * @purpose: The purpose that this configuration shall be used for.
    241 *
    242 * Open a filesystem and create a mount context.  The mount context is
    243 * initialised with the supplied flags and, if a submount/automount from
    244 * another superblock (referred to by @reference) is supplied, may have
    245 * parameters such as namespaces copied across from that superblock.
    246 */
    247static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
    248				      struct dentry *reference,
    249				      unsigned int sb_flags,
    250				      unsigned int sb_flags_mask,
    251				      enum fs_context_purpose purpose)
    252{
    253	int (*init_fs_context)(struct fs_context *);
    254	struct fs_context *fc;
    255	int ret = -ENOMEM;
    256
    257	fc = kzalloc(sizeof(struct fs_context), GFP_KERNEL_ACCOUNT);
    258	if (!fc)
    259		return ERR_PTR(-ENOMEM);
    260
    261	fc->purpose	= purpose;
    262	fc->sb_flags	= sb_flags;
    263	fc->sb_flags_mask = sb_flags_mask;
    264	fc->fs_type	= get_filesystem(fs_type);
    265	fc->cred	= get_current_cred();
    266	fc->net_ns	= get_net(current->nsproxy->net_ns);
    267	fc->log.prefix	= fs_type->name;
    268
    269	mutex_init(&fc->uapi_mutex);
    270
    271	switch (purpose) {
    272	case FS_CONTEXT_FOR_MOUNT:
    273		fc->user_ns = get_user_ns(fc->cred->user_ns);
    274		break;
    275	case FS_CONTEXT_FOR_SUBMOUNT:
    276		fc->user_ns = get_user_ns(reference->d_sb->s_user_ns);
    277		break;
    278	case FS_CONTEXT_FOR_RECONFIGURE:
    279		atomic_inc(&reference->d_sb->s_active);
    280		fc->user_ns = get_user_ns(reference->d_sb->s_user_ns);
    281		fc->root = dget(reference);
    282		break;
    283	}
    284
    285	/* TODO: Make all filesystems support this unconditionally */
    286	init_fs_context = fc->fs_type->init_fs_context;
    287	if (!init_fs_context)
    288		init_fs_context = legacy_init_fs_context;
    289
    290	ret = init_fs_context(fc);
    291	if (ret < 0)
    292		goto err_fc;
    293	fc->need_free = true;
    294	return fc;
    295
    296err_fc:
    297	put_fs_context(fc);
    298	return ERR_PTR(ret);
    299}
    300
    301struct fs_context *fs_context_for_mount(struct file_system_type *fs_type,
    302					unsigned int sb_flags)
    303{
    304	return alloc_fs_context(fs_type, NULL, sb_flags, 0,
    305					FS_CONTEXT_FOR_MOUNT);
    306}
    307EXPORT_SYMBOL(fs_context_for_mount);
    308
    309struct fs_context *fs_context_for_reconfigure(struct dentry *dentry,
    310					unsigned int sb_flags,
    311					unsigned int sb_flags_mask)
    312{
    313	return alloc_fs_context(dentry->d_sb->s_type, dentry, sb_flags,
    314				sb_flags_mask, FS_CONTEXT_FOR_RECONFIGURE);
    315}
    316EXPORT_SYMBOL(fs_context_for_reconfigure);
    317
    318struct fs_context *fs_context_for_submount(struct file_system_type *type,
    319					   struct dentry *reference)
    320{
    321	return alloc_fs_context(type, reference, 0, 0, FS_CONTEXT_FOR_SUBMOUNT);
    322}
    323EXPORT_SYMBOL(fs_context_for_submount);
    324
    325void fc_drop_locked(struct fs_context *fc)
    326{
    327	struct super_block *sb = fc->root->d_sb;
    328	dput(fc->root);
    329	fc->root = NULL;
    330	deactivate_locked_super(sb);
    331}
    332
    333static void legacy_fs_context_free(struct fs_context *fc);
    334
    335/**
    336 * vfs_dup_fc_config: Duplicate a filesystem context.
    337 * @src_fc: The context to copy.
    338 */
    339struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc)
    340{
    341	struct fs_context *fc;
    342	int ret;
    343
    344	if (!src_fc->ops->dup)
    345		return ERR_PTR(-EOPNOTSUPP);
    346
    347	fc = kmemdup(src_fc, sizeof(struct fs_context), GFP_KERNEL);
    348	if (!fc)
    349		return ERR_PTR(-ENOMEM);
    350
    351	mutex_init(&fc->uapi_mutex);
    352
    353	fc->fs_private	= NULL;
    354	fc->s_fs_info	= NULL;
    355	fc->source	= NULL;
    356	fc->security	= NULL;
    357	get_filesystem(fc->fs_type);
    358	get_net(fc->net_ns);
    359	get_user_ns(fc->user_ns);
    360	get_cred(fc->cred);
    361	if (fc->log.log)
    362		refcount_inc(&fc->log.log->usage);
    363
    364	/* Can't call put until we've called ->dup */
    365	ret = fc->ops->dup(fc, src_fc);
    366	if (ret < 0)
    367		goto err_fc;
    368
    369	ret = security_fs_context_dup(fc, src_fc);
    370	if (ret < 0)
    371		goto err_fc;
    372	return fc;
    373
    374err_fc:
    375	put_fs_context(fc);
    376	return ERR_PTR(ret);
    377}
    378EXPORT_SYMBOL(vfs_dup_fs_context);
    379
    380/**
    381 * logfc - Log a message to a filesystem context
    382 * @fc: The filesystem context to log to.
    383 * @fmt: The format of the buffer.
    384 */
    385void logfc(struct fc_log *log, const char *prefix, char level, const char *fmt, ...)
    386{
    387	va_list va;
    388	struct va_format vaf = {.fmt = fmt, .va = &va};
    389
    390	va_start(va, fmt);
    391	if (!log) {
    392		switch (level) {
    393		case 'w':
    394			printk(KERN_WARNING "%s%s%pV\n", prefix ? prefix : "",
    395						prefix ? ": " : "", &vaf);
    396			break;
    397		case 'e':
    398			printk(KERN_ERR "%s%s%pV\n", prefix ? prefix : "",
    399						prefix ? ": " : "", &vaf);
    400			break;
    401		default:
    402			printk(KERN_NOTICE "%s%s%pV\n", prefix ? prefix : "",
    403						prefix ? ": " : "", &vaf);
    404			break;
    405		}
    406	} else {
    407		unsigned int logsize = ARRAY_SIZE(log->buffer);
    408		u8 index;
    409		char *q = kasprintf(GFP_KERNEL, "%c %s%s%pV\n", level,
    410						prefix ? prefix : "",
    411						prefix ? ": " : "", &vaf);
    412
    413		index = log->head & (logsize - 1);
    414		BUILD_BUG_ON(sizeof(log->head) != sizeof(u8) ||
    415			     sizeof(log->tail) != sizeof(u8));
    416		if ((u8)(log->head - log->tail) == logsize) {
    417			/* The buffer is full, discard the oldest message */
    418			if (log->need_free & (1 << index))
    419				kfree(log->buffer[index]);
    420			log->tail++;
    421		}
    422
    423		log->buffer[index] = q ? q : "OOM: Can't store error string";
    424		if (q)
    425			log->need_free |= 1 << index;
    426		else
    427			log->need_free &= ~(1 << index);
    428		log->head++;
    429	}
    430	va_end(va);
    431}
    432EXPORT_SYMBOL(logfc);
    433
    434/*
    435 * Free a logging structure.
    436 */
    437static void put_fc_log(struct fs_context *fc)
    438{
    439	struct fc_log *log = fc->log.log;
    440	int i;
    441
    442	if (log) {
    443		if (refcount_dec_and_test(&log->usage)) {
    444			fc->log.log = NULL;
    445			for (i = 0; i <= 7; i++)
    446				if (log->need_free & (1 << i))
    447					kfree(log->buffer[i]);
    448			kfree(log);
    449		}
    450	}
    451}
    452
    453/**
    454 * put_fs_context - Dispose of a superblock configuration context.
    455 * @fc: The context to dispose of.
    456 */
    457void put_fs_context(struct fs_context *fc)
    458{
    459	struct super_block *sb;
    460
    461	if (fc->root) {
    462		sb = fc->root->d_sb;
    463		dput(fc->root);
    464		fc->root = NULL;
    465		deactivate_super(sb);
    466	}
    467
    468	if (fc->need_free && fc->ops && fc->ops->free)
    469		fc->ops->free(fc);
    470
    471	security_free_mnt_opts(&fc->security);
    472	put_net(fc->net_ns);
    473	put_user_ns(fc->user_ns);
    474	put_cred(fc->cred);
    475	put_fc_log(fc);
    476	put_filesystem(fc->fs_type);
    477	kfree(fc->source);
    478	kfree(fc);
    479}
    480EXPORT_SYMBOL(put_fs_context);
    481
    482/*
    483 * Free the config for a filesystem that doesn't support fs_context.
    484 */
    485static void legacy_fs_context_free(struct fs_context *fc)
    486{
    487	struct legacy_fs_context *ctx = fc->fs_private;
    488
    489	if (ctx) {
    490		if (ctx->param_type == LEGACY_FS_INDIVIDUAL_PARAMS)
    491			kfree(ctx->legacy_data);
    492		kfree(ctx);
    493	}
    494}
    495
    496/*
    497 * Duplicate a legacy config.
    498 */
    499static int legacy_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
    500{
    501	struct legacy_fs_context *ctx;
    502	struct legacy_fs_context *src_ctx = src_fc->fs_private;
    503
    504	ctx = kmemdup(src_ctx, sizeof(*src_ctx), GFP_KERNEL);
    505	if (!ctx)
    506		return -ENOMEM;
    507
    508	if (ctx->param_type == LEGACY_FS_INDIVIDUAL_PARAMS) {
    509		ctx->legacy_data = kmemdup(src_ctx->legacy_data,
    510					   src_ctx->data_size, GFP_KERNEL);
    511		if (!ctx->legacy_data) {
    512			kfree(ctx);
    513			return -ENOMEM;
    514		}
    515	}
    516
    517	fc->fs_private = ctx;
    518	return 0;
    519}
    520
    521/*
    522 * Add a parameter to a legacy config.  We build up a comma-separated list of
    523 * options.
    524 */
    525static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param)
    526{
    527	struct legacy_fs_context *ctx = fc->fs_private;
    528	unsigned int size = ctx->data_size;
    529	size_t len = 0;
    530	int ret;
    531
    532	ret = vfs_parse_fs_param_source(fc, param);
    533	if (ret != -ENOPARAM)
    534		return ret;
    535
    536	if (ctx->param_type == LEGACY_FS_MONOLITHIC_PARAMS)
    537		return invalf(fc, "VFS: Legacy: Can't mix monolithic and individual options");
    538
    539	switch (param->type) {
    540	case fs_value_is_string:
    541		len = 1 + param->size;
    542		fallthrough;
    543	case fs_value_is_flag:
    544		len += strlen(param->key);
    545		break;
    546	default:
    547		return invalf(fc, "VFS: Legacy: Parameter type for '%s' not supported",
    548			      param->key);
    549	}
    550
    551	if (size + len + 2 > PAGE_SIZE)
    552		return invalf(fc, "VFS: Legacy: Cumulative options too large");
    553	if (strchr(param->key, ',') ||
    554	    (param->type == fs_value_is_string &&
    555	     memchr(param->string, ',', param->size)))
    556		return invalf(fc, "VFS: Legacy: Option '%s' contained comma",
    557			      param->key);
    558	if (!ctx->legacy_data) {
    559		ctx->legacy_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
    560		if (!ctx->legacy_data)
    561			return -ENOMEM;
    562	}
    563
    564	ctx->legacy_data[size++] = ',';
    565	len = strlen(param->key);
    566	memcpy(ctx->legacy_data + size, param->key, len);
    567	size += len;
    568	if (param->type == fs_value_is_string) {
    569		ctx->legacy_data[size++] = '=';
    570		memcpy(ctx->legacy_data + size, param->string, param->size);
    571		size += param->size;
    572	}
    573	ctx->legacy_data[size] = '\0';
    574	ctx->data_size = size;
    575	ctx->param_type = LEGACY_FS_INDIVIDUAL_PARAMS;
    576	return 0;
    577}
    578
    579/*
    580 * Add monolithic mount data.
    581 */
    582static int legacy_parse_monolithic(struct fs_context *fc, void *data)
    583{
    584	struct legacy_fs_context *ctx = fc->fs_private;
    585
    586	if (ctx->param_type != LEGACY_FS_UNSET_PARAMS) {
    587		pr_warn("VFS: Can't mix monolithic and individual options\n");
    588		return -EINVAL;
    589	}
    590
    591	ctx->legacy_data = data;
    592	ctx->param_type = LEGACY_FS_MONOLITHIC_PARAMS;
    593	if (!ctx->legacy_data)
    594		return 0;
    595
    596	if (fc->fs_type->fs_flags & FS_BINARY_MOUNTDATA)
    597		return 0;
    598	return security_sb_eat_lsm_opts(ctx->legacy_data, &fc->security);
    599}
    600
    601/*
    602 * Get a mountable root with the legacy mount command.
    603 */
    604static int legacy_get_tree(struct fs_context *fc)
    605{
    606	struct legacy_fs_context *ctx = fc->fs_private;
    607	struct super_block *sb;
    608	struct dentry *root;
    609
    610	root = fc->fs_type->mount(fc->fs_type, fc->sb_flags,
    611				      fc->source, ctx->legacy_data);
    612	if (IS_ERR(root))
    613		return PTR_ERR(root);
    614
    615	sb = root->d_sb;
    616	BUG_ON(!sb);
    617
    618	fc->root = root;
    619	return 0;
    620}
    621
    622/*
    623 * Handle remount.
    624 */
    625static int legacy_reconfigure(struct fs_context *fc)
    626{
    627	struct legacy_fs_context *ctx = fc->fs_private;
    628	struct super_block *sb = fc->root->d_sb;
    629
    630	if (!sb->s_op->remount_fs)
    631		return 0;
    632
    633	return sb->s_op->remount_fs(sb, &fc->sb_flags,
    634				    ctx ? ctx->legacy_data : NULL);
    635}
    636
    637const struct fs_context_operations legacy_fs_context_ops = {
    638	.free			= legacy_fs_context_free,
    639	.dup			= legacy_fs_context_dup,
    640	.parse_param		= legacy_parse_param,
    641	.parse_monolithic	= legacy_parse_monolithic,
    642	.get_tree		= legacy_get_tree,
    643	.reconfigure		= legacy_reconfigure,
    644};
    645
    646/*
    647 * Initialise a legacy context for a filesystem that doesn't support
    648 * fs_context.
    649 */
    650static int legacy_init_fs_context(struct fs_context *fc)
    651{
    652	fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL_ACCOUNT);
    653	if (!fc->fs_private)
    654		return -ENOMEM;
    655	fc->ops = &legacy_fs_context_ops;
    656	return 0;
    657}
    658
    659int parse_monolithic_mount_data(struct fs_context *fc, void *data)
    660{
    661	int (*monolithic_mount_data)(struct fs_context *, void *);
    662
    663	monolithic_mount_data = fc->ops->parse_monolithic;
    664	if (!monolithic_mount_data)
    665		monolithic_mount_data = generic_parse_monolithic;
    666
    667	return monolithic_mount_data(fc, data);
    668}
    669
    670/*
    671 * Clean up a context after performing an action on it and put it into a state
    672 * from where it can be used to reconfigure a superblock.
    673 *
    674 * Note that here we do only the parts that can't fail; the rest is in
    675 * finish_clean_context() below and in between those fs_context is marked
    676 * FS_CONTEXT_AWAITING_RECONF.  The reason for splitup is that after
    677 * successful mount or remount we need to report success to userland.
    678 * Trying to do full reinit (for the sake of possible subsequent remount)
    679 * and failing to allocate memory would've put us into a nasty situation.
    680 * So here we only discard the old state and reinitialization is left
    681 * until we actually try to reconfigure.
    682 */
    683void vfs_clean_context(struct fs_context *fc)
    684{
    685	if (fc->need_free && fc->ops && fc->ops->free)
    686		fc->ops->free(fc);
    687	fc->need_free = false;
    688	fc->fs_private = NULL;
    689	fc->s_fs_info = NULL;
    690	fc->sb_flags = 0;
    691	security_free_mnt_opts(&fc->security);
    692	kfree(fc->source);
    693	fc->source = NULL;
    694
    695	fc->purpose = FS_CONTEXT_FOR_RECONFIGURE;
    696	fc->phase = FS_CONTEXT_AWAITING_RECONF;
    697}
    698
    699int finish_clean_context(struct fs_context *fc)
    700{
    701	int error;
    702
    703	if (fc->phase != FS_CONTEXT_AWAITING_RECONF)
    704		return 0;
    705
    706	if (fc->fs_type->init_fs_context)
    707		error = fc->fs_type->init_fs_context(fc);
    708	else
    709		error = legacy_init_fs_context(fc);
    710	if (unlikely(error)) {
    711		fc->phase = FS_CONTEXT_FAILED;
    712		return error;
    713	}
    714	fc->need_free = true;
    715	fc->phase = FS_CONTEXT_RECONF_PARAMS;
    716	return 0;
    717}