VirtualBox

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

Last change on this file since 77530 was 77530, checked in by vboxsync, 6 years ago

linux/vboxsf: Use vbxsf as prefix here - part II. bugref:9172

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

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