VirtualBox

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

Last change on this file since 64656 was 62527, checked in by vboxsync, 8 years ago

(C) 2016

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