1*4882a593Smuzhiyun // SPDX-License-Identifier: MIT
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * VirtualBox Guest Shared Folders support: Virtual File System.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Module initialization/finalization
6*4882a593Smuzhiyun * File system registration/deregistration
7*4882a593Smuzhiyun * Superblock reading
8*4882a593Smuzhiyun * Few utility functions
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Copyright (C) 2006-2018 Oracle Corporation
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/idr.h>
14*4882a593Smuzhiyun #include <linux/fs_parser.h>
15*4882a593Smuzhiyun #include <linux/magic.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/nls.h>
18*4882a593Smuzhiyun #include <linux/statfs.h>
19*4882a593Smuzhiyun #include <linux/vbox_utils.h>
20*4882a593Smuzhiyun #include "vfsmod.h"
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun #define VBOXSF_SUPER_MAGIC 0x786f4256 /* 'VBox' little endian */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun static const unsigned char VBSF_MOUNT_SIGNATURE[4] = "\000\377\376\375";
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun static int follow_symlinks;
27*4882a593Smuzhiyun module_param(follow_symlinks, int, 0444);
28*4882a593Smuzhiyun MODULE_PARM_DESC(follow_symlinks,
29*4882a593Smuzhiyun "Let host resolve symlinks rather than showing them");
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun static DEFINE_IDA(vboxsf_bdi_ida);
32*4882a593Smuzhiyun static DEFINE_MUTEX(vboxsf_setup_mutex);
33*4882a593Smuzhiyun static bool vboxsf_setup_done;
34*4882a593Smuzhiyun static struct super_operations vboxsf_super_ops; /* forward declaration */
35*4882a593Smuzhiyun static struct kmem_cache *vboxsf_inode_cachep;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static char * const vboxsf_default_nls = CONFIG_NLS_DEFAULT;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun enum { opt_nls, opt_uid, opt_gid, opt_ttl, opt_dmode, opt_fmode,
40*4882a593Smuzhiyun opt_dmask, opt_fmask };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static const struct fs_parameter_spec vboxsf_fs_parameters[] = {
43*4882a593Smuzhiyun fsparam_string ("nls", opt_nls),
44*4882a593Smuzhiyun fsparam_u32 ("uid", opt_uid),
45*4882a593Smuzhiyun fsparam_u32 ("gid", opt_gid),
46*4882a593Smuzhiyun fsparam_u32 ("ttl", opt_ttl),
47*4882a593Smuzhiyun fsparam_u32oct ("dmode", opt_dmode),
48*4882a593Smuzhiyun fsparam_u32oct ("fmode", opt_fmode),
49*4882a593Smuzhiyun fsparam_u32oct ("dmask", opt_dmask),
50*4882a593Smuzhiyun fsparam_u32oct ("fmask", opt_fmask),
51*4882a593Smuzhiyun {}
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun
vboxsf_parse_param(struct fs_context * fc,struct fs_parameter * param)54*4882a593Smuzhiyun static int vboxsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun struct vboxsf_fs_context *ctx = fc->fs_private;
57*4882a593Smuzhiyun struct fs_parse_result result;
58*4882a593Smuzhiyun kuid_t uid;
59*4882a593Smuzhiyun kgid_t gid;
60*4882a593Smuzhiyun int opt;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun opt = fs_parse(fc, vboxsf_fs_parameters, param, &result);
63*4882a593Smuzhiyun if (opt < 0)
64*4882a593Smuzhiyun return opt;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun switch (opt) {
67*4882a593Smuzhiyun case opt_nls:
68*4882a593Smuzhiyun if (ctx->nls_name || fc->purpose != FS_CONTEXT_FOR_MOUNT) {
69*4882a593Smuzhiyun vbg_err("vboxsf: Cannot reconfigure nls option\n");
70*4882a593Smuzhiyun return -EINVAL;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun ctx->nls_name = param->string;
73*4882a593Smuzhiyun param->string = NULL;
74*4882a593Smuzhiyun break;
75*4882a593Smuzhiyun case opt_uid:
76*4882a593Smuzhiyun uid = make_kuid(current_user_ns(), result.uint_32);
77*4882a593Smuzhiyun if (!uid_valid(uid))
78*4882a593Smuzhiyun return -EINVAL;
79*4882a593Smuzhiyun ctx->o.uid = uid;
80*4882a593Smuzhiyun break;
81*4882a593Smuzhiyun case opt_gid:
82*4882a593Smuzhiyun gid = make_kgid(current_user_ns(), result.uint_32);
83*4882a593Smuzhiyun if (!gid_valid(gid))
84*4882a593Smuzhiyun return -EINVAL;
85*4882a593Smuzhiyun ctx->o.gid = gid;
86*4882a593Smuzhiyun break;
87*4882a593Smuzhiyun case opt_ttl:
88*4882a593Smuzhiyun ctx->o.ttl = msecs_to_jiffies(result.uint_32);
89*4882a593Smuzhiyun break;
90*4882a593Smuzhiyun case opt_dmode:
91*4882a593Smuzhiyun if (result.uint_32 & ~0777)
92*4882a593Smuzhiyun return -EINVAL;
93*4882a593Smuzhiyun ctx->o.dmode = result.uint_32;
94*4882a593Smuzhiyun ctx->o.dmode_set = true;
95*4882a593Smuzhiyun break;
96*4882a593Smuzhiyun case opt_fmode:
97*4882a593Smuzhiyun if (result.uint_32 & ~0777)
98*4882a593Smuzhiyun return -EINVAL;
99*4882a593Smuzhiyun ctx->o.fmode = result.uint_32;
100*4882a593Smuzhiyun ctx->o.fmode_set = true;
101*4882a593Smuzhiyun break;
102*4882a593Smuzhiyun case opt_dmask:
103*4882a593Smuzhiyun if (result.uint_32 & ~07777)
104*4882a593Smuzhiyun return -EINVAL;
105*4882a593Smuzhiyun ctx->o.dmask = result.uint_32;
106*4882a593Smuzhiyun break;
107*4882a593Smuzhiyun case opt_fmask:
108*4882a593Smuzhiyun if (result.uint_32 & ~07777)
109*4882a593Smuzhiyun return -EINVAL;
110*4882a593Smuzhiyun ctx->o.fmask = result.uint_32;
111*4882a593Smuzhiyun break;
112*4882a593Smuzhiyun default:
113*4882a593Smuzhiyun return -EINVAL;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun return 0;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun
vboxsf_fill_super(struct super_block * sb,struct fs_context * fc)119*4882a593Smuzhiyun static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun struct vboxsf_fs_context *ctx = fc->fs_private;
122*4882a593Smuzhiyun struct shfl_string *folder_name, root_path;
123*4882a593Smuzhiyun struct vboxsf_sbi *sbi;
124*4882a593Smuzhiyun struct dentry *droot;
125*4882a593Smuzhiyun struct inode *iroot;
126*4882a593Smuzhiyun char *nls_name;
127*4882a593Smuzhiyun size_t size;
128*4882a593Smuzhiyun int err;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun if (!fc->source)
131*4882a593Smuzhiyun return -EINVAL;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
134*4882a593Smuzhiyun if (!sbi)
135*4882a593Smuzhiyun return -ENOMEM;
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun sbi->o = ctx->o;
138*4882a593Smuzhiyun idr_init(&sbi->ino_idr);
139*4882a593Smuzhiyun spin_lock_init(&sbi->ino_idr_lock);
140*4882a593Smuzhiyun sbi->next_generation = 1;
141*4882a593Smuzhiyun sbi->bdi_id = -1;
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /* Load nls if not utf8 */
144*4882a593Smuzhiyun nls_name = ctx->nls_name ? ctx->nls_name : vboxsf_default_nls;
145*4882a593Smuzhiyun if (strcmp(nls_name, "utf8") != 0) {
146*4882a593Smuzhiyun if (nls_name == vboxsf_default_nls)
147*4882a593Smuzhiyun sbi->nls = load_nls_default();
148*4882a593Smuzhiyun else
149*4882a593Smuzhiyun sbi->nls = load_nls(nls_name);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (!sbi->nls) {
152*4882a593Smuzhiyun vbg_err("vboxsf: Count not load '%s' nls\n", nls_name);
153*4882a593Smuzhiyun err = -EINVAL;
154*4882a593Smuzhiyun goto fail_free;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun sbi->bdi_id = ida_simple_get(&vboxsf_bdi_ida, 0, 0, GFP_KERNEL);
159*4882a593Smuzhiyun if (sbi->bdi_id < 0) {
160*4882a593Smuzhiyun err = sbi->bdi_id;
161*4882a593Smuzhiyun goto fail_free;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun err = super_setup_bdi_name(sb, "vboxsf-%d", sbi->bdi_id);
165*4882a593Smuzhiyun if (err)
166*4882a593Smuzhiyun goto fail_free;
167*4882a593Smuzhiyun sb->s_bdi->ra_pages = 0;
168*4882a593Smuzhiyun sb->s_bdi->io_pages = 0;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /* Turn source into a shfl_string and map the folder */
171*4882a593Smuzhiyun size = strlen(fc->source) + 1;
172*4882a593Smuzhiyun folder_name = kmalloc(SHFLSTRING_HEADER_SIZE + size, GFP_KERNEL);
173*4882a593Smuzhiyun if (!folder_name) {
174*4882a593Smuzhiyun err = -ENOMEM;
175*4882a593Smuzhiyun goto fail_free;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun folder_name->size = size;
178*4882a593Smuzhiyun folder_name->length = size - 1;
179*4882a593Smuzhiyun strlcpy(folder_name->string.utf8, fc->source, size);
180*4882a593Smuzhiyun err = vboxsf_map_folder(folder_name, &sbi->root);
181*4882a593Smuzhiyun kfree(folder_name);
182*4882a593Smuzhiyun if (err) {
183*4882a593Smuzhiyun vbg_err("vboxsf: Host rejected mount of '%s' with error %d\n",
184*4882a593Smuzhiyun fc->source, err);
185*4882a593Smuzhiyun goto fail_free;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun root_path.length = 1;
189*4882a593Smuzhiyun root_path.size = 2;
190*4882a593Smuzhiyun root_path.string.utf8[0] = '/';
191*4882a593Smuzhiyun root_path.string.utf8[1] = 0;
192*4882a593Smuzhiyun err = vboxsf_stat(sbi, &root_path, &sbi->root_info);
193*4882a593Smuzhiyun if (err)
194*4882a593Smuzhiyun goto fail_unmap;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun sb->s_magic = VBOXSF_SUPER_MAGIC;
197*4882a593Smuzhiyun sb->s_blocksize = 1024;
198*4882a593Smuzhiyun sb->s_maxbytes = MAX_LFS_FILESIZE;
199*4882a593Smuzhiyun sb->s_op = &vboxsf_super_ops;
200*4882a593Smuzhiyun sb->s_d_op = &vboxsf_dentry_ops;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun iroot = iget_locked(sb, 0);
203*4882a593Smuzhiyun if (!iroot) {
204*4882a593Smuzhiyun err = -ENOMEM;
205*4882a593Smuzhiyun goto fail_unmap;
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun vboxsf_init_inode(sbi, iroot, &sbi->root_info);
208*4882a593Smuzhiyun unlock_new_inode(iroot);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun droot = d_make_root(iroot);
211*4882a593Smuzhiyun if (!droot) {
212*4882a593Smuzhiyun err = -ENOMEM;
213*4882a593Smuzhiyun goto fail_unmap;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun sb->s_root = droot;
217*4882a593Smuzhiyun sb->s_fs_info = sbi;
218*4882a593Smuzhiyun return 0;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun fail_unmap:
221*4882a593Smuzhiyun vboxsf_unmap_folder(sbi->root);
222*4882a593Smuzhiyun fail_free:
223*4882a593Smuzhiyun if (sbi->bdi_id >= 0)
224*4882a593Smuzhiyun ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id);
225*4882a593Smuzhiyun if (sbi->nls)
226*4882a593Smuzhiyun unload_nls(sbi->nls);
227*4882a593Smuzhiyun idr_destroy(&sbi->ino_idr);
228*4882a593Smuzhiyun kfree(sbi);
229*4882a593Smuzhiyun return err;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
vboxsf_inode_init_once(void * data)232*4882a593Smuzhiyun static void vboxsf_inode_init_once(void *data)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun struct vboxsf_inode *sf_i = data;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun mutex_init(&sf_i->handle_list_mutex);
237*4882a593Smuzhiyun inode_init_once(&sf_i->vfs_inode);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
vboxsf_alloc_inode(struct super_block * sb)240*4882a593Smuzhiyun static struct inode *vboxsf_alloc_inode(struct super_block *sb)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun struct vboxsf_inode *sf_i;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun sf_i = kmem_cache_alloc(vboxsf_inode_cachep, GFP_NOFS);
245*4882a593Smuzhiyun if (!sf_i)
246*4882a593Smuzhiyun return NULL;
247*4882a593Smuzhiyun
248*4882a593Smuzhiyun sf_i->force_restat = 0;
249*4882a593Smuzhiyun INIT_LIST_HEAD(&sf_i->handle_list);
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun return &sf_i->vfs_inode;
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun
vboxsf_free_inode(struct inode * inode)254*4882a593Smuzhiyun static void vboxsf_free_inode(struct inode *inode)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun struct vboxsf_sbi *sbi = VBOXSF_SBI(inode->i_sb);
257*4882a593Smuzhiyun unsigned long flags;
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun spin_lock_irqsave(&sbi->ino_idr_lock, flags);
260*4882a593Smuzhiyun idr_remove(&sbi->ino_idr, inode->i_ino);
261*4882a593Smuzhiyun spin_unlock_irqrestore(&sbi->ino_idr_lock, flags);
262*4882a593Smuzhiyun kmem_cache_free(vboxsf_inode_cachep, VBOXSF_I(inode));
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
vboxsf_put_super(struct super_block * sb)265*4882a593Smuzhiyun static void vboxsf_put_super(struct super_block *sb)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun struct vboxsf_sbi *sbi = VBOXSF_SBI(sb);
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun vboxsf_unmap_folder(sbi->root);
270*4882a593Smuzhiyun if (sbi->bdi_id >= 0)
271*4882a593Smuzhiyun ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id);
272*4882a593Smuzhiyun if (sbi->nls)
273*4882a593Smuzhiyun unload_nls(sbi->nls);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun /*
276*4882a593Smuzhiyun * vboxsf_free_inode uses the idr, make sure all delayed rcu free
277*4882a593Smuzhiyun * inodes are flushed.
278*4882a593Smuzhiyun */
279*4882a593Smuzhiyun rcu_barrier();
280*4882a593Smuzhiyun idr_destroy(&sbi->ino_idr);
281*4882a593Smuzhiyun kfree(sbi);
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun
vboxsf_statfs(struct dentry * dentry,struct kstatfs * stat)284*4882a593Smuzhiyun static int vboxsf_statfs(struct dentry *dentry, struct kstatfs *stat)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun struct super_block *sb = dentry->d_sb;
287*4882a593Smuzhiyun struct shfl_volinfo shfl_volinfo;
288*4882a593Smuzhiyun struct vboxsf_sbi *sbi;
289*4882a593Smuzhiyun u32 buf_len;
290*4882a593Smuzhiyun int err;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun sbi = VBOXSF_SBI(sb);
293*4882a593Smuzhiyun buf_len = sizeof(shfl_volinfo);
294*4882a593Smuzhiyun err = vboxsf_fsinfo(sbi->root, 0, SHFL_INFO_GET | SHFL_INFO_VOLUME,
295*4882a593Smuzhiyun &buf_len, &shfl_volinfo);
296*4882a593Smuzhiyun if (err)
297*4882a593Smuzhiyun return err;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun stat->f_type = VBOXSF_SUPER_MAGIC;
300*4882a593Smuzhiyun stat->f_bsize = shfl_volinfo.bytes_per_allocation_unit;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun do_div(shfl_volinfo.total_allocation_bytes,
303*4882a593Smuzhiyun shfl_volinfo.bytes_per_allocation_unit);
304*4882a593Smuzhiyun stat->f_blocks = shfl_volinfo.total_allocation_bytes;
305*4882a593Smuzhiyun
306*4882a593Smuzhiyun do_div(shfl_volinfo.available_allocation_bytes,
307*4882a593Smuzhiyun shfl_volinfo.bytes_per_allocation_unit);
308*4882a593Smuzhiyun stat->f_bfree = shfl_volinfo.available_allocation_bytes;
309*4882a593Smuzhiyun stat->f_bavail = shfl_volinfo.available_allocation_bytes;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun stat->f_files = 1000;
312*4882a593Smuzhiyun /*
313*4882a593Smuzhiyun * Don't return 0 here since the guest may then think that it is not
314*4882a593Smuzhiyun * possible to create any more files.
315*4882a593Smuzhiyun */
316*4882a593Smuzhiyun stat->f_ffree = 1000000;
317*4882a593Smuzhiyun stat->f_fsid.val[0] = 0;
318*4882a593Smuzhiyun stat->f_fsid.val[1] = 0;
319*4882a593Smuzhiyun stat->f_namelen = 255;
320*4882a593Smuzhiyun return 0;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun static struct super_operations vboxsf_super_ops = {
324*4882a593Smuzhiyun .alloc_inode = vboxsf_alloc_inode,
325*4882a593Smuzhiyun .free_inode = vboxsf_free_inode,
326*4882a593Smuzhiyun .put_super = vboxsf_put_super,
327*4882a593Smuzhiyun .statfs = vboxsf_statfs,
328*4882a593Smuzhiyun };
329*4882a593Smuzhiyun
vboxsf_setup(void)330*4882a593Smuzhiyun static int vboxsf_setup(void)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun int err;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun mutex_lock(&vboxsf_setup_mutex);
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun if (vboxsf_setup_done)
337*4882a593Smuzhiyun goto success;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun vboxsf_inode_cachep =
340*4882a593Smuzhiyun kmem_cache_create("vboxsf_inode_cache",
341*4882a593Smuzhiyun sizeof(struct vboxsf_inode), 0,
342*4882a593Smuzhiyun (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD |
343*4882a593Smuzhiyun SLAB_ACCOUNT),
344*4882a593Smuzhiyun vboxsf_inode_init_once);
345*4882a593Smuzhiyun if (!vboxsf_inode_cachep) {
346*4882a593Smuzhiyun err = -ENOMEM;
347*4882a593Smuzhiyun goto fail_nomem;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun err = vboxsf_connect();
351*4882a593Smuzhiyun if (err) {
352*4882a593Smuzhiyun vbg_err("vboxsf: err %d connecting to guest PCI-device\n", err);
353*4882a593Smuzhiyun vbg_err("vboxsf: make sure you are inside a VirtualBox VM\n");
354*4882a593Smuzhiyun vbg_err("vboxsf: and check dmesg for vboxguest errors\n");
355*4882a593Smuzhiyun goto fail_free_cache;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun err = vboxsf_set_utf8();
359*4882a593Smuzhiyun if (err) {
360*4882a593Smuzhiyun vbg_err("vboxsf_setutf8 error %d\n", err);
361*4882a593Smuzhiyun goto fail_disconnect;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun if (!follow_symlinks) {
365*4882a593Smuzhiyun err = vboxsf_set_symlinks();
366*4882a593Smuzhiyun if (err)
367*4882a593Smuzhiyun vbg_warn("vboxsf: Unable to show symlinks: %d\n", err);
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun
370*4882a593Smuzhiyun vboxsf_setup_done = true;
371*4882a593Smuzhiyun success:
372*4882a593Smuzhiyun mutex_unlock(&vboxsf_setup_mutex);
373*4882a593Smuzhiyun return 0;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun fail_disconnect:
376*4882a593Smuzhiyun vboxsf_disconnect();
377*4882a593Smuzhiyun fail_free_cache:
378*4882a593Smuzhiyun kmem_cache_destroy(vboxsf_inode_cachep);
379*4882a593Smuzhiyun fail_nomem:
380*4882a593Smuzhiyun mutex_unlock(&vboxsf_setup_mutex);
381*4882a593Smuzhiyun return err;
382*4882a593Smuzhiyun }
383*4882a593Smuzhiyun
vboxsf_parse_monolithic(struct fs_context * fc,void * data)384*4882a593Smuzhiyun static int vboxsf_parse_monolithic(struct fs_context *fc, void *data)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun if (data && !memcmp(data, VBSF_MOUNT_SIGNATURE, 4)) {
387*4882a593Smuzhiyun vbg_err("vboxsf: Old binary mount data not supported, remove obsolete mount.vboxsf and/or update your VBoxService.\n");
388*4882a593Smuzhiyun return -EINVAL;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun return generic_parse_monolithic(fc, data);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
vboxsf_get_tree(struct fs_context * fc)394*4882a593Smuzhiyun static int vboxsf_get_tree(struct fs_context *fc)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun int err;
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun err = vboxsf_setup();
399*4882a593Smuzhiyun if (err)
400*4882a593Smuzhiyun return err;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun return get_tree_nodev(fc, vboxsf_fill_super);
403*4882a593Smuzhiyun }
404*4882a593Smuzhiyun
vboxsf_reconfigure(struct fs_context * fc)405*4882a593Smuzhiyun static int vboxsf_reconfigure(struct fs_context *fc)
406*4882a593Smuzhiyun {
407*4882a593Smuzhiyun struct vboxsf_sbi *sbi = VBOXSF_SBI(fc->root->d_sb);
408*4882a593Smuzhiyun struct vboxsf_fs_context *ctx = fc->fs_private;
409*4882a593Smuzhiyun struct inode *iroot = fc->root->d_sb->s_root->d_inode;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun /* Apply changed options to the root inode */
412*4882a593Smuzhiyun sbi->o = ctx->o;
413*4882a593Smuzhiyun vboxsf_init_inode(sbi, iroot, &sbi->root_info);
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun return 0;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
vboxsf_free_fc(struct fs_context * fc)418*4882a593Smuzhiyun static void vboxsf_free_fc(struct fs_context *fc)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun struct vboxsf_fs_context *ctx = fc->fs_private;
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun kfree(ctx->nls_name);
423*4882a593Smuzhiyun kfree(ctx);
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun static const struct fs_context_operations vboxsf_context_ops = {
427*4882a593Smuzhiyun .free = vboxsf_free_fc,
428*4882a593Smuzhiyun .parse_param = vboxsf_parse_param,
429*4882a593Smuzhiyun .parse_monolithic = vboxsf_parse_monolithic,
430*4882a593Smuzhiyun .get_tree = vboxsf_get_tree,
431*4882a593Smuzhiyun .reconfigure = vboxsf_reconfigure,
432*4882a593Smuzhiyun };
433*4882a593Smuzhiyun
vboxsf_init_fs_context(struct fs_context * fc)434*4882a593Smuzhiyun static int vboxsf_init_fs_context(struct fs_context *fc)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun struct vboxsf_fs_context *ctx;
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
439*4882a593Smuzhiyun if (!ctx)
440*4882a593Smuzhiyun return -ENOMEM;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun current_uid_gid(&ctx->o.uid, &ctx->o.gid);
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun fc->fs_private = ctx;
445*4882a593Smuzhiyun fc->ops = &vboxsf_context_ops;
446*4882a593Smuzhiyun return 0;
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun static struct file_system_type vboxsf_fs_type = {
450*4882a593Smuzhiyun .owner = THIS_MODULE,
451*4882a593Smuzhiyun .name = "vboxsf",
452*4882a593Smuzhiyun .init_fs_context = vboxsf_init_fs_context,
453*4882a593Smuzhiyun .kill_sb = kill_anon_super
454*4882a593Smuzhiyun };
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /* Module initialization/finalization handlers */
vboxsf_init(void)457*4882a593Smuzhiyun static int __init vboxsf_init(void)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun return register_filesystem(&vboxsf_fs_type);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
vboxsf_fini(void)462*4882a593Smuzhiyun static void __exit vboxsf_fini(void)
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun unregister_filesystem(&vboxsf_fs_type);
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun mutex_lock(&vboxsf_setup_mutex);
467*4882a593Smuzhiyun if (vboxsf_setup_done) {
468*4882a593Smuzhiyun vboxsf_disconnect();
469*4882a593Smuzhiyun /*
470*4882a593Smuzhiyun * Make sure all delayed rcu free inodes are flushed
471*4882a593Smuzhiyun * before we destroy the cache.
472*4882a593Smuzhiyun */
473*4882a593Smuzhiyun rcu_barrier();
474*4882a593Smuzhiyun kmem_cache_destroy(vboxsf_inode_cachep);
475*4882a593Smuzhiyun }
476*4882a593Smuzhiyun mutex_unlock(&vboxsf_setup_mutex);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun module_init(vboxsf_init);
480*4882a593Smuzhiyun module_exit(vboxsf_fini);
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun MODULE_DESCRIPTION("Oracle VM VirtualBox Module for Host File System Access");
483*4882a593Smuzhiyun MODULE_AUTHOR("Oracle Corporation");
484*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
485*4882a593Smuzhiyun MODULE_IMPORT_NS(ANDROID_GKI_VFS_EXPORT_ONLY);
486*4882a593Smuzhiyun MODULE_ALIAS_FS("vboxsf");
487