VirtualBox

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

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

linux/vboxsf: Early implementation of file_operations::read_iter to make loop back mounting work of shared folders. bugref:9172 ticketref:17360

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

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