VirtualBox

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

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

linux/vboxsf: Code cleanups in the super block info area. bugref:9172

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