VirtualBox

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

Last change on this file since 29038 was 28998, checked in by vboxsync, 15 years ago

Linux Additions: rename the vboxvfs module to vboxsf to make it load by demand of the Linux kernel

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