VirtualBox

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

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

linux/vboxsf: Removed old buffered directory content code (VBSF_BUFFER_DIRS). bugref:9172

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