VirtualBox

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

Last change on this file since 53402 was 48941, checked in by vboxsync, 11 years ago

Additions/linux: Whitespace cleanups by scm.

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