mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
824 lines
27 KiB
824 lines
27 KiB
.. 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 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 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 includes |
|
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 the kernel log buffer 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 the kernel log buffer 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.
|
|
|