VirtualBox

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

Last change on this file since 24660 was 24320, checked in by vboxsync, 15 years ago

more RT_ZERO()

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.7 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
49MODULE_DESCRIPTION ("Host file system access VFS for VirtualBox");
50MODULE_AUTHOR ("Sun Microsystems, Inc.");
51MODULE_LICENSE ("GPL");
52#ifdef MODULE_VERSION
53MODULE_VERSION(VBOX_VERSION_STRING " (interface " RT_XSTR(VMMDEV_VERSION) ")");
54#endif
55
56/* globals */
57VBSFCLIENT client_handle;
58
59/* forward declarations */
60static struct super_operations sf_super_ops;
61
62// #include "utils.c"
63// #include "dirops.c"
64// #include "regops.c"
65
66/* allocate global info, try to map host share */
67static int
68sf_glob_alloc (struct vbsf_mount_info_new *info, struct sf_glob_info **sf_gp)
69{
70 int err, rc;
71 SHFLSTRING *str_name;
72 size_t name_len, str_len;
73 struct sf_glob_info *sf_g;
74
75 TRACE ();
76 sf_g = kmalloc (sizeof (*sf_g), GFP_KERNEL);
77 if (!sf_g) {
78 err = -ENOMEM;
79 LogRelFunc(("could not allocate memory for global info\n"));
80 goto fail0;
81 }
82
83 RT_ZERO(*sf_g);
84
85 if ( info->nullchar != '\0'
86 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
87 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
88 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2)
89 {
90 /* An old version of mount.vboxsf made the syscall. Translate the
91 * old parameters to the new structure. */
92 struct vbsf_mount_info_old *info_old = (struct vbsf_mount_info_old *)info;
93 static struct vbsf_mount_info_new info_compat;
94
95 info = &info_compat;
96 memset(info, 0, sizeof(*info));
97 memcpy(&info->name, &info_old->name, MAX_HOST_NAME);
98 memcpy(&info->nls_name, &info_old->nls_name, MAX_NLS_NAME);
99 info->length = offsetof(struct vbsf_mount_info_new, dmode);
100 info->uid = info_old->uid;
101 info->gid = info_old->gid;
102 info->ttl = info_old->ttl;
103 }
104
105 info->name[sizeof (info->name) - 1] = 0;
106 info->nls_name[sizeof (info->nls_name) - 1] = 0;
107
108 name_len = strlen (info->name);
109 if (name_len > 0xfffe) {
110 err = -ENAMETOOLONG;
111 LogFunc(("map name too big\n"));
112 goto fail1;
113 }
114
115 str_len = offsetof (SHFLSTRING, String.utf8) + name_len + 1;
116 str_name = kmalloc (str_len, GFP_KERNEL);
117 if (!str_name) {
118 err = -ENOMEM;
119 LogRelFunc(("could not allocate memory for host name\n"));
120 goto fail1;
121 }
122
123 str_name->u16Length = name_len;
124 str_name->u16Size = name_len + 1;
125 memcpy (str_name->String.utf8, info->name, name_len + 1);
126
127 if (info->nls_name[0] && strcmp (info->nls_name, "utf8")) {
128 sf_g->nls = load_nls (info->nls_name);
129 if (!sf_g->nls) {
130 err = -EINVAL;
131 LogFunc(("failed to load nls %s\n", info->nls_name));
132 goto fail1;
133 }
134 }
135 else {
136 sf_g->nls = NULL;
137 }
138
139 rc = vboxCallMapFolder (&client_handle, str_name, &sf_g->map);
140 kfree (str_name);
141
142 if (RT_FAILURE (rc)) {
143 err = -EPROTO;
144 LogFunc(("vboxCallMapFolder failed rc=%d\n", rc));
145 goto fail2;
146 }
147
148 sf_g->ttl = info->ttl;
149 sf_g->uid = info->uid;
150 sf_g->gid = info->gid;
151
152 if ((unsigned)info->length >= sizeof(struct vbsf_mount_info_new))
153 {
154 /* new fields */
155 sf_g->dmode = info->dmode;
156 sf_g->fmode = info->fmode;
157 sf_g->dmask = info->dmask;
158 sf_g->fmask = info->fmask;
159 }
160 else
161 {
162 sf_g->dmode = ~0;
163 sf_g->fmode = ~0;
164 }
165
166 *sf_gp = sf_g;
167 return 0;
168
169 fail2:
170 if (sf_g->nls) {
171 unload_nls (sf_g->nls);
172 }
173 fail1:
174 kfree (sf_g);
175 fail0:
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 = vboxCallUnmapFolder (&client_handle, &sf_g->map);
187 if (RT_FAILURE (rc)) {
188 LogFunc(("vboxCallUnmapFolder failed rc=%d\n", rc));
189 }
190
191 if (sf_g->nls) {
192 unload_nls (sf_g->nls);
193 }
194 kfree (sf_g);
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] */
206static int
207sf_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 RTFSOBJINFO fsinfo;
215 struct vbsf_mount_info_new *info;
216
217 TRACE ();
218 if (!data) {
219 LogFunc(("no mount info specified\n"));
220 return -EINVAL;
221 }
222
223 info = data;
224
225 if (flags & MS_REMOUNT) {
226 LogFunc(("remounting is not supported\n"));
227 return -ENOSYS;
228 }
229
230 err = sf_glob_alloc (info, &sf_g);
231 if (err) {
232 goto fail0;
233 }
234
235 sf_i = kmalloc (sizeof (*sf_i), GFP_KERNEL);
236 if (!sf_i) {
237 err = -ENOMEM;
238 LogRelFunc (("could not allocate memory for root inode info\n"));
239 goto fail1;
240 }
241
242 sf_i->path = kmalloc (sizeof (SHFLSTRING) + 1, GFP_KERNEL);
243 if (!sf_i->path) {
244 err = -ENOMEM;
245 LogRelFunc (("could not allocate memory for root inode path\n"));
246 goto fail2;
247 }
248
249 sf_i->path->u16Length = 1;
250 sf_i->path->u16Size = 2;
251 sf_i->path->String.utf8[0] = '/';
252 sf_i->path->String.utf8[1] = 0;
253
254 err = sf_stat (__func__, sf_g, sf_i->path, &fsinfo, 0);
255 if (err) {
256 LogFunc(("could not stat root of share\n"));
257 goto fail3;
258 }
259
260 sb->s_magic = 0xface;
261 sb->s_blocksize = 1024;
262#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 4, 3)
263 /* Required for seek/sendfile.
264 *
265 * Must by less than or equal to INT64_MAX despite the fact that the
266 * declaration of this variable is unsigned long long. See determination
267 * of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
268 * correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
269 * page cache into account and is the suggested limit. */
270# if defined MAX_LFS_FILESIZE
271 sb->s_maxbytes = MAX_LFS_FILESIZE;
272# else
273 sb->s_maxbytes = 0x7fffffffffffffffULL;
274# endif
275#endif
276 sb->s_op = &sf_super_ops;
277
278#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 4, 25)
279 iroot = iget_locked (sb, 0);
280#else
281 iroot = iget (sb, 0);
282#endif
283 if (!iroot) {
284 err = -ENOMEM; /* XXX */
285 LogFunc(("could not get root inode\n"));
286 goto fail3;
287 }
288
289 sf_init_inode (sf_g, iroot, &fsinfo);
290 SET_INODE_INFO (iroot, sf_i);
291
292#if LINUX_VERSION_CODE >= KERNEL_VERSION (2, 4, 25)
293 unlock_new_inode(iroot);
294#endif
295
296 droot = d_alloc_root (iroot);
297 if (!droot) {
298 err = -ENOMEM; /* XXX */
299 LogFunc(("d_alloc_root failed\n"));
300 goto fail4;
301 }
302
303 sb->s_root = droot;
304 SET_GLOB_INFO (sb, sf_g);
305 return 0;
306
307 fail4:
308 iput (iroot);
309 fail3:
310 kfree (sf_i->path);
311 fail2:
312 kfree (sf_i);
313 fail1:
314 sf_glob_free (sf_g);
315 fail0:
316 return err;
317}
318
319#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
320static struct super_block *
321sf_read_super_24 (struct super_block *sb, void *data, int flags)
322{
323 int err;
324
325 TRACE ();
326 err = sf_read_super_aux (sb, data, flags);
327 if (err) {
328 return NULL;
329 }
330
331 return sb;
332}
333#endif
334
335/* this is called when vfs is about to destroy the [inode]. all
336 resources associated with this [inode] must be cleared here */
337static void
338sf_clear_inode (struct inode *inode)
339{
340 struct sf_inode_info *sf_i;
341
342 TRACE ();
343 sf_i = GET_INODE_INFO (inode);
344 if (!sf_i) {
345 return;
346 }
347
348 BUG_ON (!sf_i->path);
349 kfree (sf_i->path);
350 kfree (sf_i);
351 SET_INODE_INFO (inode, NULL);
352}
353
354/* this is called by vfs when it wants to populate [inode] with data.
355 the only thing that is known about inode at this point is its index
356 hence we can't do anything here, and let lookup/whatever with the
357 job to properly fill then [inode] */
358#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 25)
359static void
360sf_read_inode (struct inode *inode)
361{
362}
363#endif
364
365/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
366 the folder and free [sf_g] */
367static void
368sf_put_super (struct super_block *sb)
369{
370 struct sf_glob_info *sf_g;
371
372 sf_g = GET_GLOB_INFO (sb);
373 BUG_ON (!sf_g);
374 sf_glob_free (sf_g);
375}
376
377#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 18)
378static int
379sf_statfs (struct super_block *sb, STRUCT_STATFS *stat)
380{
381 return sf_get_volume_info(sb, stat);
382}
383#else
384static int
385sf_statfs (struct dentry *dentry, STRUCT_STATFS *stat)
386{
387 struct super_block *sb = dentry->d_inode->i_sb;
388 return sf_get_volume_info(sb, stat);
389}
390#endif
391
392static int
393sf_remount_fs (struct super_block *sb, int *flags, char *data)
394{
395 TRACE ();
396 return -ENOSYS;
397}
398
399static struct super_operations sf_super_ops = {
400 .clear_inode = sf_clear_inode,
401#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 25)
402 .read_inode = sf_read_inode,
403#endif
404 .put_super = sf_put_super,
405 .statfs = sf_statfs,
406 .remount_fs = sf_remount_fs
407};
408
409#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 0)
410static DECLARE_FSTYPE (vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
411#else
412static int
413sf_read_super_26 (struct super_block *sb, void *data, int flags)
414{
415 int err;
416
417 TRACE ();
418 err = sf_read_super_aux (sb, data, flags);
419 if (err) {
420 printk (KERN_DEBUG "sf_read_super_aux err=%d\n", err);
421 }
422 return err;
423}
424
425#if LINUX_VERSION_CODE < KERNEL_VERSION (2, 6, 18)
426static struct super_block *
427sf_get_sb (struct file_system_type *fs_type, int flags,
428 const char *dev_name, void *data)
429{
430 TRACE ();
431 return get_sb_nodev (fs_type, flags, data, sf_read_super_26);
432}
433#else
434static int
435sf_get_sb (struct file_system_type *fs_type, int flags,
436 const char *dev_name, void *data, struct vfsmount *mnt)
437{
438 TRACE ();
439 return get_sb_nodev (fs_type, flags, data, sf_read_super_26, mnt);
440}
441#endif
442
443static struct file_system_type vboxsf_fs_type = {
444 .owner = THIS_MODULE,
445 .name = "vboxsf",
446 .get_sb = sf_get_sb,
447 .kill_sb = kill_anon_super
448};
449#endif
450
451/* Module initialization/finalization handlers */
452static int __init
453init (void)
454{
455 int rcVBox;
456 int rcRet = 0;
457 int err;
458
459 TRACE ();
460
461 if (sizeof (struct vbsf_mount_info_new) > PAGE_SIZE) {
462 printk (KERN_ERR
463 "Mount information structure is too large %lu\n"
464 "Must be less than or equal to %lu\n",
465 (unsigned long)sizeof (struct vbsf_mount_info_new),
466 (unsigned long)PAGE_SIZE);
467 return -EINVAL;
468 }
469
470 err = register_filesystem (&vboxsf_fs_type);
471 if (err) {
472 LogFunc(("register_filesystem err=%d\n", err));
473 return err;
474 }
475
476 rcVBox = vboxInit ();
477 if (RT_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 (RT_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 (RT_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 " RT_XSTR(VMMDEV_VERSION) ")\n");
500
501 return 0;
502
503 fail2:
504 vboxDisconnect (&client_handle);
505 fail1:
506 vboxUninit ();
507 fail0:
508 unregister_filesystem (&vboxsf_fs_type);
509 return rcRet;
510}
511
512static void __exit
513fini (void)
514{
515 TRACE ();
516
517 vboxDisconnect (&client_handle);
518 vboxUninit ();
519 unregister_filesystem (&vboxsf_fs_type);
520}
521
522module_init (init);
523module_exit (fini);
524
525/* C++ hack */
526int __gxx_personality_v0 = 0xdeadbeef;
527
528#if 0
529/* long long hacks (as far as i can see, gcc emits the refs to those
530 symbols, notwithstanding the fact that those aren't referenced
531 anywhere in the module) */
532void __divdi3 (void)
533{
534 elog ("called from %p\n", __builtin_return_address (0));
535 BUG ();
536}
537
538void __moddi3 (void)
539{
540 elog ("called from %p\n", __builtin_return_address (0));
541 BUG ();
542}
543#endif /* 0 */
544
545/*
546 * Local Variables:
547 * c-mode: linux
548 * indent-tabs-mode: nil
549 * c-basic-offset: 8
550 * End:
551 */
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