VirtualBox

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

Last change on this file since 43133 was 43050, checked in by vboxsync, 13 years ago

GA: Linux: Shared Folders driver: If no NLS charset specified, try to load the default one.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette