xref: /linux-6.15/include/linux/fs_context.h (revision bdfa77e7)
1b4d0d230SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
29bc61ab1SDavid Howells /* Filesystem superblock creation and reconfiguration context.
39bc61ab1SDavid Howells  *
49bc61ab1SDavid Howells  * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
59bc61ab1SDavid Howells  * Written by David Howells ([email protected])
69bc61ab1SDavid Howells  */
79bc61ab1SDavid Howells 
89bc61ab1SDavid Howells #ifndef _LINUX_FS_CONTEXT_H
99bc61ab1SDavid Howells #define _LINUX_FS_CONTEXT_H
109bc61ab1SDavid Howells 
119bc61ab1SDavid Howells #include <linux/kernel.h>
12007ec26cSDavid Howells #include <linux/refcount.h>
139bc61ab1SDavid Howells #include <linux/errno.h>
149bc61ab1SDavid Howells #include <linux/security.h>
1524dcb3d9SDavid Howells #include <linux/mutex.h>
169bc61ab1SDavid Howells 
179bc61ab1SDavid Howells struct cred;
189bc61ab1SDavid Howells struct dentry;
199bc61ab1SDavid Howells struct file_operations;
209bc61ab1SDavid Howells struct file_system_type;
21f3a09c92SAl Viro struct mnt_namespace;
229bc61ab1SDavid Howells struct net;
23f3a09c92SAl Viro struct pid_namespace;
24f3a09c92SAl Viro struct super_block;
259bc61ab1SDavid Howells struct user_namespace;
26f3a09c92SAl Viro struct vfsmount;
27f3a09c92SAl Viro struct path;
289bc61ab1SDavid Howells 
299bc61ab1SDavid Howells enum fs_context_purpose {
309bc61ab1SDavid Howells 	FS_CONTEXT_FOR_MOUNT,		/* New superblock for explicit mount */
31e1a91586SAl Viro 	FS_CONTEXT_FOR_SUBMOUNT,	/* New superblock for automatic submount */
328d0347f6SDavid Howells 	FS_CONTEXT_FOR_RECONFIGURE,	/* Superblock reconfiguration (remount) */
339bc61ab1SDavid Howells };
349bc61ab1SDavid Howells 
359bc61ab1SDavid Howells /*
3624dcb3d9SDavid Howells  * Userspace usage phase for fsopen/fspick.
3724dcb3d9SDavid Howells  */
3824dcb3d9SDavid Howells enum fs_context_phase {
3924dcb3d9SDavid Howells 	FS_CONTEXT_CREATE_PARAMS,	/* Loading params for sb creation */
4024dcb3d9SDavid Howells 	FS_CONTEXT_CREATING,		/* A superblock is being created */
4124dcb3d9SDavid Howells 	FS_CONTEXT_AWAITING_MOUNT,	/* Superblock created, awaiting fsmount() */
4224dcb3d9SDavid Howells 	FS_CONTEXT_AWAITING_RECONF,	/* Awaiting initialisation for reconfiguration */
4324dcb3d9SDavid Howells 	FS_CONTEXT_RECONF_PARAMS,	/* Loading params for reconfiguration */
4424dcb3d9SDavid Howells 	FS_CONTEXT_RECONFIGURING,	/* Reconfiguring the superblock */
4524dcb3d9SDavid Howells 	FS_CONTEXT_FAILED,		/* Failed to correctly transition a context */
4624dcb3d9SDavid Howells };
4724dcb3d9SDavid Howells 
4824dcb3d9SDavid Howells /*
4931d921c7SDavid Howells  * Type of parameter value.
5031d921c7SDavid Howells  */
5131d921c7SDavid Howells enum fs_value_type {
5231d921c7SDavid Howells 	fs_value_is_undefined,
5331d921c7SDavid Howells 	fs_value_is_flag,		/* Value not given a value */
5431d921c7SDavid Howells 	fs_value_is_string,		/* Value is a string */
5531d921c7SDavid Howells 	fs_value_is_blob,		/* Value is a binary blob */
5631d921c7SDavid Howells 	fs_value_is_filename,		/* Value is a filename* + dirfd */
5731d921c7SDavid Howells 	fs_value_is_file,		/* Value is a file* */
5831d921c7SDavid Howells };
5931d921c7SDavid Howells 
6031d921c7SDavid Howells /*
6131d921c7SDavid Howells  * Configuration parameter.
6231d921c7SDavid Howells  */
6331d921c7SDavid Howells struct fs_parameter {
6431d921c7SDavid Howells 	const char		*key;		/* Parameter name */
6531d921c7SDavid Howells 	enum fs_value_type	type:8;		/* The type of value here */
6631d921c7SDavid Howells 	union {
6731d921c7SDavid Howells 		char		*string;
6831d921c7SDavid Howells 		void		*blob;
6931d921c7SDavid Howells 		struct filename	*name;
7031d921c7SDavid Howells 		struct file	*file;
7131d921c7SDavid Howells 	};
7231d921c7SDavid Howells 	size_t	size;
7331d921c7SDavid Howells 	int	dirfd;
7431d921c7SDavid Howells };
7531d921c7SDavid Howells 
763fbb8d55SAl Viro struct p_log {
773fbb8d55SAl Viro 	const char *prefix;
783fbb8d55SAl Viro 	struct fc_log *log;
793fbb8d55SAl Viro };
803fbb8d55SAl Viro 
8131d921c7SDavid Howells /*
829bc61ab1SDavid Howells  * Filesystem context for holding the parameters used in the creation or
839bc61ab1SDavid Howells  * reconfiguration of a superblock.
849bc61ab1SDavid Howells  *
859bc61ab1SDavid Howells  * Superblock creation fills in ->root whereas reconfiguration begins with this
869bc61ab1SDavid Howells  * already set.
879bc61ab1SDavid Howells  *
88791a17eeSMauro Carvalho Chehab  * See Documentation/filesystems/mount_api.rst
899bc61ab1SDavid Howells  */
909bc61ab1SDavid Howells struct fs_context {
91f3a09c92SAl Viro 	const struct fs_context_operations *ops;
9224dcb3d9SDavid Howells 	struct mutex		uapi_mutex;	/* Userspace access mutex */
939bc61ab1SDavid Howells 	struct file_system_type	*fs_type;
949bc61ab1SDavid Howells 	void			*fs_private;	/* The filesystem's context */
95fe62c3a4SDavid Howells 	void			*sget_key;
969bc61ab1SDavid Howells 	struct dentry		*root;		/* The root and superblock */
979bc61ab1SDavid Howells 	struct user_namespace	*user_ns;	/* The user namespace for this mount */
989bc61ab1SDavid Howells 	struct net		*net_ns;	/* The network namespace for this mount */
999bc61ab1SDavid Howells 	const struct cred	*cred;		/* The mounter's credentials */
100cc3c0b53SAl Viro 	struct p_log		log;		/* Logging buffer */
1019bc61ab1SDavid Howells 	const char		*source;	/* The source name (eg. dev path) */
1023b87d9f4SPaul Moore 	void			*security;	/* LSM options */
103cb50b348SAl Viro 	void			*s_fs_info;	/* Proposed s_fs_info */
1049bc61ab1SDavid Howells 	unsigned int		sb_flags;	/* Proposed superblock flags (SB_*) */
1059bc61ab1SDavid Howells 	unsigned int		sb_flags_mask;	/* Superblock flags that were changed */
106c80fa7c8SDavid Howells 	unsigned int		s_iflags;	/* OR'd with sb->s_iflags */
1079bc61ab1SDavid Howells 	enum fs_context_purpose	purpose:8;
10824dcb3d9SDavid Howells 	enum fs_context_phase	phase:8;	/* The phase the context is in */
1099bc61ab1SDavid Howells 	bool			need_free:1;	/* Need to call ops->free() */
110cb50b348SAl Viro 	bool			global:1;	/* Goes into &init_user_ns */
111b330966fSMiklos Szeredi 	bool			oldapi:1;	/* Coming from mount(2) */
11222ed7ecdSChristian Brauner 	bool			exclusive:1;    /* create new superblock, reject existing one */
1139bc61ab1SDavid Howells };
1149bc61ab1SDavid Howells 
115f3a09c92SAl Viro struct fs_context_operations {
116f3a09c92SAl Viro 	void (*free)(struct fs_context *fc);
1170b52075eSAl Viro 	int (*dup)(struct fs_context *fc, struct fs_context *src_fc);
1183e1aeb00SDavid Howells 	int (*parse_param)(struct fs_context *fc, struct fs_parameter *param);
119f3a09c92SAl Viro 	int (*parse_monolithic)(struct fs_context *fc, void *data);
120f3a09c92SAl Viro 	int (*get_tree)(struct fs_context *fc);
121f3a09c92SAl Viro 	int (*reconfigure)(struct fs_context *fc);
122f3a09c92SAl Viro };
123f3a09c92SAl Viro 
1249bc61ab1SDavid Howells /*
1259bc61ab1SDavid Howells  * fs_context manipulation functions.
1269bc61ab1SDavid Howells  */
1279bc61ab1SDavid Howells extern struct fs_context *fs_context_for_mount(struct file_system_type *fs_type,
1289bc61ab1SDavid Howells 						unsigned int sb_flags);
1298d0347f6SDavid Howells extern struct fs_context *fs_context_for_reconfigure(struct dentry *dentry,
1308d0347f6SDavid Howells 						unsigned int sb_flags,
1318d0347f6SDavid Howells 						unsigned int sb_flags_mask);
132e1a91586SAl Viro extern struct fs_context *fs_context_for_submount(struct file_system_type *fs_type,
133e1a91586SAl Viro 						struct dentry *reference);
1349bc61ab1SDavid Howells 
1350b52075eSAl Viro extern struct fs_context *vfs_dup_fs_context(struct fs_context *fc);
1363e1aeb00SDavid Howells extern int vfs_parse_fs_param(struct fs_context *fc, struct fs_parameter *param);
1373e1aeb00SDavid Howells extern int vfs_parse_fs_string(struct fs_context *fc, const char *key,
1383e1aeb00SDavid Howells 			       const char *value, size_t v_size);
139e001d144SAmir Goldstein int vfs_parse_monolithic_sep(struct fs_context *fc, void *data,
140e001d144SAmir Goldstein 			     char *(*sep)(char **));
1413e1aeb00SDavid Howells extern int generic_parse_monolithic(struct fs_context *fc, void *data);
1429bc61ab1SDavid Howells extern int vfs_get_tree(struct fs_context *fc);
1439bc61ab1SDavid Howells extern void put_fs_context(struct fs_context *fc);
144d1d488d8SChristian Brauner extern int vfs_parse_fs_param_source(struct fs_context *fc,
145d1d488d8SChristian Brauner 				     struct fs_parameter *param);
1461e7107c5SPaul Gortmaker extern void fc_drop_locked(struct fs_context *fc);
1479bc61ab1SDavid Howells 
1482ac295d4SAl Viro extern int get_tree_nodev(struct fs_context *fc,
1492ac295d4SAl Viro 			 int (*fill_super)(struct super_block *sb,
1502ac295d4SAl Viro 					   struct fs_context *fc));
151c23a0bbaSAl Viro extern int get_tree_single(struct fs_context *fc,
152c23a0bbaSAl Viro 			 int (*fill_super)(struct super_block *sb,
153c23a0bbaSAl Viro 					   struct fs_context *fc));
154533770ccSAl Viro extern int get_tree_keyed(struct fs_context *fc,
155533770ccSAl Viro 			 int (*fill_super)(struct super_block *sb,
156533770ccSAl Viro 					   struct fs_context *fc),
157533770ccSAl Viro 			 void *key);
158cb50b348SAl Viro 
159cf6da236SChristoph Hellwig int setup_bdev_super(struct super_block *sb, int sb_flags,
160cf6da236SChristoph Hellwig 		struct fs_context *fc);
161*4021e685SGao Xiang 
162*4021e685SGao Xiang #define GET_TREE_BDEV_QUIET_LOOKUP		0x0001
163*4021e685SGao Xiang int get_tree_bdev_flags(struct fs_context *fc,
164*4021e685SGao Xiang 		int (*fill_super)(struct super_block *sb,
165*4021e685SGao Xiang 				  struct fs_context *fc), unsigned int flags);
166*4021e685SGao Xiang 
167fe62c3a4SDavid Howells extern int get_tree_bdev(struct fs_context *fc,
168fe62c3a4SDavid Howells 			       int (*fill_super)(struct super_block *sb,
169fe62c3a4SDavid Howells 						 struct fs_context *fc));
170fe62c3a4SDavid Howells 
171e7582e16SDavid Howells extern const struct file_operations fscontext_fops;
172e7582e16SDavid Howells 
173007ec26cSDavid Howells /*
174007ec26cSDavid Howells  * Mount error, warning and informational message logging.  This structure is
175007ec26cSDavid Howells  * shareable between a mount and a subordinate mount.
176007ec26cSDavid Howells  */
177007ec26cSDavid Howells struct fc_log {
178007ec26cSDavid Howells 	refcount_t	usage;
179007ec26cSDavid Howells 	u8		head;		/* Insertion index in buffer[] */
180007ec26cSDavid Howells 	u8		tail;		/* Removal index in buffer[] */
181007ec26cSDavid Howells 	u8		need_free;	/* Mask of kfree'able items in buffer[] */
182007ec26cSDavid Howells 	struct module	*owner;		/* Owner module for strings that don't then need freeing */
183007ec26cSDavid Howells 	char		*buffer[8];
184007ec26cSDavid Howells };
185007ec26cSDavid Howells 
1869f09f649SAl Viro extern __attribute__((format(printf, 4, 5)))
1879f09f649SAl Viro void logfc(struct fc_log *log, const char *prefix, char level, const char *fmt, ...);
188c6b82263SDavid Howells 
189cc3c0b53SAl Viro #define __logfc(fc, l, fmt, ...) logfc((fc)->log.log, NULL, \
1907f5d3814SAl Viro 					l, fmt, ## __VA_ARGS__)
1913fbb8d55SAl Viro #define __plog(p, l, fmt, ...) logfc((p)->log, (p)->prefix, \
1923fbb8d55SAl Viro 					l, fmt, ## __VA_ARGS__)
193c6b82263SDavid Howells /**
194c6b82263SDavid Howells  * infof - Store supplementary informational message
195c6b82263SDavid Howells  * @fc: The context in which to log the informational message
196c6b82263SDavid Howells  * @fmt: The format string
197c6b82263SDavid Howells  *
198c6b82263SDavid Howells  * Store the supplementary informational message for the process if the process
199c6b82263SDavid Howells  * has enabled the facility.
200c6b82263SDavid Howells  */
2019f09f649SAl Viro #define infof(fc, fmt, ...) __logfc(fc, 'i', fmt, ## __VA_ARGS__)
2023fbb8d55SAl Viro #define info_plog(p, fmt, ...) __plog(p, 'i', fmt, ## __VA_ARGS__)
203a3ff937bSAl Viro #define infofc(p, fmt, ...) __plog((&(fc)->log), 'i', fmt, ## __VA_ARGS__)
204c6b82263SDavid Howells 
205c6b82263SDavid Howells /**
206c6b82263SDavid Howells  * warnf - Store supplementary warning message
207c6b82263SDavid Howells  * @fc: The context in which to log the error message
208c6b82263SDavid Howells  * @fmt: The format string
209c6b82263SDavid Howells  *
210c6b82263SDavid Howells  * Store the supplementary warning message for the process if the process has
211c6b82263SDavid Howells  * enabled the facility.
212c6b82263SDavid Howells  */
2139f09f649SAl Viro #define warnf(fc, fmt, ...) __logfc(fc, 'w', fmt, ## __VA_ARGS__)
2143fbb8d55SAl Viro #define warn_plog(p, fmt, ...) __plog(p, 'w', fmt, ## __VA_ARGS__)
215a3ff937bSAl Viro #define warnfc(fc, fmt, ...) __plog((&(fc)->log), 'w', fmt, ## __VA_ARGS__)
216c6b82263SDavid Howells 
217c6b82263SDavid Howells /**
218c6b82263SDavid Howells  * errorf - Store supplementary error message
219c6b82263SDavid Howells  * @fc: The context in which to log the error message
220c6b82263SDavid Howells  * @fmt: The format string
221c6b82263SDavid Howells  *
222c6b82263SDavid Howells  * Store the supplementary error message for the process if the process has
223c6b82263SDavid Howells  * enabled the facility.
224c6b82263SDavid Howells  */
2259f09f649SAl Viro #define errorf(fc, fmt, ...) __logfc(fc, 'e', fmt, ## __VA_ARGS__)
2263fbb8d55SAl Viro #define error_plog(p, fmt, ...) __plog(p, 'e', fmt, ## __VA_ARGS__)
227a3ff937bSAl Viro #define errorfc(fc, fmt, ...) __plog((&(fc)->log), 'e', fmt, ## __VA_ARGS__)
228c6b82263SDavid Howells 
229c6b82263SDavid Howells /**
230c6b82263SDavid Howells  * invalf - Store supplementary invalid argument error message
231c6b82263SDavid Howells  * @fc: The context in which to log the error message
232c6b82263SDavid Howells  * @fmt: The format string
233c6b82263SDavid Howells  *
234c6b82263SDavid Howells  * Store the supplementary error message for the process if the process has
235c6b82263SDavid Howells  * enabled the facility and return -EINVAL.
236c6b82263SDavid Howells  */
2379f09f649SAl Viro #define invalf(fc, fmt, ...) (errorf(fc, fmt, ## __VA_ARGS__), -EINVAL)
2383fbb8d55SAl Viro #define inval_plog(p, fmt, ...) (error_plog(p, fmt, ## __VA_ARGS__), -EINVAL)
239a3ff937bSAl Viro #define invalfc(fc, fmt, ...) (errorfc(fc, fmt, ## __VA_ARGS__), -EINVAL)
240c6b82263SDavid Howells 
2419bc61ab1SDavid Howells #endif /* _LINUX_FS_CONTEXT_H */
242