VirtualBox

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

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

linux/vboxsf: Cleaned out the VBOXSF_USE_DEPRECATED_VBGL_INTERFACE #ifdefs. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.7 KB
Line 
1/* $Id: vfsmod.c 77303 2019-02-13 14:49:11Z 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 rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER,
193 true /*fCaseSensitive*/, &sf_g->map.root);
194 kfree(str_name);
195
196 if (RT_FAILURE(rc)) {
197 err = -EPROTO;
198 LogFunc(("SHFL_FN_MAP_FOLDER failed rc=%Rrc\n", rc));
199 goto fail2;
200 }
201
202 /* The rest is shared with remount. */
203 sf_glob_copy_remount_options(sf_g, info);
204
205 *sf_gp = sf_g;
206 return 0;
207
208 fail2:
209 if (sf_g->nls)
210 unload_nls(sf_g->nls);
211
212 fail1:
213 kfree(sf_g);
214
215 fail0:
216 return err;
217}
218
219/* unmap the share and free global info [sf_g] */
220static void sf_glob_free(struct sf_glob_info *sf_g)
221{
222 int rc;
223
224 TRACE();
225 rc = VbglR0SfHostReqUnmapFolderSimple(sf_g->map.root);
226 if (RT_FAILURE(rc))
227 LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc));
228
229 if (sf_g->nls)
230 unload_nls(sf_g->nls);
231
232 kfree(sf_g);
233}
234
235/**
236 * This is called (by sf_read_super_[24|26] when vfs mounts the fs and
237 * wants to read super_block.
238 *
239 * calls [sf_glob_alloc] to map the folder and allocate global
240 * information structure.
241 *
242 * initializes [sb], initializes root inode and dentry.
243 *
244 * should respect [flags]
245 */
246static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
247{
248 int err;
249 struct dentry *droot;
250 struct inode *iroot;
251 struct sf_inode_info *sf_i;
252 struct sf_glob_info *sf_g;
253 SHFLFSOBJINFO fsinfo;
254 struct vbsf_mount_info_new *info;
255 bool fInodePut = true;
256
257 TRACE();
258 if (!data) {
259 LogFunc(("no mount info specified\n"));
260 return -EINVAL;
261 }
262
263 info = data;
264
265 if (flags & MS_REMOUNT) {
266 LogFunc(("remounting is not supported\n"));
267 return -ENOSYS;
268 }
269
270 err = sf_glob_alloc(info, &sf_g);
271 if (err)
272 goto fail0;
273
274 sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
275 if (!sf_i) {
276 err = -ENOMEM;
277 LogRelFunc(("could not allocate memory for root inode info\n"));
278 goto fail1;
279 }
280
281 sf_i->handle = SHFL_HANDLE_NIL;
282 sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
283 if (!sf_i->path) {
284 err = -ENOMEM;
285 LogRelFunc(("could not allocate memory for root inode path\n"));
286 goto fail2;
287 }
288
289 sf_i->path->u16Length = 1;
290 sf_i->path->u16Size = 2;
291 sf_i->path->String.utf8[0] = '/';
292 sf_i->path->String.utf8[1] = 0;
293 sf_i->force_reread = 0;
294
295 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
296 if (err) {
297 LogFunc(("could not stat root of share\n"));
298 goto fail3;
299 }
300
301 sb->s_magic = 0xface;
302 sb->s_blocksize = 1024;
303#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
304 /* Required for seek/sendfile.
305 *
306 * Must by less than or equal to INT64_MAX despite the fact that the
307 * declaration of this variable is unsigned long long. See determination
308 * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
309 * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
310 * page cache into account and is the suggested limit. */
311# if defined MAX_LFS_FILESIZE
312 sb->s_maxbytes = MAX_LFS_FILESIZE;
313# else
314 sb->s_maxbytes = 0x7fffffffffffffffULL;
315# endif
316#endif
317 sb->s_op = &sf_super_ops;
318
319#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
320 iroot = iget_locked(sb, 0);
321#else
322 iroot = iget(sb, 0);
323#endif
324 if (!iroot) {
325 err = -ENOMEM; /* XXX */
326 LogFunc(("could not get root inode\n"));
327 goto fail3;
328 }
329
330 if (sf_init_backing_dev(sf_g)) {
331 err = -EINVAL;
332 LogFunc(("could not init bdi\n"));
333#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
334 unlock_new_inode(iroot);
335#endif
336 goto fail4;
337 }
338
339 sf_init_inode(sf_g, iroot, &fsinfo);
340 SET_INODE_INFO(iroot, sf_i);
341
342#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
343 unlock_new_inode(iroot);
344#endif
345
346#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
347 droot = d_make_root(iroot);
348#else
349 droot = d_alloc_root(iroot);
350#endif
351 if (!droot) {
352 err = -ENOMEM; /* XXX */
353 LogFunc(("d_alloc_root failed\n"));
354#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
355 fInodePut = false;
356#endif
357 goto fail5;
358 }
359
360 sb->s_root = droot;
361 SET_GLOB_INFO(sb, sf_g);
362 return 0;
363
364 fail5:
365 sf_done_backing_dev(sf_g);
366
367 fail4:
368 if (fInodePut)
369 iput(iroot);
370
371 fail3:
372 kfree(sf_i->path);
373
374 fail2:
375 kfree(sf_i);
376
377 fail1:
378 sf_glob_free(sf_g);
379
380 fail0:
381 return err;
382}
383
384#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
385static struct super_block *sf_read_super_24(struct super_block *sb, void *data,
386 int flags)
387{
388 int err;
389
390 TRACE();
391 err = sf_read_super_aux(sb, data, flags);
392 if (err)
393 return NULL;
394
395 return sb;
396}
397#endif
398
399/* this is called when vfs is about to destroy the [inode]. all
400 resources associated with this [inode] must be cleared here */
401#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
402static void sf_clear_inode(struct inode *inode)
403{
404 struct sf_inode_info *sf_i;
405
406 TRACE();
407 sf_i = GET_INODE_INFO(inode);
408 if (!sf_i)
409 return;
410
411 BUG_ON(!sf_i->path);
412 kfree(sf_i->path);
413 kfree(sf_i);
414 SET_INODE_INFO(inode, NULL);
415}
416#else /* LINUX_VERSION_CODE >= 2.6.36 */
417static void sf_evict_inode(struct inode *inode)
418{
419 struct sf_inode_info *sf_i;
420
421 TRACE();
422 truncate_inode_pages(&inode->i_data, 0);
423# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
424 clear_inode(inode);
425# else
426 end_writeback(inode);
427# endif
428
429 sf_i = GET_INODE_INFO(inode);
430 if (!sf_i)
431 return;
432
433 BUG_ON(!sf_i->path);
434 kfree(sf_i->path);
435 kfree(sf_i);
436 SET_INODE_INFO(inode, NULL);
437}
438#endif /* LINUX_VERSION_CODE >= 2.6.36 */
439
440/* this is called by vfs when it wants to populate [inode] with data.
441 the only thing that is known about inode at this point is its index
442 hence we can't do anything here, and let lookup/whatever with the
443 job to properly fill then [inode] */
444#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
445static void sf_read_inode(struct inode *inode)
446{
447}
448#endif
449
450/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
451 the folder and free [sf_g] */
452static void sf_put_super(struct super_block *sb)
453{
454 struct sf_glob_info *sf_g;
455
456 sf_g = GET_GLOB_INFO(sb);
457 BUG_ON(!sf_g);
458 sf_done_backing_dev(sf_g);
459 sf_glob_free(sf_g);
460}
461
462#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
463static int sf_statfs(struct super_block *sb, STRUCT_STATFS * stat)
464{
465 return sf_get_volume_info(sb, stat);
466}
467#else
468static int sf_statfs(struct dentry *dentry, STRUCT_STATFS * stat)
469{
470 struct super_block *sb = dentry->d_inode->i_sb;
471 return sf_get_volume_info(sb, stat);
472}
473#endif
474
475static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
476{
477#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
478 struct sf_glob_info *sf_g;
479 struct sf_inode_info *sf_i;
480 struct inode *iroot;
481 SHFLFSOBJINFO fsinfo;
482 int err;
483
484 sf_g = GET_GLOB_INFO(sb);
485 BUG_ON(!sf_g);
486 if (data && data[0] != 0) {
487 struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
488 if ( info->nullchar == '\0'
489 && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
490 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
491 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
492 sf_glob_copy_remount_options(sf_g, info);
493 }
494 }
495
496 iroot = ilookup(sb, 0);
497 if (!iroot)
498 return -ENOSYS;
499
500 sf_i = GET_INODE_INFO(iroot);
501 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
502 BUG_ON(err != 0);
503 sf_init_inode(sf_g, iroot, &fsinfo);
504 /*unlock_new_inode(iroot); */
505 return 0;
506#else /* LINUX_VERSION_CODE < 2.4.23 */
507 return -ENOSYS;
508#endif /* LINUX_VERSION_CODE < 2.4.23 */
509}
510
511/** Show mount options. */
512#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
513static int sf_show_options(struct seq_file *m, struct vfsmount *mnt)
514#else
515static int sf_show_options(struct seq_file *m, struct dentry *root)
516#endif
517{
518#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
519 struct super_block *sb = mnt->mnt_sb;
520#else
521 struct super_block *sb = root->d_sb;
522#endif
523 struct sf_glob_info *sf_g = GET_GLOB_INFO(sb);
524 if (sf_g) {
525 seq_printf(m, ",uid=%u,gid=%u,ttl=%u,dmode=0%o,fmode=0%o,dmask=0%o,fmask=0%o,maxiopages=%u",
526 sf_g->uid, sf_g->gid, sf_g->ttl, sf_g->dmode, sf_g->fmode, sf_g->dmask,
527 sf_g->fmask, sf_g->cMaxIoPages);
528 if (sf_g->tag[0] != '\0') {
529 seq_puts(m, ",tag=");
530 seq_escape(m, sf_g->tag, " \t\n\\");
531 }
532 }
533
534 return 0;
535}
536
537static struct super_operations sf_super_ops = {
538#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
539 .clear_inode = sf_clear_inode,
540#else
541 .evict_inode = sf_evict_inode,
542#endif
543#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
544 .read_inode = sf_read_inode,
545#endif
546 .put_super = sf_put_super,
547 .statfs = sf_statfs,
548 .remount_fs = sf_remount_fs,
549 .show_options = sf_show_options
550};
551
552#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
553static DECLARE_FSTYPE(vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
554#else
555static int sf_read_super_26(struct super_block *sb, void *data, int flags)
556{
557 int err;
558
559 TRACE();
560 err = sf_read_super_aux(sb, data, flags);
561 if (err)
562 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
563
564 return err;
565}
566
567# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
568static struct super_block *sf_get_sb(struct file_system_type *fs_type,
569 int flags, const char *dev_name,
570 void *data)
571{
572 TRACE();
573 return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
574}
575# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
576static int sf_get_sb(struct file_system_type *fs_type, int flags,
577 const char *dev_name, void *data, struct vfsmount *mnt)
578{
579 TRACE();
580 return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
581}
582# else /* LINUX_VERSION_CODE >= 2.6.39 */
583static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
584 const char *dev_name, void *data)
585{
586 TRACE();
587 return mount_nodev(fs_type, flags, data, sf_read_super_26);
588}
589# endif /* LINUX_VERSION_CODE >= 2.6.39 */
590
591static struct file_system_type vboxsf_fs_type = {
592 .owner = THIS_MODULE,
593 .name = "vboxsf",
594# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
595 .get_sb = sf_get_sb,
596# else
597 .mount = sf_mount,
598# endif
599 .kill_sb = kill_anon_super
600};
601
602#endif /* LINUX_VERSION_CODE >= 2.6.0 */
603
604#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
605static int follow_symlinks = 0;
606module_param(follow_symlinks, int, 0);
607MODULE_PARM_DESC(follow_symlinks,
608 "Let host resolve symlinks rather than showing them");
609#endif
610
611/* Module initialization/finalization handlers */
612static int __init init(void)
613{
614 int vrc;
615 int rcRet = 0;
616 int err;
617
618 TRACE();
619
620 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
621 printk(KERN_ERR
622 "Mount information structure is too large %lu\n"
623 "Must be less than or equal to %lu\n",
624 (unsigned long)sizeof(struct vbsf_mount_info_new),
625 (unsigned long)PAGE_SIZE);
626 return -EINVAL;
627 }
628
629 err = register_filesystem(&vboxsf_fs_type);
630 if (err) {
631 LogFunc(("register_filesystem err=%d\n", err));
632 return err;
633 }
634
635 vrc = VbglR0SfInit();
636 if (RT_FAILURE(vrc)) {
637 LogRelFunc(("VbglR0SfInit failed, vrc=%Rrc\n", vrc));
638 rcRet = -EPROTO;
639 goto fail0;
640 }
641
642 vrc = VbglR0SfConnect(&client_handle);
643 g_SfClient = client_handle; /* temporary */
644 if (RT_FAILURE(vrc)) {
645 LogRelFunc(("VbglR0SfConnect failed, vrc=%Rrc\n", vrc));
646 rcRet = -EPROTO;
647 goto fail1;
648 }
649
650 vrc = VbglR0QueryHostFeatures(&g_fHostFeatures);
651 if (RT_FAILURE(vrc))
652 {
653 LogRelFunc(("VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc));
654 g_fHostFeatures = 0;
655 }
656 LogRelFunc(("g_fHostFeatures=%#x\n", g_fHostFeatures));
657
658 vrc = VbglR0SfSetUtf8(&client_handle);
659 if (RT_FAILURE(vrc)) {
660 LogRelFunc(("VbglR0SfSetUtf8 failed, vrc=%Rrc\n", vrc));
661 rcRet = -EPROTO;
662 goto fail2;
663 }
664#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
665 if (!follow_symlinks) {
666 vrc = VbglR0SfSetSymlinks(&client_handle);
667 if (RT_FAILURE(vrc)) {
668 printk(KERN_WARNING
669 "vboxsf: Host unable to show symlinks, vrc=%d\n",
670 vrc);
671 }
672 }
673#endif
674
675 printk(KERN_DEBUG
676 "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
677 " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
678
679 return 0;
680
681 fail2:
682 VbglR0SfDisconnect(&client_handle);
683 g_SfClient = client_handle; /* temporary */
684
685 fail1:
686 VbglR0SfTerm();
687
688 fail0:
689 unregister_filesystem(&vboxsf_fs_type);
690 return rcRet;
691}
692
693static void __exit fini(void)
694{
695 TRACE();
696
697 VbglR0SfDisconnect(&client_handle);
698 g_SfClient = client_handle; /* temporary */
699 VbglR0SfTerm();
700 unregister_filesystem(&vboxsf_fs_type);
701}
702
703module_init(init);
704module_exit(fini);
705
706/* C++ hack */
707int __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