From 791a17ee19736fc6d4e35c4bf9f8efd1001be77c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 27 Apr 2020 23:17:09 +0200 Subject: docs: filesystems: convert mount_api.txt to ReST - Add a SPDX header; - Adjust document and section titles; - Some whitespace fixes and new line breaks; - Mark literal blocks as such; - Add table markups; - Add lists markups; - Add it to filesystems/index.rst. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/32332c1659a28c22561cb5e64162c959856066b4.1588021877.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- Documentation/filesystems/index.rst | 1 + Documentation/filesystems/mount_api.rst | 825 ++++++++++++++++++++++++++++++++ Documentation/filesystems/mount_api.txt | 724 ---------------------------- 3 files changed, 826 insertions(+), 724 deletions(-) create mode 100644 Documentation/filesystems/mount_api.rst delete mode 100644 Documentation/filesystems/mount_api.txt (limited to 'Documentation/filesystems') diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst index df1a474ad9b9..4532b4d2631f 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -30,6 +30,7 @@ algorithms work. files locks mandatory-locking + mount_api automount-support diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst new file mode 100644 index 000000000000..dea22d64f060 --- /dev/null +++ b/Documentation/filesystems/mount_api.rst @@ -0,0 +1,825 @@ +.. SPDX-License-Identifier: GPL-2.0 + +==================== +fILESYSTEM Mount API +==================== + +.. CONTENTS + + (1) Overview. + + (2) The filesystem context. + + (3) The filesystem context operations. + + (4) Filesystem context security. + + (5) VFS filesystem context API. + + (6) Superblock creation helpers. + + (7) Parameter description. + + (8) Parameter helper functions. + + +Overview +======== + +The creation of new mounts is now to be done in a multistep process: + + (1) Create a filesystem context. + + (2) Parse the parameters and attach them to the context. Parameters are + expected to be passed individually from userspace, though legacy binary + parameters can also be handled. + + (3) Validate and pre-process the context. + + (4) Get or create a superblock and mountable root. + + (5) Perform the mount. + + (6) Return an error message attached to the context. + + (7) Destroy the context. + +To support this, the file_system_type struct gains two new fields:: + + int (*init_fs_context)(struct fs_context *fc); + const struct fs_parameter_description *parameters; + +The first is invoked to set up the filesystem-specific parts of a filesystem +context, including the additional space, and the second points to the +parameter description for validation at registration time and querying by a +future system call. + +Note that security initialisation is done *after* the filesystem is called so +that the namespaces may be adjusted first. + + +The Filesystem context +====================== + +The creation and reconfiguration of a superblock is governed by a filesystem +context. This is represented by the fs_context structure:: + + struct fs_context { + const struct fs_context_operations *ops; + struct file_system_type *fs_type; + void *fs_private; + struct dentry *root; + struct user_namespace *user_ns; + struct net *net_ns; + const struct cred *cred; + char *source; + char *subtype; + void *security; + void *s_fs_info; + unsigned int sb_flags; + unsigned int sb_flags_mask; + unsigned int s_iflags; + unsigned int lsm_flags; + enum fs_context_purpose purpose:8; + ... + }; + +The fs_context fields are as follows: + + * :: + + const struct fs_context_operations *ops + + These are operations that can be done on a filesystem context (see + below). This must be set by the ->init_fs_context() file_system_type + operation. + + * :: + + struct file_system_type *fs_type + + A pointer to the file_system_type of the filesystem that is being + constructed or reconfigured. This retains a reference on the type owner. + + * :: + + void *fs_private + + A pointer to the file system's private data. This is where the filesystem + will need to store any options it parses. + + * :: + + struct dentry *root + + A pointer to the root of the mountable tree (and indirectly, the + superblock thereof). This is filled in by the ->get_tree() op. If this + is set, an active reference on root->d_sb must also be held. + + * :: + + struct user_namespace *user_ns + struct net *net_ns + + There are a subset of the namespaces in use by the invoking process. They + retain references on each namespace. The subscribed namespaces may be + replaced by the filesystem to reflect other sources, such as the parent + mount superblock on an automount. + + * :: + + const struct cred *cred + + The mounter's credentials. This retains a reference on the credentials. + + * :: + + char *source + + This specifies the source. It may be a block device (e.g. /dev/sda1) or + something more exotic, such as the "host:/path" that NFS desires. + + * :: + + char *subtype + + This is a string to be added to the type displayed in /proc/mounts to + qualify it (used by FUSE). This is available for the filesystem to set if + desired. + + * :: + + void *security + + A place for the LSMs to hang their security data for the superblock. The + relevant security operations are described below. + + * :: + + void *s_fs_info + + The proposed s_fs_info for a new superblock, set in the superblock by + sget_fc(). This can be used to distinguish superblocks. + + * :: + + unsigned int sb_flags + unsigned int sb_flags_mask + + Which bits SB_* flags are to be set/cleared in super_block::s_flags. + + * :: + + unsigned int s_iflags + + These will be bitwise-OR'd with s->s_iflags when a superblock is created. + + * :: + + enum fs_context_purpose + + This indicates the purpose for which the context is intended. The + available values are: + + ========================== ====================================== + FS_CONTEXT_FOR_MOUNT, New superblock for explicit mount + FS_CONTEXT_FOR_SUBMOUNT New automatic submount of extant mount + FS_CONTEXT_FOR_RECONFIGURE Change an existing mount + ========================== ====================================== + +The mount context is created by calling vfs_new_fs_context() or +vfs_dup_fs_context() and is destroyed with put_fs_context(). Note that the +structure is not refcounted. + +VFS, security and filesystem mount options are set individually with +vfs_parse_mount_option(). Options provided by the old mount(2) system call as +a page of data can be parsed with generic_parse_monolithic(). + +When mounting, the filesystem is allowed to take data from any of the pointers +and attach it to the superblock (or whatever), provided it clears the pointer +in the mount context. + +The filesystem is also allowed to allocate resources and pin them with the +mount context. For instance, NFS might pin the appropriate protocol version +module. + + +The Filesystem Context Operations +================================= + +The filesystem context points to a table of operations:: + + struct fs_context_operations { + void (*free)(struct fs_context *fc); + int (*dup)(struct fs_context *fc, struct fs_context *src_fc); + int (*parse_param)(struct fs_context *fc, + struct struct fs_parameter *param); + int (*parse_monolithic)(struct fs_context *fc, void *data); + int (*get_tree)(struct fs_context *fc); + int (*reconfigure)(struct fs_context *fc); + }; + +These operations are invoked by the various stages of the mount procedure to +manage the filesystem context. They are as follows: + + * :: + + void (*free)(struct fs_context *fc); + + Called to clean up the filesystem-specific part of the filesystem context + when the context is destroyed. It should be aware that parts of the + context may have been removed and NULL'd out by ->get_tree(). + + * :: + + int (*dup)(struct fs_context *fc, struct fs_context *src_fc); + + Called when a filesystem context has been duplicated to duplicate the + filesystem-private data. An error may be returned to indicate failure to + do this. + + .. Warning:: + + Note that even if this fails, put_fs_context() will be called + immediately thereafter, so ->dup() *must* make the + filesystem-private data safe for ->free(). + + * :: + + int (*parse_param)(struct fs_context *fc, + struct struct fs_parameter *param); + + Called when a parameter is being added to the filesystem context. param + points to the key name and maybe a value object. VFS-specific options + will have been weeded out and fc->sb_flags updated in the context. + Security options will also have been weeded out and fc->security updated. + + The parameter can be parsed with fs_parse() and fs_lookup_param(). Note + that the source(s) are presented as parameters named "source". + + If successful, 0 should be returned or a negative error code otherwise. + + * :: + + int (*parse_monolithic)(struct fs_context *fc, void *data); + + Called when the mount(2) system call is invoked to pass the entire data + page in one go. If this is expected to be just a list of "key[=val]" + items separated by commas, then this may be set to NULL. + + The return value is as for ->parse_param(). + + If the filesystem (e.g. NFS) needs to examine the data first and then + finds it's the standard key-val list then it may pass it off to + generic_parse_monolithic(). + + * :: + + int (*get_tree)(struct fs_context *fc); + + Called to get or create the mountable root and superblock, using the + information stored in the filesystem context (reconfiguration goes via a + different vector). It may detach any resources it desires from the + filesystem context and transfer them to the superblock it creates. + + On success it should set fc->root to the mountable root and return 0. In + the case of an error, it should return a negative error code. + + The phase on a userspace-driven context will be set to only allow this to + be called once on any particular context. + + * :: + + int (*reconfigure)(struct fs_context *fc); + + Called to effect reconfiguration of a superblock using information stored + in the filesystem context. It may detach any resources it desires from + the filesystem context and transfer them to the superblock. The + superblock can be found from fc->root->d_sb. + + On success it should return 0. In the case of an error, it should return + a negative error code. + + .. Note:: reconfigure is intended as a replacement for remount_fs. + + +Filesystem context Security +=========================== + +The filesystem context contains a security pointer that the LSMs can use for +building up a security context for the superblock to be mounted. There are a +number of operations used by the new mount code for this purpose: + + * :: + + int security_fs_context_alloc(struct fs_context *fc, + struct dentry *reference); + + Called to initialise fc->security (which is preset to NULL) and allocate + any resources needed. It should return 0 on success or a negative error + code on failure. + + reference will be non-NULL if the context is being created for superblock + reconfiguration (FS_CONTEXT_FOR_RECONFIGURE) in which case it indicates + the root dentry of the superblock to be reconfigured. It will also be + non-NULL in the case of a submount (FS_CONTEXT_FOR_SUBMOUNT) in which case + it indicates the automount point. + + * :: + + int security_fs_context_dup(struct fs_context *fc, + struct fs_context *src_fc); + + Called to initialise fc->security (which is preset to NULL) and allocate + any resources needed. The original filesystem context is pointed to by + src_fc and may be used for reference. It should return 0 on success or a + negative error code on failure. + + * :: + + void security_fs_context_free(struct fs_context *fc); + + Called to clean up anything attached to fc->security. Note that the + contents may have been transferred to a superblock and the pointer cleared + during get_tree. + + * :: + + int security_fs_context_parse_param(struct fs_context *fc, + struct fs_parameter *param); + + Called for each mount parameter, including the source. The arguments are + as for the ->parse_param() method. It should return 0 to indicate that + the parameter should be passed on to the filesystem, 1 to indicate that + the parameter should be discarded or an error to indicate that the + parameter should be rejected. + + The value pointed to by param may be modified (if a string) or stolen + (provided the value pointer is NULL'd out). If it is stolen, 1 must be + returned to prevent it being passed to the filesystem. + + * :: + + int security_fs_context_validate(struct fs_context *fc); + + Called after all the options have been parsed to validate the collection + as a whole and to do any necessary allocation so that + security_sb_get_tree() and security_sb_reconfigure() are less likely to + fail. It should return 0 or a negative error code. + + In the case of reconfiguration, the target superblock will be accessible + via fc->root. + + * :: + + int security_sb_get_tree(struct fs_context *fc); + + Called during the mount procedure to verify that the specified superblock + is allowed to be mounted and to transfer the security data there. It + should return 0 or a negative error code. + + * :: + + void security_sb_reconfigure(struct fs_context *fc); + + Called to apply any reconfiguration to an LSM's context. It must not + fail. Error checking and resource allocation must be done in advance by + the parameter parsing and validation hooks. + + * :: + + int security_sb_mountpoint(struct fs_context *fc, + struct path *mountpoint, + unsigned int mnt_flags); + + Called during the mount procedure to verify that the root dentry attached + to the context is permitted to be attached to the specified mountpoint. + It should return 0 on success or a negative error code on failure. + + +VFS Filesystem context API +========================== + +There are four operations for creating a filesystem context and one for +destroying a context: + + * :: + + struct fs_context *fs_context_for_mount(struct file_system_type *fs_type, + unsigned int sb_flags); + + Allocate a filesystem context for the purpose of setting up a new mount, + whether that be with a new superblock or sharing an existing one. This + sets the superblock flags, initialises the security and calls + fs_type->init_fs_context() to initialise the filesystem private data. + + fs_type specifies the filesystem type that will manage the context and + sb_flags presets the superblock flags stored therein. + + * :: + + struct fs_context *fs_context_for_reconfigure( + struct dentry *dentry, + unsigned int sb_flags, + unsigned int sb_flags_mask); + + Allocate a filesystem context for the purpose of reconfiguring an + existing superblock. dentry provides a reference to the superblock to be + configured. sb_flags and sb_flags_mask indicate which superblock flags + need changing and to what. + + * :: + + struct fs_context *fs_context_for_submount( + struct file_system_type *fs_type, + struct dentry *reference); + + Allocate a filesystem context for the purpose of creating a new mount for + an automount point or other derived superblock. fs_type specifies the + filesystem type that will manage the context and the reference dentry + supplies the parameters. Namespaces are propagated from the reference + dentry's superblock also. + + Note that it's not a requirement that the reference dentry be of the same + filesystem type as fs_type. + + * :: + + struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc); + + Duplicate a filesystem context, copying any options noted and duplicating + or additionally referencing any resources held therein. This is available + for use where a filesystem has to get a mount within a mount, such as NFS4 + does by internally mounting the root of the target server and then doing a + private pathwalk to the target directory. + + The purpose in the new context is inherited from the old one. + + * :: + + void put_fs_context(struct fs_context *fc); + + Destroy a filesystem context, releasing any resources it holds. This + calls the ->free() operation. This is intended to be called by anyone who + created a filesystem context. + + .. Warning:: + + filesystem contexts are not refcounted, so this causes unconditional + destruction. + +In all the above operations, apart from the put op, the return is a mount +context pointer or a negative error code. + +For the remaining operations, if an error occurs, a negative error code will be +returned. + + * :: + + int vfs_parse_fs_param(struct fs_context *fc, + struct fs_parameter *param); + + Supply a single mount parameter to the filesystem context. This include + the specification of the source/device which is specified as the "source" + parameter (which may be specified multiple times if the filesystem + supports that). + + param specifies the parameter key name and the value. The parameter is + first checked to see if it corresponds to a standard mount flag (in which + case it is used to set an SB_xxx flag and consumed) or a security option + (in which case the LSM consumes it) before it is passed on to the + filesystem. + + The parameter value is typed and can be one of: + + ==================== ============================= + fs_value_is_flag Parameter not given a value + fs_value_is_string Value is a string + fs_value_is_blob Value is a binary blob + fs_value_is_filename Value is a filename* + dirfd + fs_value_is_file Value is an open file (file*) + ==================== ============================= + + If there is a value, that value is stored in a union in the struct in one + of param->{string,blob,name,file}. Note that the function may steal and + clear the pointer, but then becomes responsible for disposing of the + object. + + * :: + + int vfs_parse_fs_string(struct fs_context *fc, const char *key, + const char *value, size_t v_size); + + A wrapper around vfs_parse_fs_param() that copies the value string it is + passed. + + * :: + + int generic_parse_monolithic(struct fs_context *fc, void *data); + + Parse a sys_mount() data page, assuming the form to be a text list + consisting of key[=val] options separated by commas. Each item in the + list is passed to vfs_mount_option(). This is the default when the + ->parse_monolithic() method is NULL. + + * :: + + int vfs_get_tree(struct fs_context *fc); + + Get or create the mountable root and superblock, using the parameters in + the filesystem context to select/configure the superblock. This invokes + the ->get_tree() method. + + * :: + + struct vfsmount *vfs_create_mount(struct fs_context *fc); + + Create a mount given the parameters in the specified filesystem context. + Note that this does not attach the mount to anything. + + +Superblock Creation Helpers +=========================== + +A number of VFS helpers are available for use by filesystems for the creation +or looking up of superblocks. + + * :: + + struct super_block * + sget_fc(struct fs_context *fc, + int (*test)(struct super_block *sb, struct fs_context *fc), + int (*set)(struct super_block *sb, struct fs_context *fc)); + + This is the core routine. If test is non-NULL, it searches for an + existing superblock matching the criteria held in the fs_context, using + the test function to match them. If no match is found, a new superblock + is created and the set function is called to set it up. + + Prior to the set function being called, fc->s_fs_info will be transferred + to sb->s_fs_info - and fc->s_fs_info will be cleared if set returns + success (ie. 0). + +The following helpers all wrap sget_fc(): + + * :: + + int vfs_get_super(struct fs_context *fc, + enum vfs_get_super_keying keying, + int (*fill_super)(struct super_block *sb, + struct fs_context *fc)) + + This creates/looks up a deviceless superblock. The keying indicates how + many superblocks of this type may exist and in what manner they may be + shared: + + (1) vfs_get_single_super + + Only one such superblock may exist in the system. Any further + attempt to get a new superblock gets this one (and any parameter + differences are ignored). + + (2) vfs_get_keyed_super + + Multiple superblocks of this type may exist and they're keyed on + their s_fs_info pointer (for example this may refer to a + namespace). + + (3) vfs_get_independent_super + + Multiple independent superblocks of this type may exist. This + function never matches an existing one and always creates a new + one. + + +===================== +PARAMETER DESCRIPTION +===================== + +Parameters are described using structures defined in linux/fs_parser.h. +There's a core description struct that links everything together:: + + struct fs_parameter_description { + const struct fs_parameter_spec *specs; + const struct fs_parameter_enum *enums; + }; + +For example:: + + enum { + Opt_autocell, + Opt_bar, + Opt_dyn, + Opt_foo, + Opt_source, + }; + + static const struct fs_parameter_description afs_fs_parameters = { + .specs = afs_param_specs, + .enums = afs_param_enums, + }; + +The members are as follows: + + (1) :: + + const struct fs_parameter_specification *specs; + + Table of parameter specifications, terminated with a null entry, where the + entries are of type:: + + struct fs_parameter_spec { + const char *name; + u8 opt; + enum fs_parameter_type type:8; + unsigned short flags; + }; + + The 'name' field is a string to match exactly to the parameter key (no + wildcards, patterns and no case-independence) and 'opt' is the value that + will be returned by the fs_parser() function in the case of a successful + match. + + The 'type' field indicates the desired value type and must be one of: + + ======================= ======================= ===================== + TYPE NAME EXPECTED VALUE RESULT IN + ======================= ======================= ===================== + fs_param_is_flag No value n/a + fs_param_is_bool Boolean value result->boolean + fs_param_is_u32 32-bit unsigned int result->uint_32 + fs_param_is_u32_octal 32-bit octal int result->uint_32 + fs_param_is_u32_hex 32-bit hex int result->uint_32 + fs_param_is_s32 32-bit signed int result->int_32 + fs_param_is_u64 64-bit unsigned int result->uint_64 + fs_param_is_enum Enum value name result->uint_32 + fs_param_is_string Arbitrary string param->string + fs_param_is_blob Binary blob param->blob + fs_param_is_blockdev Blockdev path * Needs lookup + fs_param_is_path Path * Needs lookup + fs_param_is_fd File descriptor result->int_32 + ======================= ======================= ===================== + + Note that if the value is of fs_param_is_bool type, fs_parse() will try + to match any string value against "0", "1", "no", "yes", "false", "true". + + Each parameter can also be qualified with 'flags': + + ======================= ================================================ + fs_param_v_optional The value is optional + fs_param_neg_with_no result->negated set if key is prefixed with "no" + fs_param_neg_with_empty result->negated set if value is "" + fs_param_deprecated The parameter is deprecated. + ======================= ================================================ + + These are wrapped with a number of convenience wrappers: + + ======================= =============================================== + MACRO SPECIFIES + ======================= =============================================== + fsparam_flag() fs_param_is_flag + fsparam_flag_no() fs_param_is_flag, fs_param_neg_with_no + fsparam_bool() fs_param_is_bool + fsparam_u32() fs_param_is_u32 + fsparam_u32oct() fs_param_is_u32_octal + fsparam_u32hex() fs_param_is_u32_hex + fsparam_s32() fs_param_is_s32 + fsparam_u64() fs_param_is_u64 + fsparam_enum() fs_param_is_enum + fsparam_string() fs_param_is_string + fsparam_blob() fs_param_is_blob + fsparam_bdev() fs_param_is_blockdev + fsparam_path() fs_param_is_path + fsparam_fd() fs_param_is_fd + ======================= =============================================== + + all of which take two arguments, name string and option number - for + example:: + + static const struct fs_parameter_spec afs_param_specs[] = { + fsparam_flag ("autocell", Opt_autocell), + fsparam_flag ("dyn", Opt_dyn), + fsparam_string ("source", Opt_source), + fsparam_flag_no ("foo", Opt_foo), + {} + }; + + An addition macro, __fsparam() is provided that takes an additional pair + of arguments to specify the type and the flags for anything that doesn't + match one of the above macros. + + (2) :: + + const struct fs_parameter_enum *enums; + + Table of enum value names to integer mappings, terminated with a null + entry. This is of type:: + + struct fs_parameter_enum { + u8 opt; + char name[14]; + u8 value; + }; + + Where the array is an unsorted list of { parameter ID, name }-keyed + elements that indicate the value to map to, e.g.:: + + static const struct fs_parameter_enum afs_param_enums[] = { + { Opt_bar, "x", 1}, + { Opt_bar, "y", 23}, + { Opt_bar, "z", 42}, + }; + + If a parameter of type fs_param_is_enum is encountered, fs_parse() will + try to look the value up in the enum table and the result will be stored + in the parse result. + +The parser should be pointed to by the parser pointer in the file_system_type +struct as this will provide validation on registration (if +CONFIG_VALIDATE_FS_PARSER=y) and will allow the description to be queried from +userspace using the fsinfo() syscall. + + +Parameter Helper Functions +========================== + +A number of helper functions are provided to help a filesystem or an LSM +process the parameters it is given. + + * :: + + int lookup_constant(const struct constant_table tbl[], + const char *name, int not_found); + + Look up a constant by name in a table of name -> integer mappings. The + table is an array of elements of the following type:: + + struct constant_table { + const char *name; + int value; + }; + + If a match is found, the corresponding value is returned. If a match + isn't found, the not_found value is returned instead. + + * :: + + bool validate_constant_table(const struct constant_table *tbl, + size_t tbl_size, + int low, int high, int special); + + Validate a constant table. Checks that all the elements are appropriately + ordered, that there are no duplicates and that the values are between low + and high inclusive, though provision is made for one allowable special + value outside of that range. If no special value is required, special + should just be set to lie inside the low-to-high range. + + If all is good, true is returned. If the table is invalid, errors are + logged to dmesg and false is returned. + + * :: + + bool fs_validate_description(const struct fs_parameter_description *desc); + + This performs some validation checks on a parameter description. It + returns true if the description is good and false if it is not. It will + log errors to dmesg if validation fails. + + * :: + + int fs_parse(struct fs_context *fc, + const struct fs_parameter_description *desc, + struct fs_parameter *param, + struct fs_parse_result *result); + + This is the main interpreter of parameters. It uses the parameter + description to look up a parameter by key name and to convert that to an + option number (which it returns). + + If successful, and if the parameter type indicates the result is a + boolean, integer or enum type, the value is converted by this function and + the result stored in result->{boolean,int_32,uint_32,uint_64}. + + If a match isn't initially made, the key is prefixed with "no" and no + value is present then an attempt will be made to look up the key with the + prefix removed. If this matches a parameter for which the type has flag + fs_param_neg_with_no set, then a match will be made and result->negated + will be set to true. + + If the parameter isn't matched, -ENOPARAM will be returned; if the + parameter is matched, but the value is erroneous, -EINVAL will be + returned; otherwise the parameter's option number will be returned. + + * :: + + int fs_lookup_param(struct fs_context *fc, + struct fs_parameter *value, + bool want_bdev, + struct path *_path); + + This takes a parameter that carries a string or filename type and attempts + to do a path lookup on it. If the parameter expects a blockdev, a check + is made that the inode actually represents one. + + Returns 0 if successful and ``*_path`` will be set; returns a negative + error code if not. diff --git a/Documentation/filesystems/mount_api.txt b/Documentation/filesystems/mount_api.txt deleted file mode 100644 index 87c14bbb2b35..000000000000 --- a/Documentation/filesystems/mount_api.txt +++ /dev/null @@ -1,724 +0,0 @@ - ==================== - FILESYSTEM MOUNT API - ==================== - -CONTENTS - - (1) Overview. - - (2) The filesystem context. - - (3) The filesystem context operations. - - (4) Filesystem context security. - - (5) VFS filesystem context API. - - (6) Superblock creation helpers. - - (7) Parameter description. - - (8) Parameter helper functions. - - -======== -OVERVIEW -======== - -The creation of new mounts is now to be done in a multistep process: - - (1) Create a filesystem context. - - (2) Parse the parameters and attach them to the context. Parameters are - expected to be passed individually from userspace, though legacy binary - parameters can also be handled. - - (3) Validate and pre-process the context. - - (4) Get or create a superblock and mountable root. - - (5) Perform the mount. - - (6) Return an error message attached to the context. - - (7) Destroy the context. - -To support this, the file_system_type struct gains two new fields: - - int (*init_fs_context)(struct fs_context *fc); - const struct fs_parameter_description *parameters; - -The first is invoked to set up the filesystem-specific parts of a filesystem -context, including the additional space, and the second points to the -parameter description for validation at registration time and querying by a -future system call. - -Note that security initialisation is done *after* the filesystem is called so -that the namespaces may be adjusted first. - - -====================== -THE FILESYSTEM CONTEXT -====================== - -The creation and reconfiguration of a superblock is governed by a filesystem -context. This is represented by the fs_context structure: - - struct fs_context { - const struct fs_context_operations *ops; - struct file_system_type *fs_type; - void *fs_private; - struct dentry *root; - struct user_namespace *user_ns; - struct net *net_ns; - const struct cred *cred; - char *source; - char *subtype; - void *security; - void *s_fs_info; - unsigned int sb_flags; - unsigned int sb_flags_mask; - unsigned int s_iflags; - unsigned int lsm_flags; - enum fs_context_purpose purpose:8; - ... - }; - -The fs_context fields are as follows: - - (*) const struct fs_context_operations *ops - - These are operations that can be done on a filesystem context (see - below). This must be set by the ->init_fs_context() file_system_type - operation. - - (*) struct file_system_type *fs_type - - A pointer to the file_system_type of the filesystem that is being - constructed or reconfigured. This retains a reference on the type owner. - - (*) void *fs_private - - A pointer to the file system's private data. This is where the filesystem - will need to store any options it parses. - - (*) struct dentry *root - - A pointer to the root of the mountable tree (and indirectly, the - superblock thereof). This is filled in by the ->get_tree() op. If this - is set, an active reference on root->d_sb must also be held. - - (*) struct user_namespace *user_ns - (*) struct net *net_ns - - There are a subset of the namespaces in use by the invoking process. They - retain references on each namespace. The subscribed namespaces may be - replaced by the filesystem to reflect other sources, such as the parent - mount superblock on an automount. - - (*) const struct cred *cred - - The mounter's credentials. This retains a reference on the credentials. - - (*) char *source - - This specifies the source. It may be a block device (e.g. /dev/sda1) or - something more exotic, such as the "host:/path" that NFS desires. - - (*) char *subtype - - This is a string to be added to the type displayed in /proc/mounts to - qualify it (used by FUSE). This is available for the filesystem to set if - desired. - - (*) void *security - - A place for the LSMs to hang their security data for the superblock. The - relevant security operations are described below. - - (*) void *s_fs_info - - The proposed s_fs_info for a new superblock, set in the superblock by - sget_fc(). This can be used to distinguish superblocks. - - (*) unsigned int sb_flags - (*) unsigned int sb_flags_mask - - Which bits SB_* flags are to be set/cleared in super_block::s_flags. - - (*) unsigned int s_iflags - - These will be bitwise-OR'd with s->s_iflags when a superblock is created. - - (*) enum fs_context_purpose - - This indicates the purpose for which the context is intended. The - available values are: - - FS_CONTEXT_FOR_MOUNT, -- New superblock for explicit mount - FS_CONTEXT_FOR_SUBMOUNT -- New automatic submount of extant mount - FS_CONTEXT_FOR_RECONFIGURE -- Change an existing mount - -The mount context is created by calling vfs_new_fs_context() or -vfs_dup_fs_context() and is destroyed with put_fs_context(). Note that the -structure is not refcounted. - -VFS, security and filesystem mount options are set individually with -vfs_parse_mount_option(). Options provided by the old mount(2) system call as -a page of data can be parsed with generic_parse_monolithic(). - -When mounting, the filesystem is allowed to take data from any of the pointers -and attach it to the superblock (or whatever), provided it clears the pointer -in the mount context. - -The filesystem is also allowed to allocate resources and pin them with the -mount context. For instance, NFS might pin the appropriate protocol version -module. - - -================================= -THE FILESYSTEM CONTEXT OPERATIONS -================================= - -The filesystem context points to a table of operations: - - struct fs_context_operations { - void (*free)(struct fs_context *fc); - int (*dup)(struct fs_context *fc, struct fs_context *src_fc); - int (*parse_param)(struct fs_context *fc, - struct struct fs_parameter *param); - int (*parse_monolithic)(struct fs_context *fc, void *data); - int (*get_tree)(struct fs_context *fc); - int (*reconfigure)(struct fs_context *fc); - }; - -These operations are invoked by the various stages of the mount procedure to -manage the filesystem context. They are as follows: - - (*) void (*free)(struct fs_context *fc); - - Called to clean up the filesystem-specific part of the filesystem context - when the context is destroyed. It should be aware that parts of the - context may have been removed and NULL'd out by ->get_tree(). - - (*) int (*dup)(struct fs_context *fc, struct fs_context *src_fc); - - Called when a filesystem context has been duplicated to duplicate the - filesystem-private data. An error may be returned to indicate failure to - do this. - - [!] Note that even if this fails, put_fs_context() will be called - immediately thereafter, so ->dup() *must* make the - filesystem-private data safe for ->free(). - - (*) int (*parse_param)(struct fs_context *fc, - struct struct fs_parameter *param); - - Called when a parameter is being added to the filesystem context. param - points to the key name and maybe a value object. VFS-specific options - will have been weeded out and fc->sb_flags updated in the context. - Security options will also have been weeded out and fc->security updated. - - The parameter can be parsed with fs_parse() and fs_lookup_param(). Note - that the source(s) are presented as parameters named "source". - - If successful, 0 should be returned or a negative error code otherwise. - - (*) int (*parse_monolithic)(struct fs_context *fc, void *data); - - Called when the mount(2) system call is invoked to pass the entire data - page in one go. If this is expected to be just a list of "key[=val]" - items separated by commas, then this may be set to NULL. - - The return value is as for ->parse_param(). - - If the filesystem (e.g. NFS) needs to examine the data first and then - finds it's the standard key-val list then it may pass it off to - generic_parse_monolithic(). - - (*) int (*get_tree)(struct fs_context *fc); - - Called to get or create the mountable root and superblock, using the - information stored in the filesystem context (reconfiguration goes via a - different vector). It may detach any resources it desires from the - filesystem context and transfer them to the superblock it creates. - - On success it should set fc->root to the mountable root and return 0. In - the case of an error, it should return a negative error code. - - The phase on a userspace-driven context will be set to only allow this to - be called once on any particular context. - - (*) int (*reconfigure)(struct fs_context *fc); - - Called to effect reconfiguration of a superblock using information stored - in the filesystem context. It may detach any resources it desires from - the filesystem context and transfer them to the superblock. The - superblock can be found from fc->root->d_sb. - - On success it should return 0. In the case of an error, it should return - a negative error code. - - [NOTE] reconfigure is intended as a replacement for remount_fs. - - -=========================== -FILESYSTEM CONTEXT SECURITY -=========================== - -The filesystem context contains a security pointer that the LSMs can use for -building up a security context for the superblock to be mounted. There are a -number of operations used by the new mount code for this purpose: - - (*) int security_fs_context_alloc(struct fs_context *fc, - struct dentry *reference); - - Called to initialise fc->security (which is preset to NULL) and allocate - any resources needed. It should return 0 on success or a negative error - code on failure. - - reference will be non-NULL if the context is being created for superblock - reconfiguration (FS_CONTEXT_FOR_RECONFIGURE) in which case it indicates - the root dentry of the superblock to be reconfigured. It will also be - non-NULL in the case of a submount (FS_CONTEXT_FOR_SUBMOUNT) in which case - it indicates the automount point. - - (*) int security_fs_context_dup(struct fs_context *fc, - struct fs_context *src_fc); - - Called to initialise fc->security (which is preset to NULL) and allocate - any resources needed. The original filesystem context is pointed to by - src_fc and may be used for reference. It should return 0 on success or a - negative error code on failure. - - (*) void security_fs_context_free(struct fs_context *fc); - - Called to clean up anything attached to fc->security. Note that the - contents may have been transferred to a superblock and the pointer cleared - during get_tree. - - (*) int security_fs_context_parse_param(struct fs_context *fc, - struct fs_parameter *param); - - Called for each mount parameter, including the source. The arguments are - as for the ->parse_param() method. It should return 0 to indicate that - the parameter should be passed on to the filesystem, 1 to indicate that - the parameter should be discarded or an error to indicate that the - parameter should be rejected. - - The value pointed to by param may be modified (if a string) or stolen - (provided the value pointer is NULL'd out). If it is stolen, 1 must be - returned to prevent it being passed to the filesystem. - - (*) int security_fs_context_validate(struct fs_context *fc); - - Called after all the options have been parsed to validate the collection - as a whole and to do any necessary allocation so that - security_sb_get_tree() and security_sb_reconfigure() are less likely to - fail. It should return 0 or a negative error code. - - In the case of reconfiguration, the target superblock will be accessible - via fc->root. - - (*) int security_sb_get_tree(struct fs_context *fc); - - Called during the mount procedure to verify that the specified superblock - is allowed to be mounted and to transfer the security data there. It - should return 0 or a negative error code. - - (*) void security_sb_reconfigure(struct fs_context *fc); - - Called to apply any reconfiguration to an LSM's context. It must not - fail. Error checking and resource allocation must be done in advance by - the parameter parsing and validation hooks. - - (*) int security_sb_mountpoint(struct fs_context *fc, struct path *mountpoint, - unsigned int mnt_flags); - - Called during the mount procedure to verify that the root dentry attached - to the context is permitted to be attached to the specified mountpoint. - It should return 0 on success or a negative error code on failure. - - -========================== -VFS FILESYSTEM CONTEXT API -========================== - -There are four operations for creating a filesystem context and one for -destroying a context: - - (*) struct fs_context *fs_context_for_mount( - struct file_system_type *fs_type, - unsigned int sb_flags); - - Allocate a filesystem context for the purpose of setting up a new mount, - whether that be with a new superblock or sharing an existing one. This - sets the superblock flags, initialises the security and calls - fs_type->init_fs_context() to initialise the filesystem private data. - - fs_type specifies the filesystem type that will manage the context and - sb_flags presets the superblock flags stored therein. - - (*) struct fs_context *fs_context_for_reconfigure( - struct dentry *dentry, - unsigned int sb_flags, - unsigned int sb_flags_mask); - - Allocate a filesystem context for the purpose of reconfiguring an - existing superblock. dentry provides a reference to the superblock to be - configured. sb_flags and sb_flags_mask indicate which superblock flags - need changing and to what. - - (*) struct fs_context *fs_context_for_submount( - struct file_system_type *fs_type, - struct dentry *reference); - - Allocate a filesystem context for the purpose of creating a new mount for - an automount point or other derived superblock. fs_type specifies the - filesystem type that will manage the context and the reference dentry - supplies the parameters. Namespaces are propagated from the reference - dentry's superblock also. - - Note that it's not a requirement that the reference dentry be of the same - filesystem type as fs_type. - - (*) struct fs_context *vfs_dup_fs_context(struct fs_context *src_fc); - - Duplicate a filesystem context, copying any options noted and duplicating - or additionally referencing any resources held therein. This is available - for use where a filesystem has to get a mount within a mount, such as NFS4 - does by internally mounting the root of the target server and then doing a - private pathwalk to the target directory. - - The purpose in the new context is inherited from the old one. - - (*) void put_fs_context(struct fs_context *fc); - - Destroy a filesystem context, releasing any resources it holds. This - calls the ->free() operation. This is intended to be called by anyone who - created a filesystem context. - - [!] filesystem contexts are not refcounted, so this causes unconditional - destruction. - -In all the above operations, apart from the put op, the return is a mount -context pointer or a negative error code. - -For the remaining operations, if an error occurs, a negative error code will be -returned. - - (*) int vfs_parse_fs_param(struct fs_context *fc, - struct fs_parameter *param); - - Supply a single mount parameter to the filesystem context. This include - the specification of the source/device which is specified as the "source" - parameter (which may be specified multiple times if the filesystem - supports that). - - param specifies the parameter key name and the value. The parameter is - first checked to see if it corresponds to a standard mount flag (in which - case it is used to set an SB_xxx flag and consumed) or a security option - (in which case the LSM consumes it) before it is passed on to the - filesystem. - - The parameter value is typed and can be one of: - - fs_value_is_flag, Parameter not given a value. - fs_value_is_string, Value is a string - fs_value_is_blob, Value is a binary blob - fs_value_is_filename, Value is a filename* + dirfd - fs_value_is_file, Value is an open file (file*) - - If there is a value, that value is stored in a union in the struct in one - of param->{string,blob,name,file}. Note that the function may steal and - clear the pointer, but then becomes responsible for disposing of the - object. - - (*) int vfs_parse_fs_string(struct fs_context *fc, const char *key, - const char *value, size_t v_size); - - A wrapper around vfs_parse_fs_param() that copies the value string it is - passed. - - (*) int generic_parse_monolithic(struct fs_context *fc, void *data); - - Parse a sys_mount() data page, assuming the form to be a text list - consisting of key[=val] options separated by commas. Each item in the - list is passed to vfs_mount_option(). This is the default when the - ->parse_monolithic() method is NULL. - - (*) int vfs_get_tree(struct fs_context *fc); - - Get or create the mountable root and superblock, using the parameters in - the filesystem context to select/configure the superblock. This invokes - the ->get_tree() method. - - (*) struct vfsmount *vfs_create_mount(struct fs_context *fc); - - Create a mount given the parameters in the specified filesystem context. - Note that this does not attach the mount to anything. - - -=========================== -SUPERBLOCK CREATION HELPERS -=========================== - -A number of VFS helpers are available for use by filesystems for the creation -or looking up of superblocks. - - (*) struct super_block * - sget_fc(struct fs_context *fc, - int (*test)(struct super_block *sb, struct fs_context *fc), - int (*set)(struct super_block *sb, struct fs_context *fc)); - - This is the core routine. If test is non-NULL, it searches for an - existing superblock matching the criteria held in the fs_context, using - the test function to match them. If no match is found, a new superblock - is created and the set function is called to set it up. - - Prior to the set function being called, fc->s_fs_info will be transferred - to sb->s_fs_info - and fc->s_fs_info will be cleared if set returns - success (ie. 0). - -The following helpers all wrap sget_fc(): - - (*) int vfs_get_super(struct fs_context *fc, - enum vfs_get_super_keying keying, - int (*fill_super)(struct super_block *sb, - struct fs_context *fc)) - - This creates/looks up a deviceless superblock. The keying indicates how - many superblocks of this type may exist and in what manner they may be - shared: - - (1) vfs_get_single_super - - Only one such superblock may exist in the system. Any further - attempt to get a new superblock gets this one (and any parameter - differences are ignored). - - (2) vfs_get_keyed_super - - Multiple superblocks of this type may exist and they're keyed on - their s_fs_info pointer (for example this may refer to a - namespace). - - (3) vfs_get_independent_super - - Multiple independent superblocks of this type may exist. This - function never matches an existing one and always creates a new - one. - - -===================== -PARAMETER DESCRIPTION -===================== - -Parameters are described using structures defined in linux/fs_parser.h. -There's a core description struct that links everything together: - - struct fs_parameter_description { - const struct fs_parameter_spec *specs; - const struct fs_parameter_enum *enums; - }; - -For example: - - enum { - Opt_autocell, - Opt_bar, - Opt_dyn, - Opt_foo, - Opt_source, - }; - - static const struct fs_parameter_description afs_fs_parameters = { - .specs = afs_param_specs, - .enums = afs_param_enums, - }; - -The members are as follows: - - (1) const struct fs_parameter_specification *specs; - - Table of parameter specifications, terminated with a null entry, where the - entries are of type: - - struct fs_parameter_spec { - const char *name; - u8 opt; - enum fs_parameter_type type:8; - unsigned short flags; - }; - - The 'name' field is a string to match exactly to the parameter key (no - wildcards, patterns and no case-independence) and 'opt' is the value that - will be returned by the fs_parser() function in the case of a successful - match. - - The 'type' field indicates the desired value type and must be one of: - - TYPE NAME EXPECTED VALUE RESULT IN - ======================= ======================= ===================== - fs_param_is_flag No value n/a - fs_param_is_bool Boolean value result->boolean - fs_param_is_u32 32-bit unsigned int result->uint_32 - fs_param_is_u32_octal 32-bit octal int result->uint_32 - fs_param_is_u32_hex 32-bit hex int result->uint_32 - fs_param_is_s32 32-bit signed int result->int_32 - fs_param_is_u64 64-bit unsigned int result->uint_64 - fs_param_is_enum Enum value name result->uint_32 - fs_param_is_string Arbitrary string param->string - fs_param_is_blob Binary blob param->blob - fs_param_is_blockdev Blockdev path * Needs lookup - fs_param_is_path Path * Needs lookup - fs_param_is_fd File descriptor result->int_32 - - Note that if the value is of fs_param_is_bool type, fs_parse() will try - to match any string value against "0", "1", "no", "yes", "false", "true". - - Each parameter can also be qualified with 'flags': - - fs_param_v_optional The value is optional - fs_param_neg_with_no result->negated set if key is prefixed with "no" - fs_param_neg_with_empty result->negated set if value is "" - fs_param_deprecated The parameter is deprecated. - - These are wrapped with a number of convenience wrappers: - - MACRO SPECIFIES - ======================= =============================================== - fsparam_flag() fs_param_is_flag - fsparam_flag_no() fs_param_is_flag, fs_param_neg_with_no - fsparam_bool() fs_param_is_bool - fsparam_u32() fs_param_is_u32 - fsparam_u32oct() fs_param_is_u32_octal - fsparam_u32hex() fs_param_is_u32_hex - fsparam_s32() fs_param_is_s32 - fsparam_u64() fs_param_is_u64 - fsparam_enum() fs_param_is_enum - fsparam_string() fs_param_is_string - fsparam_blob() fs_param_is_blob - fsparam_bdev() fs_param_is_blockdev - fsparam_path() fs_param_is_path - fsparam_fd() fs_param_is_fd - - all of which take two arguments, name string and option number - for - example: - - static const struct fs_parameter_spec afs_param_specs[] = { - fsparam_flag ("autocell", Opt_autocell), - fsparam_flag ("dyn", Opt_dyn), - fsparam_string ("source", Opt_source), - fsparam_flag_no ("foo", Opt_foo), - {} - }; - - An addition macro, __fsparam() is provided that takes an additional pair - of arguments to specify the type and the flags for anything that doesn't - match one of the above macros. - - (2) const struct fs_parameter_enum *enums; - - Table of enum value names to integer mappings, terminated with a null - entry. This is of type: - - struct fs_parameter_enum { - u8 opt; - char name[14]; - u8 value; - }; - - Where the array is an unsorted list of { parameter ID, name }-keyed - elements that indicate the value to map to, e.g.: - - static const struct fs_parameter_enum afs_param_enums[] = { - { Opt_bar, "x", 1}, - { Opt_bar, "y", 23}, - { Opt_bar, "z", 42}, - }; - - If a parameter of type fs_param_is_enum is encountered, fs_parse() will - try to look the value up in the enum table and the result will be stored - in the parse result. - -The parser should be pointed to by the parser pointer in the file_system_type -struct as this will provide validation on registration (if -CONFIG_VALIDATE_FS_PARSER=y) and will allow the description to be queried from -userspace using the fsinfo() syscall. - - -========================== -PARAMETER HELPER FUNCTIONS -========================== - -A number of helper functions are provided to help a filesystem or an LSM -process the parameters it is given. - - (*) int lookup_constant(const struct constant_table tbl[], - const char *name, int not_found); - - Look up a constant by name in a table of name -> integer mappings. The - table is an array of elements of the following type: - - struct constant_table { - const char *name; - int value; - }; - - If a match is found, the corresponding value is returned. If a match - isn't found, the not_found value is returned instead. - - (*) bool validate_constant_table(const struct constant_table *tbl, - size_t tbl_size, - int low, int high, int special); - - Validate a constant table. Checks that all the elements are appropriately - ordered, that there are no duplicates and that the values are between low - and high inclusive, though provision is made for one allowable special - value outside of that range. If no special value is required, special - should just be set to lie inside the low-to-high range. - - If all is good, true is returned. If the table is invalid, errors are - logged to dmesg and false is returned. - - (*) bool fs_validate_description(const struct fs_parameter_description *desc); - - This performs some validation checks on a parameter description. It - returns true if the description is good and false if it is not. It will - log errors to dmesg if validation fails. - - (*) int fs_parse(struct fs_context *fc, - const struct fs_parameter_description *desc, - struct fs_parameter *param, - struct fs_parse_result *result); - - This is the main interpreter of parameters. It uses the parameter - description to look up a parameter by key name and to convert that to an - option number (which it returns). - - If successful, and if the parameter type indicates the result is a - boolean, integer or enum type, the value is converted by this function and - the result stored in result->{boolean,int_32,uint_32,uint_64}. - - If a match isn't initially made, the key is prefixed with "no" and no - value is present then an attempt will be made to look up the key with the - prefix removed. If this matches a parameter for which the type has flag - fs_param_neg_with_no set, then a match will be made and result->negated - will be set to true. - - If the parameter isn't matched, -ENOPARAM will be returned; if the - parameter is matched, but the value is erroneous, -EINVAL will be - returned; otherwise the parameter's option number will be returned. - - (*) int fs_lookup_param(struct fs_context *fc, - struct fs_parameter *value, - bool want_bdev, - struct path *_path); - - This takes a parameter that carries a string or filename type and attempts - to do a path lookup on it. If the parameter expects a blockdev, a check - is made that the inode actually represents one. - - Returns 0 if successful and *_path will be set; returns a negative error - code if not. -- cgit v1.2.3