xref: /openbmc/linux/fs/vboxsf/super.c (revision 55fabde8)
10fd16957SHans de Goede // SPDX-License-Identifier: MIT
20fd16957SHans de Goede /*
30fd16957SHans de Goede  * VirtualBox Guest Shared Folders support: Virtual File System.
40fd16957SHans de Goede  *
50fd16957SHans de Goede  * Module initialization/finalization
60fd16957SHans de Goede  * File system registration/deregistration
70fd16957SHans de Goede  * Superblock reading
80fd16957SHans de Goede  * Few utility functions
90fd16957SHans de Goede  *
100fd16957SHans de Goede  * Copyright (C) 2006-2018 Oracle Corporation
110fd16957SHans de Goede  */
120fd16957SHans de Goede 
130fd16957SHans de Goede #include <linux/idr.h>
140fd16957SHans de Goede #include <linux/fs_parser.h>
150fd16957SHans de Goede #include <linux/magic.h>
160fd16957SHans de Goede #include <linux/module.h>
170fd16957SHans de Goede #include <linux/nls.h>
180fd16957SHans de Goede #include <linux/statfs.h>
190fd16957SHans de Goede #include <linux/vbox_utils.h>
200fd16957SHans de Goede #include "vfsmod.h"
210fd16957SHans de Goede 
220fd16957SHans de Goede #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */
230fd16957SHans de Goede 
249b3b353eSLinus Torvalds static const unsigned char VBSF_MOUNT_SIGNATURE[4] = "\000\377\376\375";
250fd16957SHans de Goede 
260fd16957SHans de Goede static int follow_symlinks;
270fd16957SHans de Goede module_param(follow_symlinks, int, 0444);
280fd16957SHans de Goede MODULE_PARM_DESC(follow_symlinks,
290fd16957SHans de Goede 		 "Let host resolve symlinks rather than showing them");
300fd16957SHans de Goede 
310fd16957SHans de Goede static DEFINE_IDA(vboxsf_bdi_ida);
320fd16957SHans de Goede static DEFINE_MUTEX(vboxsf_setup_mutex);
330fd16957SHans de Goede static bool vboxsf_setup_done;
340fd16957SHans de Goede static struct super_operations vboxsf_super_ops; /* forward declaration */
350fd16957SHans de Goede static struct kmem_cache *vboxsf_inode_cachep;
360fd16957SHans de Goede 
370fd16957SHans de Goede static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT;
380fd16957SHans de Goede 
390fd16957SHans de Goede enum  { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode,
400fd16957SHans de Goede 	opt_dmask, opt_fmask };
410fd16957SHans de Goede 
420fd16957SHans de Goede static const struct fs_parameter_spec vboxsf_fs_parameters[] = {
430fd16957SHans de Goede 	fsparam_string	("nls",		opt_nls),
440fd16957SHans de Goede 	fsparam_u32	("uid",		opt_uid),
450fd16957SHans de Goede 	fsparam_u32	("gid",		opt_gid),
460fd16957SHans de Goede 	fsparam_u32	("ttl",		opt_ttl),
470fd16957SHans de Goede 	fsparam_u32oct	("dmode",	opt_dmode),
480fd16957SHans de Goede 	fsparam_u32oct	("fmode",	opt_fmode),
490fd16957SHans de Goede 	fsparam_u32oct	("dmask",	opt_dmask),
500fd16957SHans de Goede 	fsparam_u32oct	("fmask",	opt_fmask),
510fd16957SHans de Goede 	{}
520fd16957SHans de Goede };
530fd16957SHans de Goede 
vboxsf_parse_param(struct fs_context * fc,struct fs_parameter * param)540fd16957SHans de Goede static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
550fd16957SHans de Goede {
560fd16957SHans de Goede 	struct vboxsf_fs_context *ctx = fc->fs_private;
570fd16957SHans de Goede 	struct fs_parse_result result;
580fd16957SHans de Goede 	kuid_t uid;
590fd16957SHans de Goede 	kgid_t gid;
600fd16957SHans de Goede 	int opt;
610fd16957SHans de Goede 
620fd16957SHans de Goede 	opt = fs_parse(fc, vboxsf_fs_parameters, param, &result);
630fd16957SHans de Goede 	if (opt < 0)
640fd16957SHans de Goede 		return opt;
650fd16957SHans de Goede 
660fd16957SHans de Goede 	switch (opt) {
670fd16957SHans de Goede 	case opt_nls:
680fd16957SHans de Goede 		if (ctx->nls_name || fc->purpose != FS_CONTEXT_FOR_MOUNT) {
690fd16957SHans de Goede 			vbg_err("vboxsf: Cannot reconfigure nls option\n");
700fd16957SHans de Goede 			return -EINVAL;
710fd16957SHans de Goede 		}
720fd16957SHans de Goede 		ctx->nls_name = param->string;
730fd16957SHans de Goede 		param->string = NULL;
740fd16957SHans de Goede 		break;
750fd16957SHans de Goede 	case opt_uid:
760fd16957SHans de Goede 		uid = make_kuid(current_user_ns(), result.uint_32);
770fd16957SHans de Goede 		if (!uid_valid(uid))
780fd16957SHans de Goede 			return -EINVAL;
790fd16957SHans de Goede 		ctx->o.uid = uid;
800fd16957SHans de Goede 		break;
810fd16957SHans de Goede 	case opt_gid:
820fd16957SHans de Goede 		gid = make_kgid(current_user_ns(), result.uint_32);
830fd16957SHans de Goede 		if (!gid_valid(gid))
840fd16957SHans de Goede 			return -EINVAL;
850fd16957SHans de Goede 		ctx->o.gid = gid;
860fd16957SHans de Goede 		break;
870fd16957SHans de Goede 	case opt_ttl:
880fd16957SHans de Goede 		ctx->o.ttl = msecs_to_jiffies(result.uint_32);
890fd16957SHans de Goede 		break;
900fd16957SHans de Goede 	case opt_dmode:
910fd16957SHans de Goede 		if (result.uint_32 & ~0777)
920fd16957SHans de Goede 			return -EINVAL;
930fd16957SHans de Goede 		ctx->o.dmode = result.uint_32;
940fd16957SHans de Goede 		ctx->o.dmode_set = true;
950fd16957SHans de Goede 		break;
960fd16957SHans de Goede 	case opt_fmode:
970fd16957SHans de Goede 		if (result.uint_32 & ~0777)
980fd16957SHans de Goede 			return -EINVAL;
990fd16957SHans de Goede 		ctx->o.fmode = result.uint_32;
1000fd16957SHans de Goede 		ctx->o.fmode_set = true;
1010fd16957SHans de Goede 		break;
1020fd16957SHans de Goede 	case opt_dmask:
1030fd16957SHans de Goede 		if (result.uint_32 & ~07777)
1040fd16957SHans de Goede 			return -EINVAL;
1050fd16957SHans de Goede 		ctx->o.dmask = result.uint_32;
1060fd16957SHans de Goede 		break;
1070fd16957SHans de Goede 	case opt_fmask:
1080fd16957SHans de Goede 		if (result.uint_32 & ~07777)
1090fd16957SHans de Goede 			return -EINVAL;
1100fd16957SHans de Goede 		ctx->o.fmask = result.uint_32;
1110fd16957SHans de Goede 		break;
1120fd16957SHans de Goede 	default:
1130fd16957SHans de Goede 		return -EINVAL;
1140fd16957SHans de Goede 	}
1150fd16957SHans de Goede 
1160fd16957SHans de Goede 	return 0;
1170fd16957SHans de Goede }
1180fd16957SHans de Goede 
vboxsf_fill_super(struct super_block * sb,struct fs_context * fc)1190fd16957SHans de Goede static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
1200fd16957SHans de Goede {
1210fd16957SHans de Goede 	struct vboxsf_fs_context *ctx = fc->fs_private;
1220fd16957SHans de Goede 	struct shfl_string *folder_name, root_path;
1230fd16957SHans de Goede 	struct vboxsf_sbi *sbi;
1240fd16957SHans de Goede 	struct dentry *droot;
1250fd16957SHans de Goede 	struct inode *iroot;
1260fd16957SHans de Goede 	char *nls_name;
1270fd16957SHans de Goede 	size_t size;
1280fd16957SHans de Goede 	int err;
1290fd16957SHans de Goede 
1300fd16957SHans de Goede 	if (!fc->source)
1310fd16957SHans de Goede 		return -EINVAL;
1320fd16957SHans de Goede 
1330fd16957SHans de Goede 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
1340fd16957SHans de Goede 	if (!sbi)
1350fd16957SHans de Goede 		return -ENOMEM;
1360fd16957SHans de Goede 
1370fd16957SHans de Goede 	sbi->o = ctx->o;
1380fd16957SHans de Goede 	idr_init(&sbi->ino_idr);
1390fd16957SHans de Goede 	spin_lock_init(&sbi->ino_idr_lock);
1400fd16957SHans de Goede 	sbi->next_generation = 1;
1410fd16957SHans de Goede 	sbi->bdi_id = -1;
1420fd16957SHans de Goede 
1430fd16957SHans de Goede 	/* Load nls if not utf8 */
1440fd16957SHans de Goede 	nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls;
1450fd16957SHans de Goede 	if (strcmp(nls_name, "utf8") != 0) {
1460fd16957SHans de Goede 		if (nls_name == vboxsf_default_nls)
1470fd16957SHans de Goede 			sbi->nls = load_nls_default();
1480fd16957SHans de Goede 		else
1490fd16957SHans de Goede 			sbi->nls = load_nls(nls_name);
1500fd16957SHans de Goede 
1510fd16957SHans de Goede 		if (!sbi->nls) {
1520fd16957SHans de Goede 			vbg_err("vboxsf: Count not load '%s' nls\n", nls_name);
1530fd16957SHans de Goede 			err = -EINVAL;
154*55fabde8SChristophe JAILLET 			goto fail_destroy_idr;
1550fd16957SHans de Goede 		}
1560fd16957SHans de Goede 	}
1570fd16957SHans de Goede 
1580fd16957SHans de Goede 	sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL);
1590fd16957SHans de Goede 	if (sbi->bdi_id < 0) {
1600fd16957SHans de Goede 		err = sbi->bdi_id;
1610fd16957SHans de Goede 		goto fail_free;
1620fd16957SHans de Goede 	}
1630fd16957SHans de Goede 
164156c7573SChristoph Hellwig 	err = super_setup_bdi_name(sb, "vboxsf-%d", sbi->bdi_id);
1650fd16957SHans de Goede 	if (err)
1660fd16957SHans de Goede 		goto fail_free;
16755b2598eSChristoph Hellwig 	sb->s_bdi->ra_pages = 0;
16855b2598eSChristoph Hellwig 	sb->s_bdi->io_pages = 0;
1690fd16957SHans de Goede 
1700fd16957SHans de Goede 	/* Turn source into a shfl_string and map the folder */
1710fd16957SHans de Goede 	size = strlen(fc->source) + 1;
1720fd16957SHans de Goede 	folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL);
1730fd16957SHans de Goede 	if (!folder_name) {
1740fd16957SHans de Goede 		err = -ENOMEM;
1750fd16957SHans de Goede 		goto fail_free;
1760fd16957SHans de Goede 	}
1770fd16957SHans de Goede 	folder_name->size = size;
1780fd16957SHans de Goede 	folder_name->length = size - 1;
179883f8fe8SAzeem Shaikh 	strscpy(folder_name->string.utf8, fc->source, size);
1800fd16957SHans de Goede 	err = vboxsf_map_folder(folder_name, &sbi->root);
1810fd16957SHans de Goede 	kfree(folder_name);
1820fd16957SHans de Goede 	if (err) {
1830fd16957SHans de Goede 		vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n",
1840fd16957SHans de Goede 			fc->source, err);
1850fd16957SHans de Goede 		goto fail_free;
1860fd16957SHans de Goede 	}
1870fd16957SHans de Goede 
1880fd16957SHans de Goede 	root_path.length = 1;
1890fd16957SHans de Goede 	root_path.size = 2;
1900fd16957SHans de Goede 	root_path.string.utf8[0] = '/';
1910fd16957SHans de Goede 	root_path.string.utf8[1] = 0;
1920fd16957SHans de Goede 	err = vboxsf_stat(sbi, &root_path, &sbi->root_info);
1930fd16957SHans de Goede 	if (err)
1940fd16957SHans de Goede 		goto fail_unmap;
1950fd16957SHans de Goede 
1960fd16957SHans de Goede 	sb->s_magic = VBOXSF_SUPER_MAGIC;
1970fd16957SHans de Goede 	sb->s_blocksize = 1024;
1980fd16957SHans de Goede 	sb->s_maxbytes = MAX_LFS_FILESIZE;
1990fd16957SHans de Goede 	sb->s_op = &vboxsf_super_ops;
2000fd16957SHans de Goede 	sb->s_d_op = &vboxsf_dentry_ops;
2010fd16957SHans de Goede 
2020fd16957SHans de Goede 	iroot = iget_locked(sb, 0);
2030fd16957SHans de Goede 	if (!iroot) {
2040fd16957SHans de Goede 		err = -ENOMEM;
2050fd16957SHans de Goede 		goto fail_unmap;
2060fd16957SHans de Goede 	}
207e98f93e7SAl Viro 	vboxsf_init_inode(sbi, iroot, &sbi->root_info, false);
2080fd16957SHans de Goede 	unlock_new_inode(iroot);
2090fd16957SHans de Goede 
2100fd16957SHans de Goede 	droot = d_make_root(iroot);
2110fd16957SHans de Goede 	if (!droot) {
2120fd16957SHans de Goede 		err = -ENOMEM;
2130fd16957SHans de Goede 		goto fail_unmap;
2140fd16957SHans de Goede 	}
2150fd16957SHans de Goede 
2160fd16957SHans de Goede 	sb->s_root = droot;
2170fd16957SHans de Goede 	sb->s_fs_info = sbi;
2180fd16957SHans de Goede 	return 0;
2190fd16957SHans de Goede 
2200fd16957SHans de Goede fail_unmap:
2210fd16957SHans de Goede 	vboxsf_unmap_folder(sbi->root);
2220fd16957SHans de Goede fail_free:
2230fd16957SHans de Goede 	if (sbi->bdi_id >= 0)
2240fd16957SHans de Goede 		ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id);
2250fd16957SHans de Goede 	if (sbi->nls)
2260fd16957SHans de Goede 		unload_nls(sbi->nls);
227*55fabde8SChristophe JAILLET fail_destroy_idr:
2280fd16957SHans de Goede 	idr_destroy(&sbi->ino_idr);
2290fd16957SHans de Goede 	kfree(sbi);
2300fd16957SHans de Goede 	return err;
2310fd16957SHans de Goede }
2320fd16957SHans de Goede 
vboxsf_inode_init_once(void * data)2330fd16957SHans de Goede static void vboxsf_inode_init_once(void *data)
2340fd16957SHans de Goede {
2350fd16957SHans de Goede 	struct vboxsf_inode *sf_i = data;
2360fd16957SHans de Goede 
2370fd16957SHans de Goede 	mutex_init(&sf_i->handle_list_mutex);
2380fd16957SHans de Goede 	inode_init_once(&sf_i->vfs_inode);
2390fd16957SHans de Goede }
2400fd16957SHans de Goede 
vboxsf_alloc_inode(struct super_block * sb)2410fd16957SHans de Goede static struct inode *vboxsf_alloc_inode(struct super_block *sb)
2420fd16957SHans de Goede {
2430fd16957SHans de Goede 	struct vboxsf_inode *sf_i;
2440fd16957SHans de Goede 
245fd60b288SMuchun Song 	sf_i = alloc_inode_sb(sb, vboxsf_inode_cachep, GFP_NOFS);
2460fd16957SHans de Goede 	if (!sf_i)
2470fd16957SHans de Goede 		return NULL;
2480fd16957SHans de Goede 
2490fd16957SHans de Goede 	sf_i->force_restat = 0;
2500fd16957SHans de Goede 	INIT_LIST_HEAD(&sf_i->handle_list);
2510fd16957SHans de Goede 
2520fd16957SHans de Goede 	return &sf_i->vfs_inode;
2530fd16957SHans de Goede }
2540fd16957SHans de Goede 
vboxsf_free_inode(struct inode * inode)2550fd16957SHans de Goede static void vboxsf_free_inode(struct inode *inode)
2560fd16957SHans de Goede {
2570fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
2580fd16957SHans de Goede 	unsigned long flags;
2590fd16957SHans de Goede 
2600fd16957SHans de Goede 	spin_lock_irqsave(&sbi->ino_idr_lock, flags);
2610fd16957SHans de Goede 	idr_remove(&sbi->ino_idr, inode->i_ino);
2620fd16957SHans de Goede 	spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
2630fd16957SHans de Goede 	kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode));
2640fd16957SHans de Goede }
2650fd16957SHans de Goede 
vboxsf_put_super(struct super_block * sb)2660fd16957SHans de Goede static void vboxsf_put_super(struct super_block *sb)
2670fd16957SHans de Goede {
2680fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
2690fd16957SHans de Goede 
2700fd16957SHans de Goede 	vboxsf_unmap_folder(sbi->root);
2710fd16957SHans de Goede 	if (sbi->bdi_id >= 0)
2720fd16957SHans de Goede 		ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id);
2730fd16957SHans de Goede 	if (sbi->nls)
2740fd16957SHans de Goede 		unload_nls(sbi->nls);
2750fd16957SHans de Goede 
2760fd16957SHans de Goede 	/*
2770fd16957SHans de Goede 	 * vboxsf_free_inode uses the idr, make sure all delayed rcu free
2780fd16957SHans de Goede 	 * inodes are flushed.
2790fd16957SHans de Goede 	 */
2800fd16957SHans de Goede 	rcu_barrier();
2810fd16957SHans de Goede 	idr_destroy(&sbi->ino_idr);
2820fd16957SHans de Goede 	kfree(sbi);
2830fd16957SHans de Goede }
2840fd16957SHans de Goede 
vboxsf_statfs(struct dentry * dentry,struct kstatfs * stat)2850fd16957SHans de Goede static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat)
2860fd16957SHans de Goede {
2870fd16957SHans de Goede 	struct super_block *sb = dentry->d_sb;
2880fd16957SHans de Goede 	struct shfl_volinfo shfl_volinfo;
2890fd16957SHans de Goede 	struct vboxsf_sbi *sbi;
2900fd16957SHans de Goede 	u32 buf_len;
2910fd16957SHans de Goede 	int err;
2920fd16957SHans de Goede 
2930fd16957SHans de Goede 	sbi = VBOXSF_SBI(sb);
2940fd16957SHans de Goede 	buf_len = sizeof(shfl_volinfo);
2950fd16957SHans de Goede 	err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
2960fd16957SHans de Goede 			    &buf_len, &shfl_volinfo);
2970fd16957SHans de Goede 	if (err)
2980fd16957SHans de Goede 		return err;
2990fd16957SHans de Goede 
3000fd16957SHans de Goede 	stat->f_type = VBOXSF_SUPER_MAGIC;
3010fd16957SHans de Goede 	stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit;
3020fd16957SHans de Goede 
3030fd16957SHans de Goede 	do_div(shfl_volinfo.total_allocation_bytes,
3040fd16957SHans de Goede 	       shfl_volinfo.bytes_per_allocation_unit);
3050fd16957SHans de Goede 	stat->f_blocks = shfl_volinfo.total_allocation_bytes;
3060fd16957SHans de Goede 
3070fd16957SHans de Goede 	do_div(shfl_volinfo.available_allocation_bytes,
3080fd16957SHans de Goede 	       shfl_volinfo.bytes_per_allocation_unit);
3090fd16957SHans de Goede 	stat->f_bfree  = shfl_volinfo.available_allocation_bytes;
3100fd16957SHans de Goede 	stat->f_bavail = shfl_volinfo.available_allocation_bytes;
3110fd16957SHans de Goede 
3120fd16957SHans de Goede 	stat->f_files = 1000;
3130fd16957SHans de Goede 	/*
3140fd16957SHans de Goede 	 * Don't return 0 here since the guest may then think that it is not
3150fd16957SHans de Goede 	 * possible to create any more files.
3160fd16957SHans de Goede 	 */
3170fd16957SHans de Goede 	stat->f_ffree = 1000000;
3180fd16957SHans de Goede 	stat->f_fsid.val[0] = 0;
3190fd16957SHans de Goede 	stat->f_fsid.val[1] = 0;
3200fd16957SHans de Goede 	stat->f_namelen = 255;
3210fd16957SHans de Goede 	return 0;
3220fd16957SHans de Goede }
3230fd16957SHans de Goede 
3240fd16957SHans de Goede static struct super_operations vboxsf_super_ops = {
3250fd16957SHans de Goede 	.alloc_inode	= vboxsf_alloc_inode,
3260fd16957SHans de Goede 	.free_inode	= vboxsf_free_inode,
3270fd16957SHans de Goede 	.put_super	= vboxsf_put_super,
3280fd16957SHans de Goede 	.statfs		= vboxsf_statfs,
3290fd16957SHans de Goede };
3300fd16957SHans de Goede 
vboxsf_setup(void)3310fd16957SHans de Goede static int vboxsf_setup(void)
3320fd16957SHans de Goede {
3330fd16957SHans de Goede 	int err;
3340fd16957SHans de Goede 
3350fd16957SHans de Goede 	mutex_lock(&vboxsf_setup_mutex);
3360fd16957SHans de Goede 
3370fd16957SHans de Goede 	if (vboxsf_setup_done)
3380fd16957SHans de Goede 		goto success;
3390fd16957SHans de Goede 
3400fd16957SHans de Goede 	vboxsf_inode_cachep =
3410fd16957SHans de Goede 		kmem_cache_create("vboxsf_inode_cache",
3420fd16957SHans de Goede 				  sizeof(struct vboxsf_inode), 0,
3430fd16957SHans de Goede 				  (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD |
3440fd16957SHans de Goede 				   SLAB_ACCOUNT),
3450fd16957SHans de Goede 				  vboxsf_inode_init_once);
3460fd16957SHans de Goede 	if (!vboxsf_inode_cachep) {
3470fd16957SHans de Goede 		err = -ENOMEM;
3480fd16957SHans de Goede 		goto fail_nomem;
3490fd16957SHans de Goede 	}
3500fd16957SHans de Goede 
3510fd16957SHans de Goede 	err = vboxsf_connect();
3520fd16957SHans de Goede 	if (err) {
3530fd16957SHans de Goede 		vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err);
3540fd16957SHans de Goede 		vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n");
3550fd16957SHans de Goede 		vbg_err("vboxsf: and check dmesg for vboxguest errors\n");
3560fd16957SHans de Goede 		goto fail_free_cache;
3570fd16957SHans de Goede 	}
3580fd16957SHans de Goede 
3590fd16957SHans de Goede 	err = vboxsf_set_utf8();
3600fd16957SHans de Goede 	if (err) {
3610fd16957SHans de Goede 		vbg_err("vboxsf_setutf8 error %d\n", err);
3620fd16957SHans de Goede 		goto fail_disconnect;
3630fd16957SHans de Goede 	}
3640fd16957SHans de Goede 
3650fd16957SHans de Goede 	if (!follow_symlinks) {
3660fd16957SHans de Goede 		err = vboxsf_set_symlinks();
3670fd16957SHans de Goede 		if (err)
3680fd16957SHans de Goede 			vbg_warn("vboxsf: Unable to show symlinks: %d\n", err);
3690fd16957SHans de Goede 	}
3700fd16957SHans de Goede 
3710fd16957SHans de Goede 	vboxsf_setup_done = true;
3720fd16957SHans de Goede success:
3730fd16957SHans de Goede 	mutex_unlock(&vboxsf_setup_mutex);
3740fd16957SHans de Goede 	return 0;
3750fd16957SHans de Goede 
3760fd16957SHans de Goede fail_disconnect:
3770fd16957SHans de Goede 	vboxsf_disconnect();
3780fd16957SHans de Goede fail_free_cache:
3790fd16957SHans de Goede 	kmem_cache_destroy(vboxsf_inode_cachep);
3800fd16957SHans de Goede fail_nomem:
3810fd16957SHans de Goede 	mutex_unlock(&vboxsf_setup_mutex);
3820fd16957SHans de Goede 	return err;
3830fd16957SHans de Goede }
3840fd16957SHans de Goede 
vboxsf_parse_monolithic(struct fs_context * fc,void * data)3850fd16957SHans de Goede static int vboxsf_parse_monolithic(struct fs_context *fc, void *data)
3860fd16957SHans de Goede {
3879b3b353eSLinus Torvalds 	if (data && !memcmp(data, VBSF_MOUNT_SIGNATURE, 4)) {
3880fd16957SHans de Goede 		vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n");
3890fd16957SHans de Goede 		return -EINVAL;
3900fd16957SHans de Goede 	}
3910fd16957SHans de Goede 
3920fd16957SHans de Goede 	return generic_parse_monolithic(fc, data);
3930fd16957SHans de Goede }
3940fd16957SHans de Goede 
vboxsf_get_tree(struct fs_context * fc)3950fd16957SHans de Goede static int vboxsf_get_tree(struct fs_context *fc)
3960fd16957SHans de Goede {
3970fd16957SHans de Goede 	int err;
3980fd16957SHans de Goede 
3990fd16957SHans de Goede 	err = vboxsf_setup();
4000fd16957SHans de Goede 	if (err)
4010fd16957SHans de Goede 		return err;
4020fd16957SHans de Goede 
4030fd16957SHans de Goede 	return get_tree_nodev(fc, vboxsf_fill_super);
4040fd16957SHans de Goede }
4050fd16957SHans de Goede 
vboxsf_reconfigure(struct fs_context * fc)4060fd16957SHans de Goede static int vboxsf_reconfigure(struct fs_context *fc)
4070fd16957SHans de Goede {
4080fd16957SHans de Goede 	struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb);
4090fd16957SHans de Goede 	struct vboxsf_fs_context *ctx = fc->fs_private;
4100fd16957SHans de Goede 	struct inode *iroot = fc->root->d_sb->s_root->d_inode;
4110fd16957SHans de Goede 
4120fd16957SHans de Goede 	/* Apply changed options to the root inode */
4130fd16957SHans de Goede 	sbi->o = ctx->o;
414e98f93e7SAl Viro 	vboxsf_init_inode(sbi, iroot, &sbi->root_info, true);
4150fd16957SHans de Goede 
4160fd16957SHans de Goede 	return 0;
4170fd16957SHans de Goede }
4180fd16957SHans de Goede 
vboxsf_free_fc(struct fs_context * fc)4190fd16957SHans de Goede static void vboxsf_free_fc(struct fs_context *fc)
4200fd16957SHans de Goede {
4210fd16957SHans de Goede 	struct vboxsf_fs_context *ctx = fc->fs_private;
4220fd16957SHans de Goede 
4230fd16957SHans de Goede 	kfree(ctx->nls_name);
4240fd16957SHans de Goede 	kfree(ctx);
4250fd16957SHans de Goede }
4260fd16957SHans de Goede 
4270fd16957SHans de Goede static const struct fs_context_operations vboxsf_context_ops = {
4280fd16957SHans de Goede 	.free			= vboxsf_free_fc,
4290fd16957SHans de Goede 	.parse_param		= vboxsf_parse_param,
4300fd16957SHans de Goede 	.parse_monolithic	= vboxsf_parse_monolithic,
4310fd16957SHans de Goede 	.get_tree		= vboxsf_get_tree,
4320fd16957SHans de Goede 	.reconfigure		= vboxsf_reconfigure,
4330fd16957SHans de Goede };
4340fd16957SHans de Goede 
vboxsf_init_fs_context(struct fs_context * fc)4350fd16957SHans de Goede static int vboxsf_init_fs_context(struct fs_context *fc)
4360fd16957SHans de Goede {
4370fd16957SHans de Goede 	struct vboxsf_fs_context *ctx;
4380fd16957SHans de Goede 
4390fd16957SHans de Goede 	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
4400fd16957SHans de Goede 	if (!ctx)
4410fd16957SHans de Goede 		return -ENOMEM;
4420fd16957SHans de Goede 
4430fd16957SHans de Goede 	current_uid_gid(&ctx->o.uid, &ctx->o.gid);
4440fd16957SHans de Goede 
4450fd16957SHans de Goede 	fc->fs_private = ctx;
4460fd16957SHans de Goede 	fc->ops = &vboxsf_context_ops;
4470fd16957SHans de Goede 	return 0;
4480fd16957SHans de Goede }
4490fd16957SHans de Goede 
4500fd16957SHans de Goede static struct file_system_type vboxsf_fs_type = {
4510fd16957SHans de Goede 	.owner			= THIS_MODULE,
4520fd16957SHans de Goede 	.name			= "vboxsf",
4530fd16957SHans de Goede 	.init_fs_context	= vboxsf_init_fs_context,
4540fd16957SHans de Goede 	.kill_sb		= kill_anon_super
4550fd16957SHans de Goede };
4560fd16957SHans de Goede 
4570fd16957SHans de Goede /* Module initialization/finalization handlers */
vboxsf_init(void)4580fd16957SHans de Goede static int __init vboxsf_init(void)
4590fd16957SHans de Goede {
4600fd16957SHans de Goede 	return register_filesystem(&vboxsf_fs_type);
4610fd16957SHans de Goede }
4620fd16957SHans de Goede 
vboxsf_fini(void)4630fd16957SHans de Goede static void __exit vboxsf_fini(void)
4640fd16957SHans de Goede {
4650fd16957SHans de Goede 	unregister_filesystem(&vboxsf_fs_type);
4660fd16957SHans de Goede 
4670fd16957SHans de Goede 	mutex_lock(&vboxsf_setup_mutex);
4680fd16957SHans de Goede 	if (vboxsf_setup_done) {
4690fd16957SHans de Goede 		vboxsf_disconnect();
4700fd16957SHans de Goede 		/*
4710fd16957SHans de Goede 		 * Make sure all delayed rcu free inodes are flushed
4720fd16957SHans de Goede 		 * before we destroy the cache.
4730fd16957SHans de Goede 		 */
4740fd16957SHans de Goede 		rcu_barrier();
4750fd16957SHans de Goede 		kmem_cache_destroy(vboxsf_inode_cachep);
4760fd16957SHans de Goede 	}
4770fd16957SHans de Goede 	mutex_unlock(&vboxsf_setup_mutex);
4780fd16957SHans de Goede }
4790fd16957SHans de Goede 
4800fd16957SHans de Goede module_init(vboxsf_init);
4810fd16957SHans de Goede module_exit(vboxsf_fini);
4820fd16957SHans de Goede 
4830fd16957SHans de Goede MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access");
4840fd16957SHans de Goede MODULE_AUTHOR("Oracle Corporation");
4850fd16957SHans de Goede MODULE_LICENSE("GPL v2");
4860fd16957SHans de Goede MODULE_ALIAS_FS("vboxsf");
487