VirtualBox

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

Last change on this file since 69564 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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

© 2023 Oracle
ContactPrivacy policyTerms of Use