VirtualBox

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

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

linux/vboxsf: Use 'VBox' as f_type value. NFS_SUPER_MAGIC confuses umount from the debian mount package v2.25.2-6 (debian 8). bugref:9172

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

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