VirtualBox

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

Last change on this file since 13068 was 13058, checked in by vboxsync, 16 years ago

Linux kernel version check for r37508

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.6 KB
Line 
1/** @file
2 *
3 * vboxvfs -- 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-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
24 * Clara, CA 95054 USA or visit http://www.sun.com if you need
25 * additional information or have any questions.
26 */
27
28/**
29 * @note Anyone wishing to make changes here might wish to take a look at
30 * http://www.atnf.csiro.au/people/rgooch/linux/vfs.txt
31 * which seems to be the closest there is to official documentation on
32 * writing filesystem drivers for Linux.
33 */
34
35/*
36 * Suppress the definition of wchar_t from stddef.h that occurs below.
37 * This makes (at least) RHEL3U5 happy.
38 */
39#if 0
40#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
41# define _WCHAR_T
42#endif
43#endif
44
45#include "vfsmod.h"
46
47// #define wchar_t linux_wchar_t
48
49#define xstr(s) str(s)
50#define str(s) #s
51
52MODULE_DESCRIPTION ("Host file system access VFS for VirtualBox");
53MODULE_AUTHOR ("Sun Microsystems, Inc.");
54MODULE_LICENSE ("GPL");
55#ifdef MODULE_VERSION
56MODULE_VERSION(VBOX_VERSION_STRING " (interface " xstr(VMMDEV_VERSION) ")");
57#endif
58
59/* globals */
60VBSFCLIENT client_handle;
61
62/* forward declarations */
63static struct super_operations sf_super_ops;
64
65// #include "utils.c"
66// #include "dirops.c"
67// #include "regops.c"
68
69/* allocate global info, try to map host share */
70static int
71sf_glob_alloc (struct vbsf_mount_info_new *info, struct sf_glob_info **sf_gp)
72{
73 int err, rc;
74 SHFLSTRING *str_name;
75 size_t name_len, str_len;
76 struct sf_glob_info *sf_g;
77
78 TRACE ();
79 sf_g = kmalloc (sizeof (*sf_g), GFP_KERNEL);
80 if (!sf_g) {
81 err = -ENOMEM;
82 LogRelFunc(("could not allocate memory for global info\n"));
83 goto fail0;
84 }
85
86 memset(sf_g, 0, sizeof(*sf_g));
87
88 if ( info->nullchar != '\0'
89 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
90 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
91 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2)
92 {
93 /* An old version of mount.vboxsf made the syscall. Translate the
94 * old parameters to the new structure. */
95 struct vbsf_mount_info_old *info_old = (struct vbsf_mount_info_old *)info;
96 static struct vbsf_mount_info_new info_compat;
97
98 info = &info_compat;
99 memset(info, 0, sizeof(*info));
100 memcpy(&info->name, &info_old->name, MAX_HOST_NAME);
101 memcpy(&info->nls_name, &info_old->nls_name, MAX_NLS_NAME);
102 info->length = offsetof(struct vbsf_mount_info_new, dmode);
103 info->uid = info_old->uid;
104 info->gid = info_old->gid;
105 info->ttl = info_old->ttl;
106 }
107
108 info->name[sizeof (info->name) - 1] = 0;
109 info->nls_name[sizeof (info->nls_name) - 1] = 0;
110
111 name_len = strlen (info->name);
112 if (name_len > 0xfffe) {
113 err = -ENAMETOOLONG;
114 LogFunc(("map name too big\n"));
115 goto fail1;
116 }
117
118 str_len = offsetof (SHFLSTRING, String.utf8) + name_len + 1;
119 str_name = kmalloc (str_len, GFP_KERNEL);
120 if (!str_name) {
121 err = -ENOMEM;
122 LogRelFunc(("could not allocate memory for host name\n"));
123 goto fail1;
124 }
125
126 str_name->u16Length = name_len;
127 str_name->u16Size = name_len + 1;
128 memcpy (str_name->String.utf8, info->name, name_len + 1);
129
130 if (info->nls_name[0] && strcmp (info->nls_name, "utf8")) {
131 sf_g->nls = load_nls (info->nls_name);
132 if (!sf_g->nls) {
133 err = -EINVAL;
134 LogFunc(("failed to load nls %s\n", info->nls_name));
135 goto fail1;
136 }
137 }
138 else {
139 sf_g->nls = NULL;
140 }
141
142 rc = vboxCallMapFolder (&client_handle, str_name, &sf_g->map);
143 kfree (str_name);
144
145 if (VBOX_FAILURE (rc)) {
146 err = -EPROTO;
147 LogFunc(("vboxCallMapFolder failed rc=%d\n", rc));
148 goto fail2;
149 }
150
151 sf_g->ttl = info->ttl;
152 sf_g->uid = info->uid;
153 sf_g->gid = info->gid;
154
155 if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new))
156 {
157 /* new fields */
158 sf_g->dmode = info->dmode;
159 sf_g->fmode = info->fmode;
160 sf_g->dmask = info->dmask;
161 sf_g->fmask = info->fmask;
162 }
163 else
164 {
165 sf_g->dmode = ~0;
166 sf_g->fmode = ~0;
167 }
168
169 *sf_gp = sf_g;
170 return 0;
171
172 fail2:
173 if (sf_g->nls) {
174 unload_nls (sf_g->nls);
175 }
176 fail1:
177 kfree (sf_g);
178 fail0:
179 return err;
180}
181
182/* unmap the share and free global info [sf_g] */
183static void
184sf_glob_free (struct sf_glob_info *sf_g)
185{
186 int rc;
187
188 TRACE ();
189 rc = vboxCallUnmapFolder (&client_handle, &sf_g->map);
190 if (VBOX_FAILURE (rc)) {
191 LogFunc(("vboxCallUnmapFolder failed rc=%d\n", rc));
192 }
193
194 if (sf_g->nls) {
195 unload_nls (sf_g->nls);
196 }
197 kfree (sf_g);
198}
199
200/* this is called (by sf_read_super_[24|26] when vfs mounts the fs and
201 wants to read super_block.
202
203 calls [sf_glob_alloc] to map the folder and allocate global
204 information structure.
205
206 initializes [sb], initializes root inode and dentry.
207
208 should respect [flags] */
209static int
210sf_read_super_aux (struct super_block *sb, void *data, int flags)
211{
212 int err;
213 struct dentry *droot;
214 struct inode *iroot;
215 struct sf_inode_info *sf_i;
216 struct sf_glob_info *sf_g;
217 RTFSOBJINFO fsinfo;
218 struct vbsf_mount_info_new *info;
219
220 TRACE ();
221 if (!data) {
222 LogFunc(("no mount info specified\n"));
223 return -EINVAL;
224 }
225
226 info = data;
227
228 if (flags & MS_REMOUNT) {
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
238 sf_i = kmalloc (sizeof (*sf_i), GFP_KERNEL);
239 if (!sf_i) {
240 err = -ENOMEM;
241 LogRelFunc (("could not allocate memory for root inode info\n"));
242 goto fail1;
243 }
244
245 sf_i->path = kmalloc (sizeof (SHFLSTRING) + 1, GFP_KERNEL);
246 if (!sf_i->path) {
247 err = -ENOMEM;
248 LogRelFunc (("could not allocate memory for root inode path\n"));
249 goto fail2;
250 }
251
252 sf_i->path->u16Length = 1;
253 sf_i->path->u16Size = 2;
254 sf_i->path->String.utf8[0] = '/';
255 sf_i->path->String.utf8[1] = 0;
256
257 err = sf_stat (__func__, sf_g, sf_i->path, &fsinfo, 0);
258 if (err) {
259 LogFunc(("could not stat root of share\n"));
260 goto fail3;
261 }
262
263 sb->s_magic = 0xface;
264 sb->s_blocksize = 1024;
265#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 4, 3)
266 sb->s_maxbytes = ~0ULL; /* seek */
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 sf_init_inode (sf_g, iroot, &fsinfo);
282 SET_INODE_INFO (iroot, sf_i);
283
284#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 4, 25)
285 unlock_new_inode(iroot);
286#endif
287
288 droot = d_alloc_root (iroot);
289 if (!droot) {
290 err = -ENOMEM; /* XXX */
291 LogFunc(("d_alloc_root failed\n"));
292 goto fail4;
293 }
294
295 sb->s_root = droot;
296 SET_GLOB_INFO (sb, sf_g);
297 return 0;
298
299 fail4:
300 iput (iroot);
301 fail3:
302 kfree (sf_i->path);
303 fail2:
304 kfree (sf_i);
305 fail1:
306 sf_glob_free (sf_g);
307 fail0:
308 return err;
309}
310
311#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
312static struct super_block *
313sf_read_super_24 (struct super_block *sb, void *data, int flags)
314{
315 int err;
316
317 TRACE ();
318 err = sf_read_super_aux (sb, data, flags);
319 if (err) {
320 return NULL;
321 }
322
323 return sb;
324}
325#endif
326
327/* this is called when vfs is about to destroy the [inode]. all
328 resources associated with this [inode] must be cleared here */
329static void
330sf_clear_inode (struct inode *inode)
331{
332 struct sf_inode_info *sf_i;
333
334 TRACE ();
335 sf_i = GET_INODE_INFO (inode);
336 if (!sf_i) {
337 return;
338 }
339
340 BUG_ON (!sf_i->path);
341 kfree (sf_i->path);
342 kfree (sf_i);
343 SET_INODE_INFO (inode, NULL);
344}
345
346/* this is called by vfs when it wants to populate [inode] with data.
347 the only thing that is known about inode at this point is its index
348 hence we can't do anything here, and let lookup/whatever with the
349 job to properly fill then [inode] */
350#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 25)
351static void
352sf_read_inode (struct inode *inode)
353{
354}
355#endif
356
357/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
358 the folder and free [sf_g] */
359static void
360sf_put_super (struct super_block *sb)
361{
362 struct sf_glob_info *sf_g;
363
364 sf_g = GET_GLOB_INFO (sb);
365 BUG_ON (!sf_g);
366 sf_glob_free (sf_g);
367}
368
369#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 18)
370static int
371sf_statfs (struct super_block *sb, STRUCT_STATFS *stat)
372{
373 return sf_get_volume_info(sb, stat);
374}
375#else
376static int
377sf_statfs (struct dentry *dentry, STRUCT_STATFS *stat)
378{
379 struct super_block *sb = dentry->d_inode->i_sb;
380 return sf_get_volume_info(sb, stat);
381}
382#endif
383
384static int
385sf_remount_fs (struct super_block *sb, int *flags, char *data)
386{
387 TRACE ();
388 return -ENOSYS;
389}
390
391static struct super_operations sf_super_ops = {
392 .clear_inode = sf_clear_inode,
393#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 25)
394 .read_inode = sf_read_inode,
395#endif
396 .put_super = sf_put_super,
397 .statfs = sf_statfs,
398 .remount_fs = sf_remount_fs
399};
400
401#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
402static DECLARE_FSTYPE (vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
403#else
404static int
405sf_read_super_26 (struct super_block *sb, void *data, int flags)
406{
407 int err;
408
409 TRACE ();
410 err = sf_read_super_aux (sb, data, flags);
411 if (err) {
412 printk (KERN_DEBUG "sf_read_super_aux err=%d\n", err);
413 }
414 return err;
415}
416
417#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 18)
418static struct super_block *
419sf_get_sb (struct file_system_type *fs_type, int flags,
420 const char *dev_name, void *data)
421{
422 TRACE ();
423 return get_sb_nodev (fs_type, flags, data, sf_read_super_26);
424}
425#else
426static int
427sf_get_sb (struct file_system_type *fs_type, int flags,
428 const char *dev_name, void *data, struct vfsmount *mnt)
429{
430 TRACE ();
431 return get_sb_nodev (fs_type, flags, data, sf_read_super_26, mnt);
432}
433#endif
434
435static struct file_system_type vboxsf_fs_type = {
436 .owner = THIS_MODULE,
437 .name = "vboxsf",
438 .get_sb = sf_get_sb,
439 .kill_sb = kill_anon_super
440};
441#endif
442
443extern int CMC_API
444vboxadd_cmc_ctl_guest_filter_mask (uint32_t or_mask, uint32_t not_mask);
445
446/* Module initialization/finalization handlers */
447static int __init
448init (void)
449{
450 int rcVBox;
451 int rcRet = 0;
452 int err;
453
454 TRACE ();
455
456 if (sizeof (struct vbsf_mount_info_new) > PAGE_SIZE) {
457 printk (KERN_ERR
458 "Mount information structure is too large %lu\n"
459 "Must be less than or equal to %lu\n",
460 (unsigned long)sizeof (struct vbsf_mount_info_new),
461 PAGE_SIZE);
462 return -EINVAL;
463 }
464
465 err = register_filesystem (&vboxsf_fs_type);
466 if (err) {
467 LogFunc(("register_filesystem err=%d\n", err));
468 return err;
469 }
470
471 if (vboxadd_cmc_ctl_guest_filter_mask (VMMDEV_EVENT_HGCM, 0)) {
472 rcRet = -EINVAL;
473 goto fail0;
474 }
475
476 rcVBox = vboxInit ();
477 if (VBOX_FAILURE (rcVBox)) {
478 LogRelFunc (("vboxInit failed, rc=%d\n", rcVBox));
479 rcRet = -EPROTO;
480 goto fail0;
481 }
482
483 rcVBox = vboxConnect (&client_handle);
484 if (VBOX_FAILURE (rcVBox)) {
485 LogRelFunc (("vboxConnect failed, rc=%d\n", rcVBox));
486 rcRet = -EPROTO;
487 goto fail1;
488 }
489
490 rcVBox = vboxCallSetUtf8 (&client_handle);
491 if (VBOX_FAILURE (rcVBox)) {
492 LogRelFunc (("vboxCallSetUtf8 failed, rc=%d\n", rcVBox));
493 rcRet = -EPROTO;
494 goto fail2;
495 }
496
497 printk(KERN_DEBUG
498 "vboxvfs: Successfully loaded version " VBOX_VERSION_STRING
499 " (interface " xstr(VMMDEV_VERSION) ")\n");
500
501 return 0;
502
503 fail2:
504 vboxDisconnect (&client_handle);
505 fail1:
506 vboxUninit ();
507 fail0:
508 vboxadd_cmc_ctl_guest_filter_mask (0, VMMDEV_EVENT_HGCM);
509 unregister_filesystem (&vboxsf_fs_type);
510 return rcRet;
511}
512
513static void __exit
514fini (void)
515{
516 TRACE ();
517
518 vboxDisconnect (&client_handle);
519 vboxUninit ();
520 vboxadd_cmc_ctl_guest_filter_mask (0, VMMDEV_EVENT_HGCM);
521 unregister_filesystem (&vboxsf_fs_type);
522}
523
524module_init (init);
525module_exit (fini);
526
527/* C++ hack */
528int __gxx_personality_v0 = 0xdeadbeef;
529
530#if 0
531/* long long hacks (as far as i can see, gcc emits the refs to those
532 symbols, notwithstanding the fact that those aren't referenced
533 anywhere in the module) */
534void __divdi3 (void)
535{
536 elog ("called from %p\n", __builtin_return_address (0));
537 BUG ();
538}
539
540void __moddi3 (void)
541{
542 elog ("called from %p\n", __builtin_return_address (0));
543 BUG ();
544}
545#endif /* 0 */
546
547/*
548 * Local Variables:
549 * c-mode: linux
550 * indent-tabs-mode: nil
551 * c-basic-offset: 8
552 * End:
553 */
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