VirtualBox

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

最後變更 在這個檔案從77526是 77526,由 vboxsync 提交於 6 年 前

linux/vboxsf: We don't use tabs and our indent size is 4 not 8. Makes this a heck lot easier to maintain. bugref:9172

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 25.3 KB
 
1/* $Id: vfsmod.c 77526 2019-03-01 12:15:29Z vboxsync $ */
2/** @file
3 * vboxsf - VBox Linux Shared Folders VFS, module init/term, super block management.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/**
32 * @note Anyone wishing to make changes here might wish to take a look at
33 * https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfs.txt
34 * which seems to be the closest there is to official documentation on
35 * writing filesystem drivers for Linux.
36 *
37 * See also: http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
38 */
39
40
41/*********************************************************************************************************************************
42* Header Files *
43*********************************************************************************************************************************/
44#include "vfsmod.h"
45#include "version-generated.h"
46#include "revision-generated.h"
47#include "product-generated.h"
48#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
49# include <linux/mount.h>
50#endif
51#include <linux/seq_file.h>
52#include <linux/vfs.h>
53#include <linux/nfs_fs.h> /* for NFS_SUPER_MAGIC */
54#include <iprt/path.h>
55
56
57/*********************************************************************************************************************************
58* Global Variables *
59*********************************************************************************************************************************/
60VBGLSFCLIENT client_handle;
61VBGLSFCLIENT g_SfClient; /* temporary? */
62
63uint32_t g_fHostFeatures = 0; /* temporary? */
64
65/** Protects all the sf_inode_info::HandleList lists. */
66spinlock_t g_SfHandleLock;
67
68#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 52)
69static int g_fFollowSymlinks = 0;
70#endif
71
72/* forward declaration */
73static struct super_operations sf_super_ops;
74
75
76
77/**
78 * Copies options from the mount info structure into @a sf_g.
79 *
80 * This is used both by sf_super_info_alloc() and sf_remount_fs().
81 */
82static void sf_super_info_copy_remount_options(struct vbsf_super_info *sf_g, struct vbsf_mount_info_new *info)
83{
84 sf_g->ttl_msec = info->ttl;
85 if (info->ttl > 0)
86 sf_g->ttl = msecs_to_jiffies(info->ttl);
87 else if (info->ttl == 0 || info->ttl != -1)
88 sf_g->ttl = sf_g->ttl_msec = 0;
89 else
90 sf_g->ttl = msecs_to_jiffies(VBSF_DEFAULT_TTL_MS);
91
92 sf_g->uid = info->uid;
93 sf_g->gid = info->gid;
94
95 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, tag)) {
96 /* new fields */
97 sf_g->dmode = info->dmode;
98 sf_g->fmode = info->fmode;
99 sf_g->dmask = info->dmask;
100 sf_g->fmask = info->fmask;
101 } else {
102 sf_g->dmode = ~0;
103 sf_g->fmode = ~0;
104 }
105
106 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cMaxIoPages)) {
107 AssertCompile(sizeof(sf_g->tag) >= sizeof(info->tag));
108 memcpy(sf_g->tag, info->tag, sizeof(info->tag));
109 sf_g->tag[sizeof(sf_g->tag) - 1] = '\0';
110 } else {
111 sf_g->tag[0] = '\0';
112 }
113
114 /* The max number of pages in an I/O request. This must take into
115 account that the physical heap generally grows in 64 KB chunks,
116 so we should not try push that limit. It also needs to take
117 into account that the host will allocate temporary heap buffers
118 for the I/O bytes we send/receive, so don't push the host heap
119 too hard as we'd have to retry with smaller requests when this
120 happens, which isn't too efficient. */
121 sf_g->cMaxIoPages = RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */,
122 VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT);
123 if ( (unsigned)info->length >= sizeof(struct vbsf_mount_info_new)
124 && info->cMaxIoPages != 0) {
125 if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
126 sf_g->cMaxIoPages = info->cMaxIoPages;
127 else
128 printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n",
129 info->cMaxIoPages, sf_g->cMaxIoPages);
130 }
131}
132
133/* allocate super info, try to map host share */
134static int sf_super_info_alloc(struct vbsf_mount_info_new *info, struct vbsf_super_info **sf_gp)
135{
136 int err, rc;
137 SHFLSTRING *str_name;
138 size_t name_len, str_len;
139 struct vbsf_super_info *sf_g;
140
141 TRACE();
142 sf_g = kmalloc(sizeof(*sf_g), GFP_KERNEL);
143 if (!sf_g) {
144 err = -ENOMEM;
145 LogRelFunc(("could not allocate memory for super info\n"));
146 goto fail0;
147 }
148
149 RT_ZERO(*sf_g);
150
151 if (info->nullchar != '\0'
152 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
153 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
154 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) {
155 err = -EINVAL;
156 goto fail1;
157 }
158
159 info->name[sizeof(info->name) - 1] = 0;
160 info->nls_name[sizeof(info->nls_name) - 1] = 0;
161
162 name_len = strlen(info->name);
163 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
164 str_name = kmalloc(str_len, GFP_KERNEL);
165 if (!str_name) {
166 err = -ENOMEM;
167 LogRelFunc(("could not allocate memory for host name\n"));
168 goto fail1;
169 }
170
171 str_name->u16Length = name_len;
172 str_name->u16Size = name_len + 1;
173 memcpy(str_name->String.utf8, info->name, name_len + 1);
174
175#define _IS_UTF8(_str) (strcmp(_str, "utf8") == 0)
176#define _IS_EMPTY(_str) (strcmp(_str, "") == 0)
177
178 /* Check if NLS charset is valid and not points to UTF8 table */
179 if (info->nls_name[0]) {
180 if (_IS_UTF8(info->nls_name))
181 sf_g->nls = NULL;
182 else {
183 sf_g->nls = load_nls(info->nls_name);
184 if (!sf_g->nls) {
185 err = -EINVAL;
186 LogFunc(("failed to load nls %s\n",
187 info->nls_name));
188 kfree(str_name);
189 goto fail1;
190 }
191 }
192 } else {
193#ifdef CONFIG_NLS_DEFAULT
194 /* If no NLS charset specified, try to load the default
195 * one if it's not points to UTF8. */
196 if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
197 && !_IS_EMPTY(CONFIG_NLS_DEFAULT))
198 sf_g->nls = load_nls_default();
199 else
200 sf_g->nls = NULL;
201#else
202 sf_g->nls = NULL;
203#endif
204 }
205
206#undef _IS_UTF8
207#undef _IS_EMPTY
208
209 rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER,
210 true /*fCaseSensitive*/, &sf_g->map.root);
211 kfree(str_name);
212
213 if (RT_FAILURE(rc)) {
214 err = -EPROTO;
215 LogFunc(("SHFL_FN_MAP_FOLDER failed rc=%Rrc\n", rc));
216 goto fail2;
217 }
218
219 /* The rest is shared with remount. */
220 sf_super_info_copy_remount_options(sf_g, info);
221
222 *sf_gp = sf_g;
223 return 0;
224
225 fail2:
226 if (sf_g->nls)
227 unload_nls(sf_g->nls);
228
229 fail1:
230 kfree(sf_g);
231
232 fail0:
233 return err;
234}
235
236/* unmap the share and free super info [sf_g] */
237static void sf_super_info_free(struct vbsf_super_info *sf_g)
238{
239 int rc;
240
241 TRACE();
242 rc = VbglR0SfHostReqUnmapFolderSimple(sf_g->map.root);
243 if (RT_FAILURE(rc))
244 LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc));
245
246 if (sf_g->nls)
247 unload_nls(sf_g->nls);
248
249 kfree(sf_g);
250}
251
252
253/**
254 * Initialize backing device related matters.
255 */
256static int sf_init_backing_dev(struct super_block *sb, struct vbsf_super_info *sf_g)
257{
258 int rc = 0;
259/** @todo this needs sorting out between 3.19 and 4.11 */
260#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) //&& LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
261 /* Each new shared folder map gets a new uint64_t identifier,
262 * allocated in sequence. We ASSUME the sequence will not wrap. */
263#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
264 static uint64_t s_u64Sequence = 0;
265 uint64_t u64CurrentSequence = ASMAtomicIncU64(&s_u64Sequence);
266#endif
267 struct backing_dev_info *bdi;
268
269# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
270 rc = super_setup_bdi_name(sb, "vboxsf-%llu", (unsigned long long)u64CurrentSequence);
271 if (!rc)
272 bdi = sb->s_bdi;
273 else
274 return rc;
275# else
276 bdi = &sf_g->bdi;
277# endif
278
279 bdi->ra_pages = 0; /* No readahead */
280
281# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
282 bdi->capabilities = 0
283# ifdef BDI_CAP_MAP_DIRECT
284 | BDI_CAP_MAP_DIRECT /* MAP_SHARED */
285# endif
286# ifdef BDI_CAP_MAP_COPY
287 | BDI_CAP_MAP_COPY /* MAP_PRIVATE */
288# endif
289# ifdef BDI_CAP_READ_MAP
290 | BDI_CAP_READ_MAP /* can be mapped for reading */
291# endif
292# ifdef BDI_CAP_WRITE_MAP
293 | BDI_CAP_WRITE_MAP /* can be mapped for writing */
294# endif
295# ifdef BDI_CAP_EXEC_MAP
296 | BDI_CAP_EXEC_MAP /* can be mapped for execution */
297# endif
298# ifdef BDI_CAP_STRICTLIMIT
299 | BDI_CAP_STRICTLIMIT;
300# endif
301 ;
302# ifdef BDI_CAP_STRICTLIMIT
303 /* Smalles possible amount of dirty pages: %1 of RAM */
304 bdi_set_max_ratio(bdi, 1);
305# endif
306# endif /* >= 2.6.12 */
307
308# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
309 rc = bdi_init(&sf_g->bdi);
310# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
311 if (!rc)
312 rc = bdi_register(&sf_g->bdi, NULL, "vboxsf-%llu",
313 (unsigned long long)u64CurrentSequence);
314# endif /* >= 2.6.26 */
315# endif /* >= 2.6.24 */
316#endif /* >= 2.6.0 */
317 return rc;
318}
319
320
321/**
322 * Undoes what sf_init_backing_dev did.
323 */
324static void sf_done_backing_dev(struct super_block *sb, struct vbsf_super_info *sf_g)
325{
326#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
327 bdi_destroy(&sf_g->bdi); /* includes bdi_unregister() */
328#endif
329}
330
331
332/**
333 * This is called by sf_read_super_24() and sf_read_super_26() when vfs mounts
334 * the fs and wants to read super_block.
335 *
336 * Calls sf_super_info_alloc() to map the folder and allocate super information
337 * structure.
338 *
339 * Initializes @a sb, initializes root inode and dentry.
340 *
341 * Should respect @a flags.
342 */
343static int sf_read_super_aux(struct super_block *sb, void *data, int flags)
344{
345 int err;
346 struct dentry *droot;
347 struct inode *iroot;
348 struct sf_inode_info *sf_i;
349 struct vbsf_super_info *sf_g;
350 SHFLFSOBJINFO fsinfo;
351 struct vbsf_mount_info_new *info;
352 bool fInodePut = true;
353
354 TRACE();
355 if (!data) {
356 LogFunc(("no mount info specified\n"));
357 return -EINVAL;
358 }
359
360 info = data;
361
362 if (flags & MS_REMOUNT) {
363 LogFunc(("remounting is not supported\n"));
364 return -ENOSYS;
365 }
366
367 err = sf_super_info_alloc(info, &sf_g);
368 if (err)
369 goto fail0;
370
371 sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
372 if (!sf_i) {
373 err = -ENOMEM;
374 LogRelFunc(("could not allocate memory for root inode info\n"));
375 goto fail1;
376 }
377
378 sf_i->handle = SHFL_HANDLE_NIL;
379 sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
380 if (!sf_i->path) {
381 err = -ENOMEM;
382 LogRelFunc(("could not allocate memory for root inode path\n"));
383 goto fail2;
384 }
385
386 sf_i->path->u16Length = 1;
387 sf_i->path->u16Size = 2;
388 sf_i->path->String.utf8[0] = '/';
389 sf_i->path->String.utf8[1] = 0;
390 sf_i->force_reread = 0;
391 RTListInit(&sf_i->HandleList);
392#ifdef VBOX_STRICT
393 sf_i->u32Magic = SF_INODE_INFO_MAGIC;
394#endif
395
396 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
397 if (err) {
398 LogFunc(("could not stat root of share\n"));
399 goto fail3;
400 }
401
402 sb->s_magic = 0xface;
403 sb->s_blocksize = 1024;
404#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
405 /* Required for seek/sendfile (see 'loff_t max' in fs/read_write.c / do_sendfile()). */
406# if defined MAX_LFS_FILESIZE
407 sb->s_maxbytes = MAX_LFS_FILESIZE;
408# elif BITS_PER_LONG == 32
409 sb->s_maxbytes = (loff_t)ULONG_MAX << PAGE_SHIFT;
410# else
411 sb->s_maxbytes = INT64_MAX;
412# endif
413#endif
414 sb->s_op = &sf_super_ops;
415#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
416 sb->s_d_op = &sf_dentry_ops;
417#endif
418
419#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
420 iroot = iget_locked(sb, 0);
421#else
422 iroot = iget(sb, 0);
423#endif
424 if (!iroot) {
425 err = -ENOMEM; /* XXX */
426 LogFunc(("could not get root inode\n"));
427 goto fail3;
428 }
429
430 if (sf_init_backing_dev(sb, sf_g)) {
431 err = -EINVAL;
432 LogFunc(("could not init bdi\n"));
433#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
434 unlock_new_inode(iroot);
435#endif
436 goto fail4;
437 }
438
439 sf_init_inode(iroot, sf_i, &fsinfo, sf_g);
440 SET_INODE_INFO(iroot, sf_i);
441
442#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
443 unlock_new_inode(iroot);
444#endif
445
446#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
447 droot = d_make_root(iroot);
448#else
449 droot = d_alloc_root(iroot);
450#endif
451 if (!droot) {
452 err = -ENOMEM; /* XXX */
453 LogFunc(("d_alloc_root failed\n"));
454#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
455 fInodePut = false;
456#endif
457 goto fail5;
458 }
459
460 sb->s_root = droot;
461 VBSF_SET_SUPER_INFO(sb, sf_g);
462 return 0;
463
464 fail5:
465 sf_done_backing_dev(sb, sf_g);
466
467 fail4:
468 if (fInodePut)
469 iput(iroot);
470
471 fail3:
472 kfree(sf_i->path);
473
474 fail2:
475 kfree(sf_i);
476
477 fail1:
478 sf_super_info_free(sf_g);
479
480 fail0:
481 return err;
482}
483
484
485/**
486 * This is called when vfs is about to destroy the @a inode.
487 *
488 * We must free the inode info structure here.
489 */
490#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
491static void sf_evict_inode(struct inode *inode)
492#else
493static void sf_clear_inode(struct inode *inode)
494#endif
495{
496 struct sf_inode_info *sf_i;
497
498 TRACE();
499
500 /*
501 * Flush stuff.
502 */
503#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
504 truncate_inode_pages(&inode->i_data, 0);
505# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
506 clear_inode(inode);
507# else
508 end_writeback(inode);
509# endif
510#endif
511 /*
512 * Clean up our inode info.
513 */
514 sf_i = GET_INODE_INFO(inode);
515 if (sf_i) {
516 SET_INODE_INFO(inode, NULL);
517
518 Assert(sf_i->u32Magic == SF_INODE_INFO_MAGIC);
519 BUG_ON(!sf_i->path);
520 kfree(sf_i->path);
521 sf_handle_drop_chain(sf_i);
522# ifdef VBOX_STRICT
523 sf_i->u32Magic = SF_INODE_INFO_MAGIC_DEAD;
524# endif
525 kfree(sf_i);
526 }
527}
528
529
530/* this is called by vfs when it wants to populate [inode] with data.
531 the only thing that is known about inode at this point is its index
532 hence we can't do anything here, and let lookup/whatever with the
533 job to properly fill then [inode] */
534#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
535static void sf_read_inode(struct inode *inode)
536{
537}
538#endif
539
540
541/* vfs is done with [sb] (umount called) call [sf_super_info_free] to unmap
542 the folder and free [sf_g] */
543static void sf_put_super(struct super_block *sb)
544{
545 struct vbsf_super_info *sf_g;
546
547 sf_g = VBSF_GET_SUPER_INFO(sb);
548 BUG_ON(!sf_g);
549 sf_done_backing_dev(sb, sf_g);
550 sf_super_info_free(sf_g);
551}
552
553
554/**
555 * Get file system statistics.
556 */
557#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
558static int sf_statfs(struct dentry *dentry, struct kstatfs *stat)
559#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73)
560static int sf_statfs(struct super_block *sb, struct kstatfs *stat)
561#else
562static int sf_statfs(struct super_block *sb, struct statfs *stat)
563#endif
564{
565#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
566 struct super_block *sb = dentry->d_inode->i_sb;
567#endif
568 int rc;
569 VBOXSFVOLINFOREQ *pReq = (VBOXSFVOLINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
570 if (pReq) {
571 SHFLVOLINFO *pVolInfo = &pReq->VolInfo;
572 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(sb);
573 rc = VbglR0SfHostReqQueryVolInfo(sf_g->map.root, pReq, SHFL_HANDLE_ROOT);
574 if (RT_SUCCESS(rc)) {
575 stat->f_type = NFS_SUPER_MAGIC; /** @todo vboxsf type? */
576 stat->f_bsize = pVolInfo->ulBytesPerAllocationUnit;
577#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73)
578 stat->f_frsize = pVolInfo->ulBytesPerAllocationUnit;
579#endif
580 stat->f_blocks = pVolInfo->ullTotalAllocationBytes
581 / pVolInfo->ulBytesPerAllocationUnit;
582 stat->f_bfree = pVolInfo->ullAvailableAllocationBytes
583 / pVolInfo->ulBytesPerAllocationUnit;
584 stat->f_bavail = pVolInfo->ullAvailableAllocationBytes
585 / pVolInfo->ulBytesPerAllocationUnit;
586 stat->f_files = 1000;
587 stat->f_ffree = 1000; /* don't return 0 here since the guest may think
588 * that it is not possible to create any more files */
589 stat->f_fsid.val[0] = 0;
590 stat->f_fsid.val[1] = 0;
591 stat->f_namelen = 255;
592#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
593 stat->f_flags = 0; /* not valid */
594#endif
595 RT_ZERO(stat->f_spare);
596 rc = 0;
597 } else
598 rc = -RTErrConvertToErrno(rc);
599 VbglR0PhysHeapFree(pReq);
600 } else
601 rc = -ENOMEM;
602 return rc;
603}
604
605static int sf_remount_fs(struct super_block *sb, int *flags, char *data)
606{
607#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
608 struct vbsf_super_info *sf_g;
609 struct sf_inode_info *sf_i;
610 struct inode *iroot;
611 SHFLFSOBJINFO fsinfo;
612 int err;
613
614 sf_g = VBSF_GET_SUPER_INFO(sb);
615 BUG_ON(!sf_g);
616 if (data && data[0] != 0) {
617 struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
618 if ( info->nullchar == '\0'
619 && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
620 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
621 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
622 sf_super_info_copy_remount_options(sf_g, info);
623 }
624 }
625
626 iroot = ilookup(sb, 0);
627 if (!iroot)
628 return -ENOSYS;
629
630 sf_i = GET_INODE_INFO(iroot);
631 err = sf_stat(__func__, sf_g, sf_i->path, &fsinfo, 0);
632 BUG_ON(err != 0);
633 sf_init_inode(iroot, sf_i, &fsinfo, sf_g);
634 /*unlock_new_inode(iroot); */
635 return 0;
636#else /* LINUX_VERSION_CODE < 2.4.23 */
637 return -ENOSYS;
638#endif /* LINUX_VERSION_CODE < 2.4.23 */
639}
640
641
642/**
643 * Show mount options.
644 *
645 * This is needed by the VBoxService automounter in order for it to pick up
646 * the the 'tag' option value it sets on its mount.
647 */
648#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
649static int sf_show_options(struct seq_file *m, struct vfsmount *mnt)
650#else
651static int sf_show_options(struct seq_file *m, struct dentry *root)
652#endif
653{
654#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
655 struct super_block *sb = mnt->mnt_sb;
656#else
657 struct super_block *sb = root->d_sb;
658#endif
659 struct vbsf_super_info *sf_g = VBSF_GET_SUPER_INFO(sb);
660 if (sf_g) {
661 seq_printf(m, ",uid=%u,gid=%u,ttl=%d,dmode=0%o,fmode=0%o,dmask=0%o,fmask=0%o,maxiopages=%u",
662 sf_g->uid, sf_g->gid, sf_g->ttl_msec, sf_g->dmode, sf_g->fmode, sf_g->dmask,
663 sf_g->fmask, sf_g->cMaxIoPages);
664 if (sf_g->tag[0] != '\0') {
665 seq_puts(m, ",tag=");
666 seq_escape(m, sf_g->tag, " \t\n\\");
667 }
668 }
669 return 0;
670}
671
672
673/**
674 * Super block operations.
675 */
676static struct super_operations sf_super_ops = {
677#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
678 .clear_inode = sf_clear_inode,
679#else
680 .evict_inode = sf_evict_inode,
681#endif
682#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
683 .read_inode = sf_read_inode,
684#endif
685 .put_super = sf_put_super,
686 .statfs = sf_statfs,
687 .remount_fs = sf_remount_fs,
688 .show_options = sf_show_options
689};
690
691
692/*
693 * File system type related stuff.
694 */
695
696#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 4)
697
698static int sf_read_super_26(struct super_block *sb, void *data, int flags)
699{
700 int err;
701
702 TRACE();
703 err = sf_read_super_aux(sb, data, flags);
704 if (err)
705 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
706
707 return err;
708}
709
710# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
711static struct super_block *sf_get_sb(struct file_system_type *fs_type,
712 int flags, const char *dev_name,
713 void *data)
714{
715 TRACE();
716 return get_sb_nodev(fs_type, flags, data, sf_read_super_26);
717}
718# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
719static int sf_get_sb(struct file_system_type *fs_type, int flags,
720 const char *dev_name, void *data, struct vfsmount *mnt)
721{
722 TRACE();
723 return get_sb_nodev(fs_type, flags, data, sf_read_super_26, mnt);
724}
725# else /* LINUX_VERSION_CODE >= 2.6.39 */
726static struct dentry *sf_mount(struct file_system_type *fs_type, int flags,
727 const char *dev_name, void *data)
728{
729 TRACE();
730 return mount_nodev(fs_type, flags, data, sf_read_super_26);
731}
732# endif /* LINUX_VERSION_CODE >= 2.6.39 */
733
734static struct file_system_type vboxsf_fs_type = {
735 .owner = THIS_MODULE,
736 .name = "vboxsf",
737# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
738 .get_sb = sf_get_sb,
739# else
740 .mount = sf_mount,
741# endif
742 .kill_sb = kill_anon_super
743};
744
745#else /* LINUX_VERSION_CODE < 2.5.4 */
746
747static struct super_block *sf_read_super_24(struct super_block *sb, void *data,
748 int flags)
749{
750 int err;
751
752 TRACE();
753 err = sf_read_super_aux(sb, data, flags);
754 if (err) {
755 printk(KERN_DEBUG "sf_read_super_aux err=%d\n", err);
756 return NULL;
757 }
758
759 return sb;
760}
761
762static DECLARE_FSTYPE(vboxsf_fs_type, "vboxsf", sf_read_super_24, 0);
763
764#endif /* LINUX_VERSION_CODE < 2.5.4 */
765
766
767/* Module initialization/finalization handlers */
768static int __init init(void)
769{
770 int vrc;
771 int rcRet = 0;
772 int err;
773
774 TRACE();
775
776 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
777 printk(KERN_ERR
778 "Mount information structure is too large %lu\n"
779 "Must be less than or equal to %lu\n",
780 (unsigned long)sizeof(struct vbsf_mount_info_new),
781 (unsigned long)PAGE_SIZE);
782 return -EINVAL;
783 }
784
785 /** @todo Init order is wrong, file system reigstration is the very last
786 * thing we should do. */
787 spin_lock_init(&g_SfHandleLock);
788 err = register_filesystem(&vboxsf_fs_type);
789 if (err) {
790 LogFunc(("register_filesystem err=%d\n", err));
791 return err;
792 }
793
794 vrc = VbglR0SfInit();
795 if (RT_FAILURE(vrc)) {
796 LogRelFunc(("VbglR0SfInit failed, vrc=%Rrc\n", vrc));
797 rcRet = -EPROTO;
798 goto fail0;
799 }
800
801 vrc = VbglR0SfConnect(&client_handle);
802 g_SfClient = client_handle; /* temporary */
803 if (RT_FAILURE(vrc)) {
804 LogRelFunc(("VbglR0SfConnect failed, vrc=%Rrc\n", vrc));
805 rcRet = -EPROTO;
806 goto fail1;
807 }
808
809 vrc = VbglR0QueryHostFeatures(&g_fHostFeatures);
810 if (RT_FAILURE(vrc))
811 {
812 LogRelFunc(("VbglR0QueryHostFeatures failed: vrc=%Rrc (ignored)\n", vrc));
813 g_fHostFeatures = 0;
814 }
815 LogRelFunc(("g_fHostFeatures=%#x\n", g_fHostFeatures));
816
817 vrc = VbglR0SfSetUtf8(&client_handle);
818 if (RT_FAILURE(vrc)) {
819 LogRelFunc(("VbglR0SfSetUtf8 failed, vrc=%Rrc\n", vrc));
820 rcRet = -EPROTO;
821 goto fail2;
822 }
823#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
824 if (!g_fFollowSymlinks) {
825 vrc = VbglR0SfSetSymlinks(&client_handle);
826 if (RT_FAILURE(vrc)) {
827 printk(KERN_WARNING
828 "vboxsf: Host unable to show symlinks, vrc=%d\n",
829 vrc);
830 }
831 }
832#endif
833
834 printk(KERN_DEBUG
835 "vboxsf: Successfully loaded version " VBOX_VERSION_STRING
836 " (interface " RT_XSTR(VMMDEV_VERSION) ")\n");
837
838 return 0;
839
840 fail2:
841 VbglR0SfDisconnect(&client_handle);
842 g_SfClient = client_handle; /* temporary */
843
844 fail1:
845 VbglR0SfTerm();
846
847 fail0:
848 unregister_filesystem(&vboxsf_fs_type);
849 return rcRet;
850}
851
852static void __exit fini(void)
853{
854 TRACE();
855
856 VbglR0SfDisconnect(&client_handle);
857 g_SfClient = client_handle; /* temporary */
858 VbglR0SfTerm();
859 unregister_filesystem(&vboxsf_fs_type);
860}
861
862
863/*
864 * Module parameters.
865 */
866#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 52)
867module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0);
868MODULE_PARM_DESC(follow_symlinks,
869 "Let host resolve symlinks rather than showing them");
870#endif
871
872
873/*
874 * Module declaration related bits.
875 */
876module_init(init);
877module_exit(fini);
878
879MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
880MODULE_AUTHOR(VBOX_VENDOR);
881MODULE_LICENSE("GPL and additional rights");
882#ifdef MODULE_ALIAS_FS
883MODULE_ALIAS_FS("vboxsf");
884#endif
885#ifdef MODULE_VERSION
886MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
887#endif
888
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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