VirtualBox

source: vbox/trunk/src/VBox/Additions/linux/sharedfolders/vfsmod.c@ 70836

Last change on this file since 70836 was 70801, checked in by vboxsync, 7 years ago

URL to vfs.txt was broken. Found current (hopefully enduring) location on github

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.2 KB
Line 
1/** @file
2 *
3 * vboxsf -- VirtualBox Guest Additions for Linux:
4 * Virtual File System for VirtualBox Shared Folders
5 *
6 * Module initialization/finalization
7 * File system registration/deregistration
8 * Superblock reading
9 * Few utility functions
10 */
11
12/*
13 * Copyright (C) 2006-2017 Oracle Corporation
14 *
15 * This file is part of VirtualBox Open Source Edition (OSE), as
16 * available from http://www.virtualbox.org. This file is free software;
17 * you can redistribute it and/or modify it under the terms of the GNU
18 * General Public License (GPL) as published by the Free Software
19 * Foundation, in version 2 as it comes in the "COPYING" file of the
20 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
21 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
22 */
23
24/**
25 * @note Anyone wishing to make changes here might wish to take a look at
26 * https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfs.txt
27 * which seems to be the closest there is to official documentation on
28 * writing filesystem drivers for Linux.
29 */
30
31#include "vfsmod.h"
32#include "version-generated.h"
33#include "revision-generated.h"
34#include "product-generated.h"
35#include "VBoxGuestR0LibInternal.h"
36
37MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
38MODULE_AUTHOR(VBOX_VENDOR);
39MODULE_LICENSE("GPL");
40#ifdef MODULE_ALIAS_FS
41MODULE_ALIAS_FS("vboxsf");
42#endif
43#ifdef MODULE_VERSION
44MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
45#endif
46
47/* globals */
48VBGLSFCLIENT client_handle;
49
50/* forward declarations */
51static struct super_operations sf_super_ops;
52
53/* allocate global info, try to map host share */
54static int sf_glob_alloc(struct vbsf_mount_info_new *info,
55 struct sf_glob_info **sf_gp)
56{
57 int err, rc;
58 SHFLSTRING *str_name;
59 size_t name_len, str_len;
60 struct sf_glob_info *sf_g;
61
62 TRACE();
63 sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
64 if (!sf_g) {
65 err = -ENOMEM;
66 LogRelFunc(("could not allocate memory for global info\n"));
67 goto fail0;
68 }
69
70 RT_ZERO(*sf_g);
71
72 if (info->nullchar != '\0'
73 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
74 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
75 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) {
76 err = -EINVAL;
77 goto fail1;
78 }
79
80 info->name[sizeof(info->name) - 1] = 0;
81 info->nls_name[sizeof(info->nls_name) - 1] = 0;
82
83 name_len = strlen(info->name);
84 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
85 str_name = kmalloc(str_len, GFP_KERNEL);
86 if (!str_name) {
87 err = -ENOMEM;
88 LogRelFunc(("could not allocate memory for host name\n"));
89 goto fail1;
90 }
91
92 str_name->u16Length = name_len;
93 str_name->u16Size = name_len + 1;
94 memcpy(str_name->String.utf8, info->name, name_len + 1);
95
96#define _IS_UTF8(_str) \
97 (strcmp(_str, "utf8") == 0)
98#define _IS_EMPTY(_str) \
99 (strcmp(_str, "") == 0)
100
101 /* Check if NLS charset is valid and not points to UTF8 table */
102 if (info->nls_name[0]) {
103 if (_IS_UTF8(info->nls_name))
104 sf_g->nls = NULL;
105 else {
106 sf_g->nls = load_nls(info->nls_name);
107 if (!sf_g->nls) {
108 err = -EINVAL;
109 LogFunc(("failed to load nls %s\n",
110 info->nls_name));
111 kfree(str_name);
112 goto fail1;
113 }
114 }
115 } else {
116#ifdef CONFIG_NLS_DEFAULT
117 /* If no NLS charset specified, try to load the default
118 * one if it's not points to UTF8. */
119 if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
120 && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
121 sf_g->nls = load_nls_default();
122 else
123 sf_g->nls = NULL;
124#else
125 sf_g->nls = NULL;
126#endif
127
128#undef _IS_UTF8
129#undef _IS_EMPTY
130 }
131
132 rc = VbglR0SfMapFolder(&client_handle, str_name, &sf_g->map);
133 kfree(str_name);
134
135 if (RT_FAILURE(rc)) {
136 err = -EPROTO;
137 LogFunc(("VbglR0SfMapFolder failed rc=%d\n", rc));
138 goto fail2;
139 }
140
141 sf_g->ttl = info->ttl;
142 sf_g->uid = info->uid;
143 sf_g->gid = info->gid;
144
145 if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new)) {
146 /* new fields */
147 sf_g->dmode = info->dmode;
148 sf_g->fmode = info->fmode;
149 sf_g->dmask = info->dmask;
150 sf_g->fmask = info->fmask;
151 } else {
152 sf_g->dmode = ~0;
153 sf_g->fmode = ~0;
154 }
155
156 *sf_gp = sf_g;
157 return 0;
158
159 fail2:
160 if (sf_g->nls)
161 unload_nls(sf_g->nls);
162
163 fail1:
164 kfree(sf_g);
165
166 fail0:
167 return err;
168}
169
170/* unmap the share and free global info [sf_g] */
171static void sf_glob_free(struct sf_glob_info *sf_g)
172{
173 int rc;
174
175 TRACE();
176 rc = VbglR0SfUnmapFolder(&client_handle, &sf_g->map);
177 if (RT_FAILURE(rc))
178 LogFunc(("VbglR0SfUnmapFolder failed rc=%d\n", rc));
179
180 if (sf_g->nls)
181 unload_nls(sf_g->nls);
182
183 kfree(sf_g);
184}
185
186/**
187 * This is called (by sf_read_super_[24|26] when vfs mounts the fs and
188 * wants to read super_block.
189 *
190 * calls [sf_glob_alloc] to map the folder and allocate global
191 * information structure.
192 *
193 * initializes [sb], initializes root inode and dentry.
194 *
195 * should respect [flags]
196 */
197static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
198{
199 int err;
200 struct dentry *droot;
201 struct inode *iroot;
202 struct sf_inode_info *sf_i;
203 struct sf_glob_info *sf_g;
204 SHFLFSOBJINFO fsinfo;
205 struct vbsf_mount_info_new *info;
206 bool fInodePut = true;
207
208 TRACE();
209 if (!data) {
210 LogFunc(("no mount info specified\n"));
211 return -EINVAL;
212 }
213
214 info = data;
215
216 if (flags & MS_REMOUNT) {
217 LogFunc(("remounting is not supported\n"));
218 return -ENOSYS;
219 }
220
221 err = sf_glob_alloc(info, &sf_g);
222 if (err)
223 goto fail0;
224
225 sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
226 if (!sf_i) {
227 err = -ENOMEM;
228 LogRelFunc(("could not allocate memory for root inode info\n"));
229 goto fail1;
230 }
231
232 sf_i->handle = SHFL_HANDLE_NIL;
233 sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
234 if (!sf_i->path) {
235 err = -ENOMEM;
236 LogRelFunc(("could not allocate memory for root inode path\n"));
237 goto fail2;
238 }
239
240 sf_i->path->u16Length = 1;
241 sf_i->path->u16Size = 2;
242 sf_i->path->String.utf8[0] = '/';
243 sf_i->path->String.utf8[1] = 0;
244 sf_i->force_reread = 0;
245
246 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
247 if (err) {
248 LogFunc(("could not stat root of share\n"));
249 goto fail3;
250 }
251
252 sb->s_magic = 0xface;
253 sb->s_blocksize = 1024;
254#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
255 /* Required for seek/sendfile.
256 *
257 * Must by less than or equal to INT64_MAX despite the fact that the
258 * declaration of this variable is unsigned long long. See determination
259 * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
260 * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
261 * page cache into account and is the suggested limit. */
262#if defined MAX_LFS_FILESIZE
263 sb->s_maxbytes = MAX_LFS_FILESIZE;
264#else
265 sb->s_maxbytes = 0x7fffffffffffffffULL;
266#endif
267#endif
268 sb->s_op = &sf_super_ops;
269
270#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
271 iroot = iget_locked(sb, 0);
272#else
273 iroot = iget(sb, 0);
274#endif
275 if (!iroot) {
276 err = -ENOMEM; /* XXX */
277 LogFunc(("could not get root inode\n"));
278 goto fail3;
279 }
280
281 if (sf_init_backing_dev(sf_g)) {
282 err = -EINVAL;
283 LogFunc(("could not init bdi\n"));
284#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
285 unlock_new_inode(iroot);
286#endif
287 goto fail4;
288 }
289
290 sf_init_inode(sf_g, iroot, &fsinfo);
291 SET_INODE_INFO(iroot, sf_i);
292
293#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
294 unlock_new_inode(iroot);
295#endif
296
297#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
298 droot = d_make_root(iroot);
299#else
300 droot = d_alloc_root(iroot);
301#endif
302 if (!droot) {
303 err = -ENOMEM; /* XXX */
304 LogFunc(("d_alloc_root failed\n"));
305#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
306 fInodePut = false;
307#endif
308 goto fail5;
309 }
310
311 sb->s_root = droot;
312 SET_GLOB_INFO(sb, sf_g);
313 return 0;
314
315 fail5:
316 sf_done_backing_dev(sf_g);
317
318 fail4:
319 if (fInodePut)
320 iput(iroot);
321
322 fail3:
323 kfree(sf_i->path);
324
325 fail2:
326 kfree(sf_i);
327
328 fail1:
329 sf_glob_free(sf_g);
330
331 fail0:
332 return err;
333}
334
335#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
336static struct super_block *sf_read_super_24(struct super_block *sb, void *data,
337 int flags)
338{
339 int err;
340
341 TRACE();
342 err = sf_read_super_aux(sb, data, flags);
343 if (err)
344 return NULL;
345
346 return sb;
347}
348#endif
349
350/* this is called when vfs is about to destroy the [inode]. all
351 resources associated with this [inode] must be cleared here */
352#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
353static void sf_clear_inode(struct inode *inode)
354{
355 struct sf_inode_info *sf_i;
356
357 TRACE();
358 sf_i = GET_INODE_INFO(inode);
359 if (!sf_i)
360 return;
361
362 BUG_ON(!sf_i->path);
363 kfree(sf_i->path);
364 kfree(sf_i);
365 SET_INODE_INFO(inode, NULL);
366}
367#else
368static void sf_evict_inode(struct inode *inode)
369{
370 struct sf_inode_info *sf_i;
371
372 TRACE();
373 truncate_inode_pages(&inode->i_data, 0);
374#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
375 clear_inode(inode);
376#else
377 end_writeback(inode);
378#endif
379
380 sf_i = GET_INODE_INFO(inode);
381 if (!sf_i)
382 return;
383
384 BUG_ON(!sf_i->path);
385 kfree(sf_i->path);
386 kfree(sf_i);
387 SET_INODE_INFO(inode, NULL);
388}
389#endif
390
391/* this is called by vfs when it wants to populate [inode] with data.
392 the only thing that is known about inode at this point is its index
393 hence we can't do anything here, and let lookup/whatever with the
394 job to properly fill then [inode] */
395#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
396static void sf_read_inode(struct inode *inode)
397{
398}
399#endif
400
401/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
402 the folder and free [sf_g] */
403static void sf_put_super(struct super_block *sb)
404{
405 struct sf_glob_info *sf_g;
406
407 sf_g = GET_GLOB_INFO(sb);
408 BUG_ON(!sf_g);
409 sf_done_backing_dev(sf_g);
410 sf_glob_free(sf_g);
411}
412
413#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
414static int sf_statfs(struct super_block *sb, STRUCT_STATFS * stat)
415{
416 return sf_get_volume_info(sb, stat);
417}
418#else
419static int sf_statfs(struct dentry *dentry, STRUCT_STATFS * stat)
420{
421 struct super_block *sb = dentry->d_inode->i_sb;
422 return sf_get_volume_info(sb, stat);
423}
424#endif
425
426static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
427{
428#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
429 struct sf_glob_info *sf_g;
430 struct sf_inode_info *sf_i;
431 struct inode *iroot;
432 SHFLFSOBJINFO fsinfo;
433 int err;
434
435 sf_g = GET_GLOB_INFO(sb);
436 BUG_ON(!sf_g);
437 if (data && data[0] != 0) {
438 struct vbsf_mount_info_new *info =
439 (struct vbsf_mount_info_new *)data;
440 if (info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
441 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
442 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
443 sf_g->uid = info->uid;
444 sf_g->gid = info->gid;
445 sf_g->ttl = info->ttl;
446 sf_g->dmode = info->dmode;
447 sf_g->fmode = info->fmode;
448 sf_g->dmask = info->dmask;
449 sf_g->fmask = info->fmask;
450 }
451 }
452
453 iroot = ilookup(sb, 0);
454 if (!iroot)
455 return -ENOSYS;
456
457 sf_i = GET_INODE_INFO(iroot);
458 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
459 BUG_ON(err != 0);
460 sf_init_inode(sf_g, iroot, &fsinfo);
461 /*unlock_new_inode(iroot); */
462 return 0;
463#else
464 return -ENOSYS;
465#endif
466}
467
468static struct super_operations sf_super_ops = {
469#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
470 .clear_inode = sf_clear_inode,
471#else
472 .evict_inode = sf_evict_inode,
473#endif
474#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
475 .read_inode = sf_read_inode,
476#endif
477 .put_super = sf_put_super,
478 .statfs = sf_statfs,
479 .remount_fs = sf_remount_fs
480};
481
482#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
483static DECLARE_FSTYPE(vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
484#else
485static int sf_read_super_26(struct super_block *sb, void *data, int flags)
486{
487 int err;
488
489 TRACE();
490 err = sf_read_super_aux(sb, data, flags);
491 if (err)
492 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
493
494 return err;
495}
496
497#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
498static struct super_block *sf_get_sb(struct file_system_type *fs_type,
499 int flags, const char *dev_name,
500 void *data)
501{
502 TRACE();
503 return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
504}
505#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
506static int sf_get_sb(struct file_system_type *fs_type, int flags,
507 const char *dev_name, void *data, struct vfsmount *mnt)
508{
509 TRACE();
510 return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
511}
512#else
513static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
514 const char *dev_name, void *data)
515{
516 TRACE();
517 return mount_nodev(fs_type, flags, data, sf_read_super_26);
518}
519#endif
520
521static struct file_system_type vboxsf_fs_type = {
522 .owner = THIS_MODULE,
523 .name = "vboxsf",
524#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
525 .get_sb = sf_get_sb,
526#else
527 .mount = sf_mount,
528#endif
529 .kill_sb = kill_anon_super
530};
531#endif
532
533#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
534static int follow_symlinks = 0;
535module_param(follow_symlinks, int, 0);
536MODULE_PARM_DESC(follow_symlinks,
537 "Let host resolve symlinks rather than showing them");
538#endif
539
540/* Module initialization/finalization handlers */
541static int __init init(void)
542{
543 int rcVBox;
544 int rcRet = 0;
545 int err;
546
547 TRACE();
548
549 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
550 printk(KERN_ERR
551 "Mount information structure is too large %lu\n"
552 "Must be less than or equal to %lu\n",
553 (unsigned long)sizeof(struct vbsf_mount_info_new),
554 (unsigned long)PAGE_SIZE);
555 return -EINVAL;
556 }
557
558 err = register_filesystem(&vboxsf_fs_type);
559 if (err) {
560 LogFunc(("register_filesystem err=%d\n", err));
561 return err;
562 }
563
564 rcVBox = VbglR0HGCMInit();
565 if (RT_FAILURE(rcVBox)) {
566 LogRelFunc(("VbglR0HGCMInit failed, rc=%d\n", rcVBox));
567 rcRet = -EPROTO;
568 goto fail0;
569 }
570
571 rcVBox = VbglR0SfConnect(&client_handle);
572 if (RT_FAILURE(rcVBox)) {
573 LogRelFunc(("VbglR0SfConnect failed, rc=%d\n", rcVBox));
574 rcRet = -EPROTO;
575 goto fail1;
576 }
577
578 rcVBox = VbglR0SfSetUtf8(&client_handle);
579 if (RT_FAILURE(rcVBox)) {
580 LogRelFunc(("VbglR0SfSetUtf8 failed, rc=%d\n", rcVBox));
581 rcRet = -EPROTO;
582 goto fail2;
583 }
584#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
585 if (!follow_symlinks) {
586 rcVBox = VbglR0SfSetSymlinks(&client_handle);
587 if (RT_FAILURE(rcVBox)) {
588 printk(KERN_WARNING
589 "vboxsf: Host unable to show symlinks, rc=%d\n",
590 rcVBox);
591 }
592 }
593#endif
594
595 printk(KERN_DEBUG
596 "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
597 " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
598
599 return 0;
600
601 fail2:
602 VbglR0SfDisconnect(&client_handle);
603
604 fail1:
605 VbglR0HGCMTerminate();
606
607 fail0:
608 unregister_filesystem(&vboxsf_fs_type);
609 return rcRet;
610}
611
612static void __exit fini(void)
613{
614 TRACE();
615
616 VbglR0SfDisconnect(&client_handle);
617 VbglR0HGCMTerminate();
618 unregister_filesystem(&vboxsf_fs_type);
619}
620
621module_init(init);
622module_exit(fini);
623
624/* C++ hack */
625int __gxx_personality_v0 = 0xdeadbeef;
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette