VirtualBox

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

Last change on this file since 4485 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

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