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