VirtualBox

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

Last change on this file since 77138 was 77138, checked in by vboxsync, 6 years ago

linux/vboxsf: More read code tweaking, making the max read/write buffer size configurable (mount option maxiopages). Also added code for dealing with the host running out of heap. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.0 KB
Line 
1/* $Id: vfsmod.c 77138 2019-02-01 19:00:23Z vboxsync $ */
2/** @file
3 * vboxsf - VBox Linux Shared Folders VFS, module init/term, super block management.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/**
32 * @note Anyone wishing to make changes here might wish to take a look at
33 * https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfs.txt
34 * which seems to be the closest there is to official documentation on
35 * writing filesystem drivers for Linux.
36 */
37
38#include "vfsmod.h"
39#include "version-generated.h"
40#include "revision-generated.h"
41#include "product-generated.h"
42#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
43# include <linux/mount.h>
44#endif
45#include <linux/seq_file.h>
46#include <iprt/path.h>
47
48MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
49MODULE_AUTHOR(VBOX_VENDOR);
50MODULE_LICENSE("GPL and additional rights");
51#ifdef MODULE_ALIAS_FS
52MODULE_ALIAS_FS("vboxsf");
53#endif
54#ifdef MODULE_VERSION
55MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
56#endif
57
58/* globals */
59VBGLSFCLIENT client_handle;
60VBGLSFCLIENT g_SfClient; /* temporary? */
61uint32_t g_fHostFeatures = 0; /* temporary? */
62
63/* forward declarations */
64static struct super_operations sf_super_ops;
65
66/**
67 * Copies options from the mount info structure into @a sf_g.
68 *
69 * This is used both by sf_glob_alloc() and sf_remount_fs().
70 */
71static void sf_glob_copy_remount_options(struct sf_glob_info *sf_g, struct vbsf_mount_info_new *info)
72{
73 sf_g->ttl = info->ttl;
74 sf_g->uid = info->uid;
75 sf_g->gid = info->gid;
76
77 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, tag)) {
78 /* new fields */
79 sf_g->dmode = info->dmode;
80 sf_g->fmode = info->fmode;
81 sf_g->dmask = info->dmask;
82 sf_g->fmask = info->fmask;
83 } else {
84 sf_g->dmode = ~0;
85 sf_g->fmode = ~0;
86 }
87
88 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cMaxIoPages)) {
89 AssertCompile(sizeof(sf_g->tag) >= sizeof(info->tag));
90 memcpy(sf_g->tag, info->tag, sizeof(info->tag));
91 sf_g->tag[sizeof(sf_g->tag) - 1] = '\0';
92 } else {
93 sf_g->tag[0] = '\0';
94 }
95
96 /* The max number of pages in an I/O request. This must take into
97 account that the physical heap generally grows in 64 KB chunks,
98 so we should not try push that limit. It also needs to take
99 into account that the host will allocate temporary heap buffers
100 for the I/O bytes we send/receive, so don't push the host heap
101 too hard as we'd have to retry with smaller requests when this
102 happens, which isn't too efficient. */
103 sf_g->cMaxIoPages = RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */,
104 VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT);
105 if ( (unsigned)info->length >= sizeof(struct vbsf_mount_info_new)
106 && info->cMaxIoPages != 0) {
107 if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
108 sf_g->cMaxIoPages = info->cMaxIoPages;
109 else
110 printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n",
111 info->cMaxIoPages, sf_g->cMaxIoPages);
112 }
113}
114
115/* allocate global info, try to map host share */
116static int sf_glob_alloc(struct vbsf_mount_info_new *info,
117 struct sf_glob_info **sf_gp)
118{
119 int err, rc;
120 SHFLSTRING *str_name;
121 size_t name_len, str_len;
122 struct sf_glob_info *sf_g;
123
124 TRACE();
125 sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
126 if (!sf_g) {
127 err = -ENOMEM;
128 LogRelFunc(("could not allocate memory for global info\n"));
129 goto fail0;
130 }
131
132 RT_ZERO(*sf_g);
133
134 if (info->nullchar != '\0'
135 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
136 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
137 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) {
138 err = -EINVAL;
139 goto fail1;
140 }
141
142 info->name[sizeof(info->name) - 1] = 0;
143 info->nls_name[sizeof(info->nls_name) - 1] = 0;
144
145 name_len = strlen(info->name);
146 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
147 str_name = kmalloc(str_len, GFP_KERNEL);
148 if (!str_name) {
149 err = -ENOMEM;
150 LogRelFunc(("could not allocate memory for host name\n"));
151 goto fail1;
152 }
153
154 str_name->u16Length = name_len;
155 str_name->u16Size = name_len + 1;
156 memcpy(str_name->String.utf8, info->name, name_len + 1);
157
158#define _IS_UTF8(_str) (strcmp(_str, "utf8") == 0)
159#define _IS_EMPTY(_str) (strcmp(_str, "") == 0)
160
161 /* Check if NLS charset is valid and not points to UTF8 table */
162 if (info->nls_name[0]) {
163 if (_IS_UTF8(info->nls_name))
164 sf_g->nls = NULL;
165 else {
166 sf_g->nls = load_nls(info->nls_name);
167 if (!sf_g->nls) {
168 err = -EINVAL;
169 LogFunc(("failed to load nls %s\n",
170 info->nls_name));
171 kfree(str_name);
172 goto fail1;
173 }
174 }
175 } else {
176#ifdef CONFIG_NLS_DEFAULT
177 /* If no NLS charset specified, try to load the default
178 * one if it's not points to UTF8. */
179 if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
180 && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
181 sf_g->nls = load_nls_default();
182 else
183 sf_g->nls = NULL;
184#else
185 sf_g->nls = NULL;
186#endif
187 }
188
189#undef _IS_UTF8
190#undef _IS_EMPTY
191
192#ifdef VBOXSF_USE_DEPRECATED_VBGL_INTERFACE
193 rc = VbglR0SfMapFolder(&client_handle, str_name, &sf_g->map);
194#else
195 rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER,
196 true /*fCaseSensitive*/, &sf_g->map.root);
197#endif
198 kfree(str_name);
199
200 if (RT_FAILURE(rc)) {
201 err = -EPROTO;
202 LogFunc(("SHFL_FN_MAP_FOLDER failed rc=%Rrc\n", rc));
203 goto fail2;
204 }
205
206 /* The rest is shared with remount. */
207 sf_glob_copy_remount_options(sf_g, info);
208
209 *sf_gp = sf_g;
210 return 0;
211
212 fail2:
213 if (sf_g->nls)
214 unload_nls(sf_g->nls);
215
216 fail1:
217 kfree(sf_g);
218
219 fail0:
220 return err;
221}
222
223/* unmap the share and free global info [sf_g] */
224static void sf_glob_free(struct sf_glob_info *sf_g)
225{
226 int rc;
227
228 TRACE();
229#ifdef VBOXSF_USE_DEPRECATED_VBGL_INTERFACE
230 rc = VbglR0SfUnmapFolder(&client_handle, &sf_g->map);
231 if (RT_FAILURE(rc))
232 LogFunc(("VbglR0SfUnmapFolder failed rc=%d\n", rc));
233#else
234 rc = VbglR0SfHostReqUnmapFolderSimple(sf_g->map.root);
235 if (RT_FAILURE(rc))
236 LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc));
237#endif
238
239 if (sf_g->nls)
240 unload_nls(sf_g->nls);
241
242 kfree(sf_g);
243}
244
245/**
246 * This is called (by sf_read_super_[24|26] when vfs mounts the fs and
247 * wants to read super_block.
248 *
249 * calls [sf_glob_alloc] to map the folder and allocate global
250 * information structure.
251 *
252 * initializes [sb], initializes root inode and dentry.
253 *
254 * should respect [flags]
255 */
256static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
257{
258 int err;
259 struct dentry *droot;
260 struct inode *iroot;
261 struct sf_inode_info *sf_i;
262 struct sf_glob_info *sf_g;
263 SHFLFSOBJINFO fsinfo;
264 struct vbsf_mount_info_new *info;
265 bool fInodePut = true;
266
267 TRACE();
268 if (!data) {
269 LogFunc(("no mount info specified\n"));
270 return -EINVAL;
271 }
272
273 info = data;
274
275 if (flags & MS_REMOUNT) {
276 LogFunc(("remounting is not supported\n"));
277 return -ENOSYS;
278 }
279
280 err = sf_glob_alloc(info, &sf_g);
281 if (err)
282 goto fail0;
283
284 sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
285 if (!sf_i) {
286 err = -ENOMEM;
287 LogRelFunc(("could not allocate memory for root inode info\n"));
288 goto fail1;
289 }
290
291 sf_i->handle = SHFL_HANDLE_NIL;
292 sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
293 if (!sf_i->path) {
294 err = -ENOMEM;
295 LogRelFunc(("could not allocate memory for root inode path\n"));
296 goto fail2;
297 }
298
299 sf_i->path->u16Length = 1;
300 sf_i->path->u16Size = 2;
301 sf_i->path->String.utf8[0] = '/';
302 sf_i->path->String.utf8[1] = 0;
303 sf_i->force_reread = 0;
304
305 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
306 if (err) {
307 LogFunc(("could not stat root of share\n"));
308 goto fail3;
309 }
310
311 sb->s_magic = 0xface;
312 sb->s_blocksize = 1024;
313#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
314 /* Required for seek/sendfile.
315 *
316 * Must by less than or equal to INT64_MAX despite the fact that the
317 * declaration of this variable is unsigned long long. See determination
318 * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
319 * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
320 * page cache into account and is the suggested limit. */
321# if defined MAX_LFS_FILESIZE
322 sb->s_maxbytes = MAX_LFS_FILESIZE;
323# else
324 sb->s_maxbytes = 0x7fffffffffffffffULL;
325# endif
326#endif
327 sb->s_op = &sf_super_ops;
328
329#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
330 iroot = iget_locked(sb, 0);
331#else
332 iroot = iget(sb, 0);
333#endif
334 if (!iroot) {
335 err = -ENOMEM; /* XXX */
336 LogFunc(("could not get root inode\n"));
337 goto fail3;
338 }
339
340 if (sf_init_backing_dev(sf_g)) {
341 err = -EINVAL;
342 LogFunc(("could not init bdi\n"));
343#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
344 unlock_new_inode(iroot);
345#endif
346 goto fail4;
347 }
348
349 sf_init_inode(sf_g, iroot, &fsinfo);
350 SET_INODE_INFO(iroot, sf_i);
351
352#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
353 unlock_new_inode(iroot);
354#endif
355
356#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
357 droot = d_make_root(iroot);
358#else
359 droot = d_alloc_root(iroot);
360#endif
361 if (!droot) {
362 err = -ENOMEM; /* XXX */
363 LogFunc(("d_alloc_root failed\n"));
364#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
365 fInodePut = false;
366#endif
367 goto fail5;
368 }
369
370 sb->s_root = droot;
371 SET_GLOB_INFO(sb, sf_g);
372 return 0;
373
374 fail5:
375 sf_done_backing_dev(sf_g);
376
377 fail4:
378 if (fInodePut)
379 iput(iroot);
380
381 fail3:
382 kfree(sf_i->path);
383
384 fail2:
385 kfree(sf_i);
386
387 fail1:
388 sf_glob_free(sf_g);
389
390 fail0:
391 return err;
392}
393
394#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
395static struct super_block *sf_read_super_24(struct super_block *sb, void *data,
396 int flags)
397{
398 int err;
399
400 TRACE();
401 err = sf_read_super_aux(sb, data, flags);
402 if (err)
403 return NULL;
404
405 return sb;
406}
407#endif
408
409/* this is called when vfs is about to destroy the [inode]. all
410 resources associated with this [inode] must be cleared here */
411#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
412static void sf_clear_inode(struct inode *inode)
413{
414 struct sf_inode_info *sf_i;
415
416 TRACE();
417 sf_i = GET_INODE_INFO(inode);
418 if (!sf_i)
419 return;
420
421 BUG_ON(!sf_i->path);
422 kfree(sf_i->path);
423 kfree(sf_i);
424 SET_INODE_INFO(inode, NULL);
425}
426#else /* LINUX_VERSION_CODE >= 2.6.36 */
427static void sf_evict_inode(struct inode *inode)
428{
429 struct sf_inode_info *sf_i;
430
431 TRACE();
432 truncate_inode_pages(&inode->i_data, 0);
433# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
434 clear_inode(inode);
435# else
436 end_writeback(inode);
437# endif
438
439 sf_i = GET_INODE_INFO(inode);
440 if (!sf_i)
441 return;
442
443 BUG_ON(!sf_i->path);
444 kfree(sf_i->path);
445 kfree(sf_i);
446 SET_INODE_INFO(inode, NULL);
447}
448#endif /* LINUX_VERSION_CODE >= 2.6.36 */
449
450/* this is called by vfs when it wants to populate [inode] with data.
451 the only thing that is known about inode at this point is its index
452 hence we can't do anything here, and let lookup/whatever with the
453 job to properly fill then [inode] */
454#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
455static void sf_read_inode(struct inode *inode)
456{
457}
458#endif
459
460/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
461 the folder and free [sf_g] */
462static void sf_put_super(struct super_block *sb)
463{
464 struct sf_glob_info *sf_g;
465
466 sf_g = GET_GLOB_INFO(sb);
467 BUG_ON(!sf_g);
468 sf_done_backing_dev(sf_g);
469 sf_glob_free(sf_g);
470}
471
472#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
473static int sf_statfs(struct super_block *sb, STRUCT_STATFS * stat)
474{
475 return sf_get_volume_info(sb, stat);
476}
477#else
478static int sf_statfs(struct dentry *dentry, STRUCT_STATFS * stat)
479{
480 struct super_block *sb = dentry->d_inode->i_sb;
481 return sf_get_volume_info(sb, stat);
482}
483#endif
484
485static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
486{
487#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
488 struct sf_glob_info *sf_g;
489 struct sf_inode_info *sf_i;
490 struct inode *iroot;
491 SHFLFSOBJINFO fsinfo;
492 int err;
493
494 sf_g = GET_GLOB_INFO(sb);
495 BUG_ON(!sf_g);
496 if (data && data[0] != 0) {
497 struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
498 if ( info->nullchar == '\0'
499 && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
500 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
501 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
502 sf_glob_copy_remount_options(sf_g, info);
503 }
504 }
505
506 iroot = ilookup(sb, 0);
507 if (!iroot)
508 return -ENOSYS;
509
510 sf_i = GET_INODE_INFO(iroot);
511 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
512 BUG_ON(err != 0);
513 sf_init_inode(sf_g, iroot, &fsinfo);
514 /*unlock_new_inode(iroot); */
515 return 0;
516#else /* LINUX_VERSION_CODE < 2.4.23 */
517 return -ENOSYS;
518#endif /* LINUX_VERSION_CODE < 2.4.23 */
519}
520
521/** Show mount options. */
522#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
523static int sf_show_options(struct seq_file *m, struct vfsmount *mnt)
524#else
525static int sf_show_options(struct seq_file *m, struct dentry *root)
526#endif
527{
528#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
529 struct super_block *sb = mnt->mnt_sb;
530#else
531 struct super_block *sb = root->d_sb;
532#endif
533 struct sf_glob_info *sf_g = GET_GLOB_INFO(sb);
534 if (sf_g) {
535 seq_printf(m, ",uid=%u,gid=%u,ttl=%u,dmode=0%o,fmode=0%o,dmask=0%o,fmask=0%o,maxiopages=%u",
536 sf_g->uid, sf_g->gid, sf_g->ttl, sf_g->dmode, sf_g->fmode, sf_g->dmask,
537 sf_g->fmask, sf_g->cMaxIoPages);
538 if (sf_g->tag[0] != '\0') {
539 seq_puts(m, ",tag=");
540 seq_escape(m, sf_g->tag, " \t\n\\");
541 }
542 }
543
544 return 0;
545}
546
547static struct super_operations sf_super_ops = {
548#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
549 .clear_inode = sf_clear_inode,
550#else
551 .evict_inode = sf_evict_inode,
552#endif
553#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
554 .read_inode = sf_read_inode,
555#endif
556 .put_super = sf_put_super,
557 .statfs = sf_statfs,
558 .remount_fs = sf_remount_fs,
559 .show_options = sf_show_options
560};
561
562#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
563static DECLARE_FSTYPE(vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
564#else
565static int sf_read_super_26(struct super_block *sb, void *data, int flags)
566{
567 int err;
568
569 TRACE();
570 err = sf_read_super_aux(sb, data, flags);
571 if (err)
572 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
573
574 return err;
575}
576
577# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
578static struct super_block *sf_get_sb(struct file_system_type *fs_type,
579 int flags, const char *dev_name,
580 void *data)
581{
582 TRACE();
583 return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
584}
585# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
586static int sf_get_sb(struct file_system_type *fs_type, int flags,
587 const char *dev_name, void *data, struct vfsmount *mnt)
588{
589 TRACE();
590 return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
591}
592# else /* LINUX_VERSION_CODE >= 2.6.39 */
593static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
594 const char *dev_name, void *data)
595{
596 TRACE();
597 return mount_nodev(fs_type, flags, data, sf_read_super_26);
598}
599# endif /* LINUX_VERSION_CODE >= 2.6.39 */
600
601static struct file_system_type vboxsf_fs_type = {
602 .owner = THIS_MODULE,
603 .name = "vboxsf",
604# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
605 .get_sb = sf_get_sb,
606# else
607 .mount = sf_mount,
608# endif
609 .kill_sb = kill_anon_super
610};
611
612#endif /* LINUX_VERSION_CODE >= 2.6.0 */
613
614#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
615static int follow_symlinks = 0;
616module_param(follow_symlinks, int, 0);
617MODULE_PARM_DESC(follow_symlinks,
618 "Let host resolve symlinks rather than showing them");
619#endif
620
621/* Module initialization/finalization handlers */
622static int __init init(void)
623{
624 int vrc;
625 int rcRet = 0;
626 int err;
627
628 TRACE();
629
630 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
631 printk(KERN_ERR
632 "Mount information structure is too large %lu\n"
633 "Must be less than or equal to %lu\n",
634 (unsigned long)sizeof(struct vbsf_mount_info_new),
635 (unsigned long)PAGE_SIZE);
636 return -EINVAL;
637 }
638
639 err = register_filesystem(&vboxsf_fs_type);
640 if (err) {
641 LogFunc(("register_filesystem err=%d\n", err));
642 return err;
643 }
644
645 vrc = VbglR0SfInit();
646 if (RT_FAILURE(vrc)) {
647 LogRelFunc(("VbglR0SfInit failed, vrc=%Rrc\n", vrc));
648 rcRet = -EPROTO;
649 goto fail0;
650 }
651
652 vrc = VbglR0SfConnect(&client_handle);
653 g_SfClient = client_handle; /* temporary */
654 if (RT_FAILURE(vrc)) {
655 LogRelFunc(("VbglR0SfConnect failed, vrc=%Rrc\n", vrc));
656 rcRet = -EPROTO;
657 goto fail1;
658 }
659
660 vrc = VbglR0QueryHostFeatures(&g_fHostFeatures);
661 if (RT_FAILURE(vrc))
662 {
663 LogRelFunc(("VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc));
664 g_fHostFeatures = 0;
665 }
666 LogRelFunc(("g_fHostFeatures=%#x\n", g_fHostFeatures));
667
668 vrc = VbglR0SfSetUtf8(&client_handle);
669 if (RT_FAILURE(vrc)) {
670 LogRelFunc(("VbglR0SfSetUtf8 failed, vrc=%Rrc\n", vrc));
671 rcRet = -EPROTO;
672 goto fail2;
673 }
674#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
675 if (!follow_symlinks) {
676 vrc = VbglR0SfSetSymlinks(&client_handle);
677 if (RT_FAILURE(vrc)) {
678 printk(KERN_WARNING
679 "vboxsf: Host unable to show symlinks, vrc=%d\n",
680 vrc);
681 }
682 }
683#endif
684
685 printk(KERN_DEBUG
686 "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
687 " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
688
689 return 0;
690
691 fail2:
692 VbglR0SfDisconnect(&client_handle);
693 g_SfClient = client_handle; /* temporary */
694
695 fail1:
696 VbglR0SfTerm();
697
698 fail0:
699 unregister_filesystem(&vboxsf_fs_type);
700 return rcRet;
701}
702
703static void __exit fini(void)
704{
705 TRACE();
706
707 VbglR0SfDisconnect(&client_handle);
708 g_SfClient = client_handle; /* temporary */
709 VbglR0SfTerm();
710 unregister_filesystem(&vboxsf_fs_type);
711}
712
713module_init(init);
714module_exit(fini);
715
716/* C++ hack */
717int __gxx_personality_v0 = 0xdeadbeef;
Note: See TracBrowser for help on using the repository browser.

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