mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	introduce fs_context methods
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									e1a91586d5
								
							
						
					
					
						commit
						f3a09c9201
					
				
					 5 changed files with 65 additions and 16 deletions
				
			
		| 
						 | 
					@ -51,6 +51,7 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
 | 
				
			||||||
				      unsigned int sb_flags_mask,
 | 
									      unsigned int sb_flags_mask,
 | 
				
			||||||
				      enum fs_context_purpose purpose)
 | 
									      enum fs_context_purpose purpose)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						int (*init_fs_context)(struct fs_context *);
 | 
				
			||||||
	struct fs_context *fc;
 | 
						struct fs_context *fc;
 | 
				
			||||||
	int ret = -ENOMEM;
 | 
						int ret = -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,7 +82,12 @@ static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = legacy_init_fs_context(fc);
 | 
						/* TODO: Make all filesystems support this unconditionally */
 | 
				
			||||||
 | 
						init_fs_context = fc->fs_type->init_fs_context;
 | 
				
			||||||
 | 
						if (!init_fs_context)
 | 
				
			||||||
 | 
							init_fs_context = legacy_init_fs_context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = init_fs_context(fc);
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0)
 | 
				
			||||||
		goto err_fc;
 | 
							goto err_fc;
 | 
				
			||||||
	fc->need_free = true;
 | 
						fc->need_free = true;
 | 
				
			||||||
| 
						 | 
					@ -141,8 +147,8 @@ void put_fs_context(struct fs_context *fc)
 | 
				
			||||||
		deactivate_super(sb);
 | 
							deactivate_super(sb);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (fc->need_free)
 | 
						if (fc->need_free && fc->ops && fc->ops->free)
 | 
				
			||||||
		legacy_fs_context_free(fc);
 | 
							fc->ops->free(fc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	security_free_mnt_opts(&fc->security);
 | 
						security_free_mnt_opts(&fc->security);
 | 
				
			||||||
	put_net(fc->net_ns);
 | 
						put_net(fc->net_ns);
 | 
				
			||||||
| 
						 | 
					@ -180,7 +186,7 @@ static int legacy_parse_monolithic(struct fs_context *fc, void *data)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Get a mountable root with the legacy mount command.
 | 
					 * Get a mountable root with the legacy mount command.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int legacy_get_tree(struct fs_context *fc)
 | 
					static int legacy_get_tree(struct fs_context *fc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct legacy_fs_context *ctx = fc->fs_private;
 | 
						struct legacy_fs_context *ctx = fc->fs_private;
 | 
				
			||||||
	struct super_block *sb;
 | 
						struct super_block *sb;
 | 
				
			||||||
| 
						 | 
					@ -201,7 +207,7 @@ int legacy_get_tree(struct fs_context *fc)
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Handle remount.
 | 
					 * Handle remount.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int legacy_reconfigure(struct fs_context *fc)
 | 
					static int legacy_reconfigure(struct fs_context *fc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct legacy_fs_context *ctx = fc->fs_private;
 | 
						struct legacy_fs_context *ctx = fc->fs_private;
 | 
				
			||||||
	struct super_block *sb = fc->root->d_sb;
 | 
						struct super_block *sb = fc->root->d_sb;
 | 
				
			||||||
| 
						 | 
					@ -213,6 +219,13 @@ int legacy_reconfigure(struct fs_context *fc)
 | 
				
			||||||
				    ctx ? ctx->legacy_data : NULL);
 | 
									    ctx ? ctx->legacy_data : NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct fs_context_operations legacy_fs_context_ops = {
 | 
				
			||||||
 | 
						.free			= legacy_fs_context_free,
 | 
				
			||||||
 | 
						.parse_monolithic	= legacy_parse_monolithic,
 | 
				
			||||||
 | 
						.get_tree		= legacy_get_tree,
 | 
				
			||||||
 | 
						.reconfigure		= legacy_reconfigure,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Initialise a legacy context for a filesystem that doesn't support
 | 
					 * Initialise a legacy context for a filesystem that doesn't support
 | 
				
			||||||
 * fs_context.
 | 
					 * fs_context.
 | 
				
			||||||
| 
						 | 
					@ -222,10 +235,13 @@ static int legacy_init_fs_context(struct fs_context *fc)
 | 
				
			||||||
	fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL);
 | 
						fc->fs_private = kzalloc(sizeof(struct legacy_fs_context), GFP_KERNEL);
 | 
				
			||||||
	if (!fc->fs_private)
 | 
						if (!fc->fs_private)
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
 | 
						fc->ops = &legacy_fs_context_ops;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int parse_monolithic_mount_data(struct fs_context *fc, void *data)
 | 
					int parse_monolithic_mount_data(struct fs_context *fc, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return legacy_parse_monolithic(fc, data);
 | 
						int (*monolithic_mount_data)(struct fs_context *, void *);
 | 
				
			||||||
 | 
						monolithic_mount_data = fc->ops->parse_monolithic;
 | 
				
			||||||
 | 
						return monolithic_mount_data(fc, data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,8 +55,6 @@ extern void __init chrdev_init(void);
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * fs_context.c
 | 
					 * fs_context.c
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
extern int legacy_get_tree(struct fs_context *fc);
 | 
					 | 
				
			||||||
extern int legacy_reconfigure(struct fs_context *fc);
 | 
					 | 
				
			||||||
extern int parse_monolithic_mount_data(struct fs_context *, void *);
 | 
					extern int parse_monolithic_mount_data(struct fs_context *, void *);
 | 
				
			||||||
extern void fc_drop_locked(struct fs_context *);
 | 
					extern void fc_drop_locked(struct fs_context *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								fs/super.c
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								fs/super.c
									
									
									
									
									
								
							| 
						 | 
					@ -894,13 +894,15 @@ int reconfigure_super(struct fs_context *fc)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	retval = legacy_reconfigure(fc);
 | 
						if (fc->ops->reconfigure) {
 | 
				
			||||||
	if (retval) {
 | 
							retval = fc->ops->reconfigure(fc);
 | 
				
			||||||
		if (!force)
 | 
							if (retval) {
 | 
				
			||||||
			goto cancel_readonly;
 | 
								if (!force)
 | 
				
			||||||
		/* If forced remount, go ahead despite any errors */
 | 
									goto cancel_readonly;
 | 
				
			||||||
		WARN(1, "forced remount of a %s fs returned %i\n",
 | 
								/* If forced remount, go ahead despite any errors */
 | 
				
			||||||
		     sb->s_type->name, retval);
 | 
								WARN(1, "forced remount of a %s fs returned %i\n",
 | 
				
			||||||
 | 
								     sb->s_type->name, retval);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) |
 | 
						WRITE_ONCE(sb->s_flags, ((sb->s_flags & ~fc->sb_flags_mask) |
 | 
				
			||||||
| 
						 | 
					@ -1294,10 +1296,28 @@ int vfs_get_tree(struct fs_context *fc)
 | 
				
			||||||
	struct super_block *sb;
 | 
						struct super_block *sb;
 | 
				
			||||||
	int error;
 | 
						int error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	error = legacy_get_tree(fc);
 | 
						if (fc->fs_type->fs_flags & FS_REQUIRES_DEV && !fc->source)
 | 
				
			||||||
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fc->root)
 | 
				
			||||||
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Get the mountable root in fc->root, with a ref on the root and a ref
 | 
				
			||||||
 | 
						 * on the superblock.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						error = fc->ops->get_tree(fc);
 | 
				
			||||||
	if (error < 0)
 | 
						if (error < 0)
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!fc->root) {
 | 
				
			||||||
 | 
							pr_err("Filesystem %s get_tree() didn't set fc->root\n",
 | 
				
			||||||
 | 
							       fc->fs_type->name);
 | 
				
			||||||
 | 
							/* We don't know what the locking state of the superblock is -
 | 
				
			||||||
 | 
							 * if there is a superblock.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							BUG();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sb = fc->root->d_sb;
 | 
						sb = fc->root->d_sb;
 | 
				
			||||||
	WARN_ON(!sb->s_bdi);
 | 
						WARN_ON(!sb->s_bdi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,6 +61,7 @@ struct workqueue_struct;
 | 
				
			||||||
struct iov_iter;
 | 
					struct iov_iter;
 | 
				
			||||||
struct fscrypt_info;
 | 
					struct fscrypt_info;
 | 
				
			||||||
struct fscrypt_operations;
 | 
					struct fscrypt_operations;
 | 
				
			||||||
 | 
					struct fs_context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void __init inode_init(void);
 | 
					extern void __init inode_init(void);
 | 
				
			||||||
extern void __init inode_init_early(void);
 | 
					extern void __init inode_init_early(void);
 | 
				
			||||||
| 
						 | 
					@ -2173,6 +2174,7 @@ struct file_system_type {
 | 
				
			||||||
#define FS_HAS_SUBTYPE		4
 | 
					#define FS_HAS_SUBTYPE		4
 | 
				
			||||||
#define FS_USERNS_MOUNT		8	/* Can be mounted by userns root */
 | 
					#define FS_USERNS_MOUNT		8	/* Can be mounted by userns root */
 | 
				
			||||||
#define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
 | 
					#define FS_RENAME_DOES_D_MOVE	32768	/* FS will handle d_move() during rename() internally. */
 | 
				
			||||||
 | 
						int (*init_fs_context)(struct fs_context *);
 | 
				
			||||||
	struct dentry *(*mount) (struct file_system_type *, int,
 | 
						struct dentry *(*mount) (struct file_system_type *, int,
 | 
				
			||||||
		       const char *, void *);
 | 
							       const char *, void *);
 | 
				
			||||||
	void (*kill_sb) (struct super_block *);
 | 
						void (*kill_sb) (struct super_block *);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,8 +20,13 @@ struct cred;
 | 
				
			||||||
struct dentry;
 | 
					struct dentry;
 | 
				
			||||||
struct file_operations;
 | 
					struct file_operations;
 | 
				
			||||||
struct file_system_type;
 | 
					struct file_system_type;
 | 
				
			||||||
 | 
					struct mnt_namespace;
 | 
				
			||||||
struct net;
 | 
					struct net;
 | 
				
			||||||
 | 
					struct pid_namespace;
 | 
				
			||||||
 | 
					struct super_block;
 | 
				
			||||||
struct user_namespace;
 | 
					struct user_namespace;
 | 
				
			||||||
 | 
					struct vfsmount;
 | 
				
			||||||
 | 
					struct path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum fs_context_purpose {
 | 
					enum fs_context_purpose {
 | 
				
			||||||
	FS_CONTEXT_FOR_MOUNT,		/* New superblock for explicit mount */
 | 
						FS_CONTEXT_FOR_MOUNT,		/* New superblock for explicit mount */
 | 
				
			||||||
| 
						 | 
					@ -39,6 +44,7 @@ enum fs_context_purpose {
 | 
				
			||||||
 * See Documentation/filesystems/mounting.txt
 | 
					 * See Documentation/filesystems/mounting.txt
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct fs_context {
 | 
					struct fs_context {
 | 
				
			||||||
 | 
						const struct fs_context_operations *ops;
 | 
				
			||||||
	struct file_system_type	*fs_type;
 | 
						struct file_system_type	*fs_type;
 | 
				
			||||||
	void			*fs_private;	/* The filesystem's context */
 | 
						void			*fs_private;	/* The filesystem's context */
 | 
				
			||||||
	struct dentry		*root;		/* The root and superblock */
 | 
						struct dentry		*root;		/* The root and superblock */
 | 
				
			||||||
| 
						 | 
					@ -54,6 +60,13 @@ struct fs_context {
 | 
				
			||||||
	bool			need_free:1;	/* Need to call ops->free() */
 | 
						bool			need_free:1;	/* Need to call ops->free() */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct fs_context_operations {
 | 
				
			||||||
 | 
						void (*free)(struct fs_context *fc);
 | 
				
			||||||
 | 
						int (*parse_monolithic)(struct fs_context *fc, void *data);
 | 
				
			||||||
 | 
						int (*get_tree)(struct fs_context *fc);
 | 
				
			||||||
 | 
						int (*reconfigure)(struct fs_context *fc);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * fs_context manipulation functions.
 | 
					 * fs_context manipulation functions.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue