VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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