VirtualBox

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

Last change on this file was 103788, checked in by vboxsync, 2 months ago

Linux Additions: Add possiblity to prevent kernel modules from loading in kernel command line, bugref:8409.

Add to kernel command line either vboxguest.disabled=1 and/or vboxsf.disabled=1
and/or vboxvideo.disabled=1 in order to prevent certain module or all of them
from loading during system boot.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 57.4 KB
Line 
1/* $Id: vfsmod.c 103788 2024-03-11 17:50:25Z vboxsync $ */
2/** @file
3 * vboxsf - VBox Linux Shared Folders VFS, module init/term, super block management.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
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 RTLNX_VER_MIN(5,0,0) || RTLNX_RHEL_MIN(8,4)
49# include <uapi/linux/mount.h> /* for MS_REMOUNT */
50#elif RTLNX_VER_MAX(3,3,0)
51# include <linux/mount.h>
52#endif
53#include <linux/seq_file.h>
54#include <linux/vfs.h>
55#if RTLNX_VER_RANGE(2,5,62, 5,8,0)
56# include <linux/vermagic.h>
57#endif
58#include <VBox/err.h>
59#include <iprt/path.h>
60#if RTLNX_VER_MIN(5,1,0)
61# include <linux/fs_context.h>
62# include <linux/fs_parser.h>
63#elif RTLNX_VER_MIN(2,6,0)
64# include <linux/parser.h>
65#endif
66#include <VBox/VBoxLnxModInline.h>
67
68
69/*********************************************************************************************************************************
70* Defined Constants And Macros *
71*********************************************************************************************************************************/
72#define VBSF_DEFAULT_MAX_IO_PAGES RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */, VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
73#define VBSF_DEFAULT_DIR_BUF_SIZE _64K
74
75
76/*********************************************************************************************************************************
77* Global Variables *
78*********************************************************************************************************************************/
79VBGLSFCLIENT g_SfClient;
80uint32_t g_fHostFeatures = 0;
81/** Last valid shared folders function number. */
82uint32_t g_uSfLastFunction = SHFL_FN_SET_FILE_SIZE;
83/** Shared folders features (SHFL_FEATURE_XXX). */
84uint64_t g_fSfFeatures = 0;
85
86/** Protects all the vbsf_inode_info::HandleList lists. */
87spinlock_t g_SfHandleLock;
88
89/** The 'follow_symlinks' module parameter.
90 * @todo Figure out how do this for 2.4.x! */
91static int g_fFollowSymlinks = 0;
92
93/* forward declaration */
94static struct super_operations g_vbsf_super_ops;
95
96
97
98/**
99 * Copies options from the mount info structure into @a pSuperInfo.
100 *
101 * This is used both by vbsf_super_info_alloc_and_map_it() and
102 * vbsf_remount_fs().
103 */
104static void vbsf_super_info_copy_remount_options(struct vbsf_super_info *pSuperInfo, struct vbsf_mount_info_new *info)
105{
106 pSuperInfo->uid = info->uid;
107 pSuperInfo->gid = info->gid;
108
109 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, szTag)) {
110 /* new fields */
111 pSuperInfo->dmode = info->dmode;
112 pSuperInfo->fmode = info->fmode;
113 pSuperInfo->dmask = info->dmask;
114 pSuperInfo->fmask = info->fmask;
115 } else {
116 pSuperInfo->dmode = ~0;
117 pSuperInfo->fmode = ~0;
118 }
119
120 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cMaxIoPages)) {
121 AssertCompile(sizeof(pSuperInfo->szTag) >= sizeof(info->szTag));
122 RT_BCOPY_UNFORTIFIED(pSuperInfo->szTag, info->szTag, sizeof(info->szTag));
123 pSuperInfo->szTag[sizeof(pSuperInfo->szTag) - 1] = '\0';
124 } else {
125 pSuperInfo->szTag[0] = '\0';
126 }
127
128 /* The max number of pages in an I/O request. This must take into
129 account that the physical heap generally grows in 64 KB chunks,
130 so we should not try push that limit. It also needs to take
131 into account that the host will allocate temporary heap buffers
132 for the I/O bytes we send/receive, so don't push the host heap
133 too hard as we'd have to retry with smaller requests when this
134 happens, which isn't too efficient. */
135 pSuperInfo->cMaxIoPages = VBSF_DEFAULT_MAX_IO_PAGES;
136 if ( (unsigned)info->length >= sizeof(struct vbsf_mount_info_new)
137 && info->cMaxIoPages > 0) {
138 if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
139 pSuperInfo->cMaxIoPages = RT_MAX(info->cMaxIoPages, 2); /* read_iter/write_iter requires a minimum of 2. */
140 else
141 printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n",
142 info->cMaxIoPages, pSuperInfo->cMaxIoPages);
143 }
144
145 pSuperInfo->cbDirBuf = VBSF_DEFAULT_DIR_BUF_SIZE;
146 if ( (unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cbDirBuf)
147 && info->cbDirBuf > 0) {
148 if (info->cbDirBuf <= _16M)
149 pSuperInfo->cbDirBuf = RT_ALIGN_32(info->cbDirBuf, PAGE_SIZE);
150 else
151 printk(KERN_WARNING "vboxsf: max directory buffer size (%#x) is out of range, using default (%#x) instead.\n",
152 info->cMaxIoPages, pSuperInfo->cMaxIoPages);
153 }
154
155 /*
156 * TTLs.
157 */
158 pSuperInfo->msTTL = info->ttl;
159 if (info->ttl > 0)
160 pSuperInfo->cJiffiesDirCacheTTL = msecs_to_jiffies(info->ttl);
161 else if (info->ttl == 0 || info->ttl != -1)
162 pSuperInfo->cJiffiesDirCacheTTL = pSuperInfo->msTTL = 0;
163 else
164 pSuperInfo->cJiffiesDirCacheTTL = msecs_to_jiffies(VBSF_DEFAULT_TTL_MS);
165 pSuperInfo->cJiffiesInodeTTL = pSuperInfo->cJiffiesDirCacheTTL;
166
167 pSuperInfo->msDirCacheTTL = -1;
168 if ( (unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, msDirCacheTTL)
169 && info->msDirCacheTTL >= 0) {
170 if (info->msDirCacheTTL > 0) {
171 pSuperInfo->msDirCacheTTL = info->msDirCacheTTL;
172 pSuperInfo->cJiffiesDirCacheTTL = msecs_to_jiffies(info->msDirCacheTTL);
173 } else {
174 pSuperInfo->msDirCacheTTL = 0;
175 pSuperInfo->cJiffiesDirCacheTTL = 0;
176 }
177 }
178
179 pSuperInfo->msInodeTTL = -1;
180 if ( (unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, msInodeTTL)
181 && info->msInodeTTL >= 0) {
182 if (info->msInodeTTL > 0) {
183 pSuperInfo->msInodeTTL = info->msInodeTTL;
184 pSuperInfo->cJiffiesInodeTTL = msecs_to_jiffies(info->msInodeTTL);
185 } else {
186 pSuperInfo->msInodeTTL = 0;
187 pSuperInfo->cJiffiesInodeTTL = 0;
188 }
189 }
190
191 /*
192 * Caching.
193 */
194 pSuperInfo->enmCacheMode = kVbsfCacheMode_Strict;
195 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, enmCacheMode)) {
196 switch (info->enmCacheMode) {
197 case kVbsfCacheMode_Default:
198 case kVbsfCacheMode_Strict:
199 break;
200 case kVbsfCacheMode_None:
201 case kVbsfCacheMode_Read:
202 case kVbsfCacheMode_ReadWrite:
203 pSuperInfo->enmCacheMode = info->enmCacheMode;
204 break;
205 default:
206 printk(KERN_WARNING "vboxsf: cache mode (%#x) is out of range, using default instead.\n", info->enmCacheMode);
207 break;
208 }
209 }
210}
211
212/**
213 * Allocate the super info structure and try map the host share.
214 */
215static int vbsf_super_info_alloc_and_map_it(struct vbsf_mount_info_new *info, struct vbsf_super_info **sf_gp)
216{
217 int rc;
218 SHFLSTRING *str_name;
219 size_t name_len, str_len;
220 struct vbsf_super_info *pSuperInfo;
221
222 TRACE();
223 *sf_gp = NULL; /* (old gcc maybe used initialized) */
224
225 name_len = RTStrNLen(info->name, sizeof(info->name));
226 if (name_len >= sizeof(info->name)) {
227 SFLOGRELBOTH(("vboxsf: Specified shared folder name is not zero terminated!\n"));
228 return -EINVAL;
229 }
230 if (RTStrNLen(info->nls_name, sizeof(info->nls_name)) >= sizeof(info->nls_name)) {
231 SFLOGRELBOTH(("vboxsf: Specified nls name is not zero terminated!\n"));
232 return -EINVAL;
233 }
234
235 /*
236 * Allocate memory.
237 */
238 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
239 str_name = (PSHFLSTRING)kmalloc(str_len, GFP_KERNEL);
240 pSuperInfo = (struct vbsf_super_info *)kmalloc(sizeof(*pSuperInfo), GFP_KERNEL);
241 if (pSuperInfo && str_name) {
242 RT_ZERO(*pSuperInfo);
243
244 str_name->u16Length = name_len;
245 str_name->u16Size = name_len + 1;
246 RT_BCOPY_UNFORTIFIED(str_name->String.utf8, info->name, name_len + 1);
247
248 /*
249 * Init the NLS support, if needed.
250 */
251 rc = 0;
252#define _IS_UTF8(_str) (strcmp(_str, "utf8") == 0)
253#define _IS_EMPTY(_str) (strcmp(_str, "") == 0)
254
255 /* Check if NLS charset is valid and not points to UTF8 table */
256 pSuperInfo->fNlsIsUtf8 = true;
257 if (info->nls_name[0]) {
258 if (_IS_UTF8(info->nls_name)) {
259 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=utf8\n"));
260 pSuperInfo->nls = NULL;
261 } else {
262 pSuperInfo->fNlsIsUtf8 = false;
263 pSuperInfo->nls = load_nls(info->nls_name);
264 if (pSuperInfo->nls) {
265 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=%s -> %p\n", info->nls_name, pSuperInfo->nls));
266 } else {
267 SFLOGRELBOTH(("vboxsf: Failed to load nls '%s'!\n", info->nls_name));
268 rc = -EINVAL;
269 }
270 }
271 } else {
272#ifdef CONFIG_NLS_DEFAULT
273 /* If no NLS charset specified, try to load the default
274 * one if it's not points to UTF8. */
275 if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
276 && !_IS_EMPTY(CONFIG_NLS_DEFAULT)) {
277 pSuperInfo->fNlsIsUtf8 = false;
278 pSuperInfo->nls = load_nls_default();
279 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: CONFIG_NLS_DEFAULT=%s -> %p\n", CONFIG_NLS_DEFAULT, pSuperInfo->nls));
280 } else {
281 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=utf8 (default %s)\n", CONFIG_NLS_DEFAULT));
282 pSuperInfo->nls = NULL;
283 }
284#else
285 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=utf8 (no default)\n"));
286 pSuperInfo->nls = NULL;
287#endif
288 }
289#undef _IS_UTF8
290#undef _IS_EMPTY
291 if (rc == 0) {
292 /*
293 * Try mount it.
294 */
295 rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER,
296 true /*fCaseSensitive*/, &pSuperInfo->map.root);
297 if (RT_SUCCESS(rc)) {
298 kfree(str_name);
299
300 /* The rest is shared with remount. */
301 vbsf_super_info_copy_remount_options(pSuperInfo, info);
302
303 *sf_gp = pSuperInfo;
304 return 0;
305 }
306
307 /*
308 * bail out:
309 */
310 if (rc == VERR_FILE_NOT_FOUND) {
311 LogRel(("vboxsf: SHFL_FN_MAP_FOLDER failed for '%s': share not found\n", info->name));
312 rc = -ENXIO;
313 } else {
314 LogRel(("vboxsf: SHFL_FN_MAP_FOLDER failed for '%s': %Rrc\n", info->name, rc));
315 rc = -EPROTO;
316 }
317 if (pSuperInfo->nls)
318 unload_nls(pSuperInfo->nls);
319 }
320 } else {
321 SFLOGRELBOTH(("vboxsf: Could not allocate memory for super info!\n"));
322 rc = -ENOMEM;
323 }
324 if (str_name)
325 kfree(str_name);
326 if (pSuperInfo)
327 kfree(pSuperInfo);
328 return rc;
329}
330
331/* unmap the share and free super info [pSuperInfo] */
332static void vbsf_super_info_free(struct vbsf_super_info *pSuperInfo)
333{
334 int rc;
335
336 TRACE();
337 rc = VbglR0SfHostReqUnmapFolderSimple(pSuperInfo->map.root);
338 if (RT_FAILURE(rc))
339 LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc));
340
341 if (pSuperInfo->nls)
342 unload_nls(pSuperInfo->nls);
343
344 kfree(pSuperInfo);
345}
346
347
348/**
349 * Initialize backing device related matters.
350 */
351static int vbsf_init_backing_dev(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
352{
353 int rc = 0;
354#if RTLNX_VER_MIN(2,6,0)
355 /* Each new shared folder map gets a new uint64_t identifier,
356 * allocated in sequence. We ASSUME the sequence will not wrap. */
357# if RTLNX_VER_MIN(2,6,26)
358 static uint64_t s_u64Sequence = 0;
359 uint64_t idSeqMine = ASMAtomicIncU64(&s_u64Sequence);
360# endif
361 struct backing_dev_info *bdi;
362
363# if RTLNX_VER_RANGE(4,0,0, 4,2,0)
364 pSuperInfo->bdi_org = sb->s_bdi;
365# endif
366
367# if RTLNX_VER_MIN(4,12,0)
368 rc = super_setup_bdi_name(sb, "vboxsf-%llu", (unsigned long long)idSeqMine);
369 if (!rc)
370 bdi = sb->s_bdi;
371 else
372 return rc;
373# else
374 bdi = &pSuperInfo->bdi;
375# endif
376
377 bdi->ra_pages = 0; /* No readahead */
378
379# if RTLNX_VER_MIN(2,6,12)
380 bdi->capabilities = 0
381# ifdef BDI_CAP_MAP_DIRECT
382 | BDI_CAP_MAP_DIRECT /* MAP_SHARED */
383# endif
384# ifdef BDI_CAP_MAP_COPY
385 | BDI_CAP_MAP_COPY /* MAP_PRIVATE */
386# endif
387# ifdef BDI_CAP_READ_MAP
388 | BDI_CAP_READ_MAP /* can be mapped for reading */
389# endif
390# ifdef BDI_CAP_WRITE_MAP
391 | BDI_CAP_WRITE_MAP /* can be mapped for writing */
392# endif
393# ifdef BDI_CAP_EXEC_MAP
394 | BDI_CAP_EXEC_MAP /* can be mapped for execution */
395# endif
396# ifdef BDI_CAP_STRICTLIMIT
397# if RTLNX_VER_MIN(4,19,0) /* Trouble with 3.16.x/debian8. Process stops after dirty page throttling.
398 * Only tested successfully with 4.19. Maybe skip altogether? */
399 | BDI_CAP_STRICTLIMIT;
400# endif
401# endif
402 ;
403# ifdef BDI_CAP_STRICTLIMIT
404 /* Smalles possible amount of dirty pages: %1 of RAM. We set this to
405 try reduce amount of data that's out of sync with the host side.
406 Besides, writepages isn't implemented, so flushing is extremely slow.
407 Note! Extremely slow linux 3.0.0 msync doesn't seem to be related to this setting. */
408 bdi_set_max_ratio(bdi, 1);
409# endif
410# endif /* >= 2.6.12 */
411
412# if RTLNX_VER_RANGE(2,6,24, 4,12,0)
413 rc = bdi_init(&pSuperInfo->bdi);
414# if RTLNX_VER_MIN(2,6,26)
415 if (!rc)
416 rc = bdi_register(&pSuperInfo->bdi, NULL, "vboxsf-%llu", (unsigned long long)idSeqMine);
417# endif /* >= 2.6.26 */
418# endif /* 4.11.0 > version >= 2.6.24 */
419
420# if RTLNX_VER_RANGE(2,6,34, 4,12,0)
421 if (!rc)
422 sb->s_bdi = bdi;
423# endif
424
425#endif /* >= 2.6.0 */
426 return rc;
427}
428
429
430/**
431 * Undoes what vbsf_init_backing_dev did.
432 */
433static void vbsf_done_backing_dev(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
434{
435#if RTLNX_VER_RANGE(2,6,24, 4,12,0)
436 bdi_destroy(&pSuperInfo->bdi); /* includes bdi_unregister() */
437
438 /* Paranoia: Make sb->s_bdi not point at pSuperInfo->bdi, in case someone
439 trouches it after this point (we may screw up something). */
440# if RTLNX_VER_RANGE(4,0,0, 4,2,0)
441 sb->s_bdi = pSuperInfo->bdi_org; /* (noop_backing_dev_info is not exported) */
442# elif RTLNX_VER_RANGE(2,6,34, 4,10,0)
443 sb->s_bdi = &noop_backing_dev_info;
444# endif
445#endif
446}
447
448
449/**
450 * Creates the root inode and attaches it to the super block.
451 *
452 * @returns 0 on success, negative errno on failure.
453 * @param sb The super block.
454 * @param pSuperInfo Our super block info.
455 */
456static int vbsf_create_root_inode(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
457{
458 SHFLFSOBJINFO fsinfo;
459 int rc;
460
461 /*
462 * Allocate and initialize the memory for our inode info structure.
463 */
464 struct vbsf_inode_info *sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
465 SHFLSTRING *path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
466 if (sf_i && path) {
467 sf_i->handle = SHFL_HANDLE_NIL;
468 sf_i->force_restat = false;
469 RTListInit(&sf_i->HandleList);
470#ifdef VBOX_STRICT
471 sf_i->u32Magic = SF_INODE_INFO_MAGIC;
472#endif
473 sf_i->path = path;
474
475 path->u16Length = 1;
476 path->u16Size = 2;
477 RTStrCopy(path->String.utf8, path->u16Size, "/");
478
479 /*
480 * Stat the root directory (for inode info).
481 */
482 rc = vbsf_stat(__func__, pSuperInfo, sf_i->path, &fsinfo, 0);
483 if (rc == 0) {
484 /*
485 * Create the actual inode structure.
486 * Note! ls -la does display '.' and '..' entries with st_ino == 0, so root is #1.
487 */
488#if RTLNX_VER_MIN(2,4,25)
489 struct inode *iroot = iget_locked(sb, 1);
490#else
491 struct inode *iroot = iget(sb, 1);
492#endif
493 if (iroot) {
494 vbsf_init_inode(iroot, sf_i, &fsinfo, pSuperInfo);
495 VBSF_SET_INODE_INFO(iroot, sf_i);
496
497#if RTLNX_VER_MIN(2,4,25)
498 unlock_new_inode(iroot);
499#endif
500
501 /*
502 * Now make it a root inode.
503 */
504#if RTLNX_VER_MIN(3,4,0)
505 sb->s_root = d_make_root(iroot);
506#else
507 sb->s_root = d_alloc_root(iroot);
508#endif
509 if (sb->s_root) {
510
511 return 0;
512 }
513
514 SFLOGRELBOTH(("vboxsf: d_make_root failed!\n"));
515#if RTLNX_VER_MAX(3,4,0) /* d_make_root calls iput */
516 iput(iroot);
517#endif
518 /* iput() will call vbsf_evict_inode()/vbsf_clear_inode(). */
519 sf_i = NULL;
520 path = NULL;
521
522 rc = -ENOMEM;
523 } else {
524 SFLOGRELBOTH(("vboxsf: failed to allocate root inode!\n"));
525 rc = -ENOMEM;
526 }
527 } else
528 SFLOGRELBOTH(("vboxsf: could not stat root of share: %d\n", rc));
529 } else {
530 SFLOGRELBOTH(("vboxsf: Could not allocate memory for root inode info!\n"));
531 rc = -ENOMEM;
532 }
533 if (sf_i)
534 kfree(sf_i);
535 if (path)
536 kfree(path);
537 return rc;
538}
539
540
541#if RTLNX_VER_MAX(5,1,0)
542static void vbsf_init_mount_info(struct vbsf_mount_info_new *mount_info,
543 const char *sf_name)
544{
545 mount_info->ttl = mount_info->msDirCacheTTL = mount_info->msInodeTTL = -1;
546 mount_info->dmode = mount_info->fmode = ~0U;
547 mount_info->enmCacheMode = kVbsfCacheMode_Strict;
548 mount_info->length = sizeof(struct vbsf_mount_info_new);
549 if (sf_name) {
550# if RTLNX_VER_MAX(2,5,69)
551 strncpy(mount_info->name, sf_name, sizeof(mount_info->name));
552 mount_info->name[sizeof(mount_info->name)-1] = 0;
553# else
554 strlcpy(mount_info->name, sf_name, sizeof(mount_info->name));
555# endif
556 }
557}
558#endif
559
560#if RTLNX_VER_RANGE(2,6,0, 5,1,0)
561/**
562 * The following section of code uses the Linux match_token() family of
563 * routines to parse string-based mount options.
564 */
565enum {
566 Opt_iocharset, /* nls_name[] */
567 Opt_nls, /* alias for iocharset */
568 Opt_uid,
569 Opt_gid,
570 Opt_ttl,
571 Opt_dmode,
572 Opt_fmode,
573 Opt_dmask,
574 Opt_fmask,
575 Opt_umask,
576 Opt_maxiopages,
577 Opt_dirbuf,
578 Opt_dcachettl,
579 Opt_inodettl,
580 Opt_cachemode, /* enum vbsf_cache_mode */
581 Opt_tag,
582 Opt_err
583};
584
585# if RTLNX_VER_MAX(2,6,28)
586static match_table_t vbsf_tokens = {
587# else
588static const match_table_t vbsf_tokens = {
589# endif
590 { Opt_iocharset, "iocharset=%s" },
591 { Opt_nls, "nls=%s" },
592 { Opt_uid, "uid=%u" },
593 { Opt_gid, "gid=%u" },
594 { Opt_ttl, "ttl=%u" },
595 { Opt_dmode, "dmode=%o" },
596 { Opt_fmode, "fmode=%o" },
597 { Opt_dmask, "dmask=%o" },
598 { Opt_fmask, "fmask=%o" },
599 { Opt_umask, "umask=%o" },
600 { Opt_maxiopages, "maxiopages=%u" },
601 { Opt_dirbuf, "dirbuf=%u" },
602 { Opt_dcachettl, "dcachettl=%u" },
603 { Opt_inodettl, "inodettl=%u" },
604 { Opt_cachemode, "cache=%s" },
605 { Opt_tag, "tag=%s" }, /* private option for automounter */
606 { Opt_err, NULL }
607};
608
609static int vbsf_parse_mount_options(char *options,
610 struct vbsf_mount_info_new *mount_info)
611{
612 substring_t args[MAX_OPT_ARGS];
613 int option;
614 int token;
615 char *p;
616 char *iocharset;
617 char *cachemode;
618 char *tag;
619
620 if (!options)
621 return -EINVAL;
622
623 while ((p = strsep(&options, ",")) != NULL) {
624 if (!*p)
625 continue;
626
627 token = match_token(p, vbsf_tokens, args);
628 switch (token) {
629 case Opt_iocharset:
630 case Opt_nls:
631 iocharset = match_strdup(&args[0]);
632 if (!iocharset) {
633 SFLOGRELBOTH(("vboxsf: Could not allocate memory for iocharset!\n"));
634 return -ENOMEM;
635 }
636 strlcpy(mount_info->nls_name, iocharset,
637 sizeof(mount_info->nls_name));
638 kfree(iocharset);
639 break;
640 case Opt_uid:
641 if (match_int(&args[0], &option))
642 return -EINVAL;
643 mount_info->uid = option;
644 break;
645 case Opt_gid:
646 if (match_int(&args[0], &option))
647 return -EINVAL;
648 mount_info->gid = option;
649 break;
650 case Opt_ttl:
651 if (match_int(&args[0], &option))
652 return -EINVAL;
653 mount_info->ttl = option;
654 break;
655 case Opt_dmode:
656 if (match_octal(&args[0], &option))
657 return -EINVAL;
658 mount_info->dmode = option;
659 break;
660 case Opt_fmode:
661 if (match_octal(&args[0], &option))
662 return -EINVAL;
663 mount_info->fmode = option;
664 break;
665 case Opt_dmask:
666 if (match_octal(&args[0], &option))
667 return -EINVAL;
668 mount_info->dmask = option;
669 break;
670 case Opt_fmask:
671 if (match_octal(&args[0], &option))
672 return -EINVAL;
673 mount_info->fmask = option;
674 break;
675 case Opt_umask:
676 if (match_octal(&args[0], &option))
677 return -EINVAL;
678 mount_info->dmask = mount_info->fmask = option;
679 break;
680 case Opt_maxiopages:
681 if (match_int(&args[0], &option))
682 return -EINVAL;
683 mount_info->cMaxIoPages = option;
684 break;
685 case Opt_dirbuf:
686 if (match_int(&args[0], &option))
687 return -EINVAL;
688 mount_info->cbDirBuf = option;
689 break;
690 case Opt_dcachettl:
691 if (match_int(&args[0], &option))
692 return -EINVAL;
693 mount_info->msDirCacheTTL = option;
694 break;
695 case Opt_inodettl:
696 if (match_int(&args[0], &option))
697 return -EINVAL;
698 mount_info->msInodeTTL = option;
699 break;
700 case Opt_cachemode: {
701 cachemode = match_strdup(&args[0]);
702 if (!cachemode) {
703 SFLOGRELBOTH(("vboxsf: Could not allocate memory for cachemode!\n"));
704 return -ENOMEM;
705 }
706 if (!strcmp(cachemode, "default") || !strcmp(cachemode, "strict"))
707 mount_info->enmCacheMode = kVbsfCacheMode_Strict;
708 else if (!strcmp(cachemode, "none"))
709 mount_info->enmCacheMode = kVbsfCacheMode_None;
710 else if (!strcmp(cachemode, "read"))
711 mount_info->enmCacheMode = kVbsfCacheMode_Read;
712 else if (!strcmp(cachemode, "readwrite"))
713 mount_info->enmCacheMode = kVbsfCacheMode_ReadWrite;
714 else
715 printk(KERN_WARNING "vboxsf: cache mode (%s) is out of range, using default instead.\n", cachemode);
716 kfree(cachemode);
717 break;
718 }
719 case Opt_tag:
720 tag = match_strdup(&args[0]);
721 if (!tag) {
722 SFLOGRELBOTH(("vboxsf: Could not allocate memory for automount tag!\n"));
723 return -ENOMEM;
724 }
725 strlcpy(mount_info->szTag, tag, sizeof(mount_info->szTag));
726 kfree(tag);
727 break;
728 default:
729 printk(KERN_ERR "unrecognised mount option \"%s\"", p);
730 return -EINVAL;
731 }
732 }
733
734 return 0;
735}
736#endif /* 5.1.0 > version >= 2.6.0 */
737
738
739#if RTLNX_VER_MAX(2,6,0)
740/**
741 * Linux kernel versions older than 2.6.0 don't have the match_token() routines
742 * so we parse the string-based mount options manually here.
743 */
744static int vbsf_parse_mount_options(char *options,
745 struct vbsf_mount_info_new *mount_info)
746{
747 char *value;
748 char *option;
749
750 if (!options)
751 return -EINVAL;
752
753# if RTLNX_VER_MIN(2,3,9)
754 while ((option = strsep(&options, ",")) != NULL) {
755# else
756 for (option = strtok(options, ","); option; option = strtok(NULL, ",")) {
757# endif
758 if (!*option)
759 continue;
760
761 value = strchr(option, '=');
762 if (value)
763 *value++ = '\0';
764
765 if (!strcmp(option, "iocharset") || !strcmp(option, "nls")) {
766 if (!value || !*value)
767 return -EINVAL;
768 strncpy(mount_info->nls_name, value, sizeof(mount_info->nls_name));
769 mount_info->nls_name[sizeof(mount_info->nls_name)-1] = 0;
770 } else if (!strcmp(option, "uid")) {
771 mount_info->uid = simple_strtoul(value, &value, 0);
772 if (*value)
773 return -EINVAL;
774 } else if (!strcmp(option, "gid")) {
775 mount_info->gid = simple_strtoul(value, &value, 0);
776 if (*value)
777 return -EINVAL;
778 } else if (!strcmp(option, "ttl")) {
779 mount_info->ttl = simple_strtoul(value, &value, 0);
780 if (*value)
781 return -EINVAL;
782 } else if (!strcmp(option, "dmode")) {
783 mount_info->dmode = simple_strtoul(value, &value, 8);
784 if (*value)
785 return -EINVAL;
786 } else if (!strcmp(option, "fmode")) {
787 mount_info->fmode = simple_strtoul(value, &value, 8);
788 if (*value)
789 return -EINVAL;
790 } else if (!strcmp(option, "dmask")) {
791 mount_info->dmask = simple_strtoul(value, &value, 8);
792 if (*value)
793 return -EINVAL;
794 } else if (!strcmp(option, "fmask")) {
795 mount_info->fmask = simple_strtoul(value, &value, 8);
796 if (*value)
797 return -EINVAL;
798 } else if (!strcmp(option, "umask")) {
799 mount_info->dmask = mount_info->fmask = simple_strtoul(value,
800 &value, 8);
801 if (*value)
802 return -EINVAL;
803 } else if (!strcmp(option, "maxiopages")) {
804 mount_info->cMaxIoPages = simple_strtoul(value, &value, 0);
805 if (*value)
806 return -EINVAL;
807 } else if (!strcmp(option, "dirbuf")) {
808 mount_info->cbDirBuf = simple_strtoul(value, &value, 0);
809 if (*value)
810 return -EINVAL;
811 } else if (!strcmp(option, "dcachettl")) {
812 mount_info->msDirCacheTTL = simple_strtoul(value, &value, 0);
813 if (*value)
814 return -EINVAL;
815 } else if (!strcmp(option, "inodettl")) {
816 mount_info->msInodeTTL = simple_strtoul(value, &value, 0);
817 if (*value)
818 return -EINVAL;
819 } else if (!strcmp(option, "cache")) {
820 if (!value || !*value)
821 return -EINVAL;
822 if (!strcmp(value, "default") || !strcmp(value, "strict"))
823 mount_info->enmCacheMode = kVbsfCacheMode_Strict;
824 else if (!strcmp(value, "none"))
825 mount_info->enmCacheMode = kVbsfCacheMode_None;
826 else if (!strcmp(value, "read"))
827 mount_info->enmCacheMode = kVbsfCacheMode_Read;
828 else if (!strcmp(value, "readwrite"))
829 mount_info->enmCacheMode = kVbsfCacheMode_ReadWrite;
830 else
831 printk(KERN_WARNING "vboxsf: cache mode (%s) is out of range, using default instead.\n", value);
832 } else if (!strcmp(option, "tag")) {
833 if (!value || !*value)
834 return -EINVAL;
835 strncpy(mount_info->szTag, value, sizeof(mount_info->szTag));
836 mount_info->szTag[sizeof(mount_info->szTag)-1] = 0;
837 } else if (!strcmp(option, "sf_name")) {
838 if (!value || !*value)
839 return -EINVAL;
840 strncpy(mount_info->name, value, sizeof(mount_info->name));
841 mount_info->name[sizeof(mount_info->name)-1] = 0;
842 } else {
843 printk(KERN_ERR "unrecognised mount option \"%s\"", option);
844 return -EINVAL;
845 }
846 }
847
848 return 0;
849}
850#endif
851
852
853/**
854 * This is called by vbsf_read_super_24(), vbsf_read_super_26(), and
855 * vbsf_get_tree() when vfs mounts the fs and wants to read the super_block.
856 *
857 * Calls vbsf_super_info_alloc_and_map_it() to map the folder and allocate super
858 * information structure.
859 *
860 * Initializes @a sb, initializes root inode and dentry.
861 *
862 * Should respect @a flags.
863 */
864#if RTLNX_VER_MIN(5,1,0)
865static int vbsf_read_super_aux(struct super_block *sb, struct fs_context *fc)
866#else
867static int vbsf_read_super_aux(struct super_block *sb, void *data, int flags)
868#endif
869{
870 int rc;
871 struct vbsf_super_info *pSuperInfo;
872
873 TRACE();
874#if RTLNX_VER_MAX(5,1,0)
875 if (!data) {
876 SFLOGRELBOTH(("vboxsf: No mount data. Is mount.vboxsf installed (typically in /sbin)?\n"));
877 return -EINVAL;
878 }
879
880 if (flags & MS_REMOUNT) {
881 SFLOGRELBOTH(("vboxsf: Remounting is not supported!\n"));
882 return -ENOSYS;
883 }
884#endif
885
886 /*
887 * Create our super info structure and map the shared folder.
888 */
889#if RTLNX_VER_MIN(5,1,0)
890 struct vbsf_mount_info_new *info = fc->fs_private;
891 rc = vbsf_super_info_alloc_and_map_it(info, &pSuperInfo);
892#else
893 rc = vbsf_super_info_alloc_and_map_it((struct vbsf_mount_info_new *)data, &pSuperInfo);
894#endif
895 if (rc == 0) {
896 /*
897 * Initialize the super block structure (must be done before
898 * root inode creation).
899 */
900 sb->s_magic = 0xface;
901 sb->s_blocksize = 1024;
902#if RTLNX_VER_MIN(2,4,3)
903 /* Required for seek/sendfile (see 'loff_t max' in fs/read_write.c / do_sendfile()). */
904# if defined MAX_LFS_FILESIZE
905 sb->s_maxbytes = MAX_LFS_FILESIZE;
906# elif BITS_PER_LONG == 32
907 sb->s_maxbytes = (loff_t)ULONG_MAX << PAGE_SHIFT;
908# else
909 sb->s_maxbytes = INT64_MAX;
910# endif
911#endif
912#if RTLNX_VER_MIN(2,6,11)
913 sb->s_time_gran = 1; /* This might be a little optimistic for windows hosts, where it should be 100. */
914#endif
915 sb->s_op = &g_vbsf_super_ops;
916#if RTLNX_VER_MIN(2,6,38)
917 sb->s_d_op = &vbsf_dentry_ops;
918#endif
919
920 /*
921 * Initialize the backing device. This is important for memory mapped
922 * files among other things.
923 */
924 rc = vbsf_init_backing_dev(sb, pSuperInfo);
925 if (rc == 0) {
926 /*
927 * Create the root inode and we're done.
928 */
929 rc = vbsf_create_root_inode(sb, pSuperInfo);
930 if (rc == 0) {
931 VBSF_SET_SUPER_INFO(sb, pSuperInfo);
932 SFLOGFLOW(("vbsf_read_super_aux: returns successfully\n"));
933 return 0;
934 }
935 vbsf_done_backing_dev(sb, pSuperInfo);
936 } else
937 SFLOGRELBOTH(("vboxsf: backing device information initialization failed: %d\n", rc));
938 vbsf_super_info_free(pSuperInfo);
939 }
940 return rc;
941}
942
943
944/**
945 * This is called when vfs is about to destroy the @a inode.
946 *
947 * We must free the inode info structure here.
948 */
949#if RTLNX_VER_MIN(2,6,36)
950static void vbsf_evict_inode(struct inode *inode)
951#else
952static void vbsf_clear_inode(struct inode *inode)
953#endif
954{
955 struct vbsf_inode_info *sf_i;
956
957 TRACE();
958
959 /*
960 * Flush stuff.
961 */
962#if RTLNX_VER_MIN(2,6,36)
963 truncate_inode_pages(&inode->i_data, 0);
964# if RTLNX_VER_MIN(3,5,0)
965 clear_inode(inode);
966# else
967 end_writeback(inode);
968# endif
969#endif
970 /*
971 * Clean up our inode info.
972 */
973 sf_i = VBSF_GET_INODE_INFO(inode);
974 if (sf_i) {
975 VBSF_SET_INODE_INFO(inode, NULL);
976
977 Assert(sf_i->u32Magic == SF_INODE_INFO_MAGIC);
978 BUG_ON(!sf_i->path);
979 kfree(sf_i->path);
980 vbsf_handle_drop_chain(sf_i);
981# ifdef VBOX_STRICT
982 sf_i->u32Magic = SF_INODE_INFO_MAGIC_DEAD;
983# endif
984 kfree(sf_i);
985 }
986}
987
988
989/* this is called by vfs when it wants to populate [inode] with data.
990 the only thing that is known about inode at this point is its index
991 hence we can't do anything here, and let lookup/whatever with the
992 job to properly fill then [inode] */
993#if RTLNX_VER_MAX(2,6,25)
994static void vbsf_read_inode(struct inode *inode)
995{
996}
997#endif
998
999
1000/* vfs is done with [sb] (umount called) call [vbsf_super_info_free] to unmap
1001 the folder and free [pSuperInfo] */
1002static void vbsf_put_super(struct super_block *sb)
1003{
1004 struct vbsf_super_info *pSuperInfo;
1005
1006 pSuperInfo = VBSF_GET_SUPER_INFO(sb);
1007 BUG_ON(!pSuperInfo);
1008 vbsf_done_backing_dev(sb, pSuperInfo);
1009 vbsf_super_info_free(pSuperInfo);
1010}
1011
1012
1013/**
1014 * Get file system statistics.
1015 */
1016#if RTLNX_VER_MIN(2,6,18)
1017static int vbsf_statfs(struct dentry *dentry, struct kstatfs *stat)
1018#elif RTLNX_VER_MIN(2,5,73)
1019static int vbsf_statfs(struct super_block *sb, struct kstatfs *stat)
1020#else
1021static int vbsf_statfs(struct super_block *sb, struct statfs *stat)
1022#endif
1023{
1024#if RTLNX_VER_MIN(2,6,18)
1025 struct super_block *sb = dentry->d_inode->i_sb;
1026#endif
1027 int rc;
1028 VBOXSFVOLINFOREQ *pReq = (VBOXSFVOLINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
1029 if (pReq) {
1030 SHFLVOLINFO *pVolInfo = &pReq->VolInfo;
1031 struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
1032 rc = VbglR0SfHostReqQueryVolInfo(pSuperInfo->map.root, pReq, SHFL_HANDLE_ROOT);
1033 if (RT_SUCCESS(rc)) {
1034 stat->f_type = UINT32_C(0x786f4256); /* 'VBox' little endian */
1035 stat->f_bsize = pVolInfo->ulBytesPerAllocationUnit;
1036#if RTLNX_VER_MIN(2,5,73)
1037 stat->f_frsize = pVolInfo->ulBytesPerAllocationUnit;
1038#endif
1039 stat->f_blocks = pVolInfo->ullTotalAllocationBytes
1040 / pVolInfo->ulBytesPerAllocationUnit;
1041 stat->f_bfree = pVolInfo->ullAvailableAllocationBytes
1042 / pVolInfo->ulBytesPerAllocationUnit;
1043 stat->f_bavail = pVolInfo->ullAvailableAllocationBytes
1044 / pVolInfo->ulBytesPerAllocationUnit;
1045 stat->f_files = 1000;
1046 stat->f_ffree = 1000000; /* don't return 0 here since the guest may think
1047 * that it is not possible to create any more files */
1048 stat->f_fsid.val[0] = 0;
1049 stat->f_fsid.val[1] = 0;
1050 stat->f_namelen = 255;
1051#if RTLNX_VER_MIN(2,6,36)
1052 stat->f_flags = 0; /* not valid */
1053#endif
1054 RT_ZERO(stat->f_spare);
1055 rc = 0;
1056 } else
1057 rc = -RTErrConvertToErrno(rc);
1058 VbglR0PhysHeapFree(pReq);
1059 } else
1060 rc = -ENOMEM;
1061 return rc;
1062}
1063
1064#if RTLNX_VER_MIN(5,1,0)
1065static int vbsf_remount_fs(struct super_block *sb,
1066 struct vbsf_mount_info_new *info)
1067#else
1068static int vbsf_remount_fs(struct super_block *sb, int *flags, char *data)
1069#endif
1070{
1071#if RTLNX_VER_MIN(2,4,23)
1072 struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
1073 struct vbsf_inode_info *sf_i;
1074 struct inode *iroot;
1075 SHFLFSOBJINFO fsinfo;
1076 int err;
1077 Assert(pSuperInfo);
1078
1079# if RTLNX_VER_MIN(5,1,0)
1080 vbsf_super_info_copy_remount_options(pSuperInfo, info);
1081# else
1082 if (VBSF_IS_MOUNT_VBOXSF_DATA(data)) {
1083 vbsf_super_info_copy_remount_options(pSuperInfo, (struct vbsf_mount_info_new *)data);
1084 } else {
1085 struct vbsf_mount_info_new mount_opts = { '\0' };
1086 vbsf_init_mount_info(&mount_opts, NULL);
1087 err = vbsf_parse_mount_options(data, &mount_opts);
1088 if (err)
1089 return err;
1090 vbsf_super_info_copy_remount_options(pSuperInfo, &mount_opts);
1091 }
1092# endif
1093
1094 /* '.' and '..' entries are st_ino == 0 so root is #1 */
1095 iroot = ilookup(sb, 1);
1096 if (!iroot)
1097 return -ENOSYS;
1098
1099 sf_i = VBSF_GET_INODE_INFO(iroot);
1100 err = vbsf_stat(__func__, pSuperInfo, sf_i->path, &fsinfo, 0);
1101 BUG_ON(err != 0);
1102 vbsf_init_inode(iroot, sf_i, &fsinfo, pSuperInfo);
1103 iput(iroot);
1104 return 0;
1105#else /* < 2.4.23 */
1106 return -ENOSYS;
1107#endif /* < 2.4.23 */
1108}
1109
1110
1111/**
1112 * Show mount options.
1113 *
1114 * This is needed by the VBoxService automounter in order for it to pick up
1115 * the the 'szTag' option value it sets on its mount.
1116 */
1117#if RTLNX_VER_MAX(3,3,0)
1118static int vbsf_show_options(struct seq_file *m, struct vfsmount *mnt)
1119#else
1120static int vbsf_show_options(struct seq_file *m, struct dentry *root)
1121#endif
1122{
1123#if RTLNX_VER_MAX(3,3,0)
1124 struct super_block *sb = mnt->mnt_sb;
1125#else
1126 struct super_block *sb = root->d_sb;
1127#endif
1128 struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
1129 if (pSuperInfo) {
1130 /* Performance related options: */
1131 if (pSuperInfo->msTTL != -1)
1132 seq_printf(m, ",ttl=%d", pSuperInfo->msTTL);
1133 if (pSuperInfo->msDirCacheTTL >= 0)
1134 seq_printf(m, ",dcachettl=%d", pSuperInfo->msDirCacheTTL);
1135 if (pSuperInfo->msInodeTTL >= 0)
1136 seq_printf(m, ",inodettl=%d", pSuperInfo->msInodeTTL);
1137 if (pSuperInfo->cMaxIoPages != VBSF_DEFAULT_MAX_IO_PAGES)
1138 seq_printf(m, ",maxiopages=%u", pSuperInfo->cMaxIoPages);
1139 if (pSuperInfo->cbDirBuf != VBSF_DEFAULT_DIR_BUF_SIZE)
1140 seq_printf(m, ",dirbuf=%u", pSuperInfo->cbDirBuf);
1141 switch (pSuperInfo->enmCacheMode) {
1142 default: AssertFailed(); RT_FALL_THRU();
1143 case kVbsfCacheMode_Strict:
1144 break;
1145 case kVbsfCacheMode_None: seq_puts(m, ",cache=none"); break;
1146 case kVbsfCacheMode_Read: seq_puts(m, ",cache=read"); break;
1147 case kVbsfCacheMode_ReadWrite: seq_puts(m, ",cache=readwrite"); break;
1148 }
1149
1150 /* Attributes and NLS: */
1151 seq_printf(m, ",iocharset=%s", pSuperInfo->nls ? pSuperInfo->nls->charset : "utf8");
1152 seq_printf(m, ",uid=%u,gid=%u", pSuperInfo->uid, pSuperInfo->gid);
1153 if (pSuperInfo->dmode != ~0)
1154 seq_printf(m, ",dmode=0%o", pSuperInfo->dmode);
1155 if (pSuperInfo->fmode != ~0)
1156 seq_printf(m, ",fmode=0%o", pSuperInfo->fmode);
1157 if (pSuperInfo->dmask != 0)
1158 seq_printf(m, ",dmask=0%o", pSuperInfo->dmask);
1159 if (pSuperInfo->fmask != 0)
1160 seq_printf(m, ",fmask=0%o", pSuperInfo->fmask);
1161
1162 /* Misc: */
1163 if (pSuperInfo->szTag[0] != '\0') {
1164 seq_puts(m, ",tag=");
1165 seq_escape(m, pSuperInfo->szTag, " \t\n\\");
1166 }
1167 }
1168 return 0;
1169}
1170
1171
1172/**
1173 * Super block operations.
1174 */
1175static struct super_operations g_vbsf_super_ops = {
1176#if RTLNX_VER_MAX(2,6,36)
1177 .clear_inode = vbsf_clear_inode,
1178#else
1179 .evict_inode = vbsf_evict_inode,
1180#endif
1181#if RTLNX_VER_MAX(2,6,25)
1182 .read_inode = vbsf_read_inode,
1183#endif
1184 .put_super = vbsf_put_super,
1185 .statfs = vbsf_statfs,
1186#if RTLNX_VER_MAX(5,1,0)
1187 .remount_fs = vbsf_remount_fs,
1188#endif
1189 .show_options = vbsf_show_options
1190};
1191
1192
1193
1194/*********************************************************************************************************************************
1195* File system type related stuff. *
1196*********************************************************************************************************************************/
1197
1198#if RTLNX_VER_RANGE(2,5,4, 5,1,0)
1199
1200static int vbsf_read_super_26(struct super_block *sb, void *data, int flags)
1201{
1202 int err;
1203
1204 TRACE();
1205 err = vbsf_read_super_aux(sb, data, flags);
1206 if (err)
1207 printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
1208
1209 return err;
1210}
1211
1212# if RTLNX_VER_MIN(2,6,39)
1213static struct dentry *sf_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
1214{
1215 TRACE();
1216
1217 if (!VBSF_IS_MOUNT_VBOXSF_DATA(data)) {
1218 int rc;
1219 struct vbsf_mount_info_new mount_opts = { '\0' };
1220
1221 vbsf_init_mount_info(&mount_opts, dev_name);
1222 rc = vbsf_parse_mount_options(data, &mount_opts);
1223 if (rc)
1224 return ERR_PTR(rc);
1225 return mount_nodev(fs_type, flags, &mount_opts, vbsf_read_super_26);
1226 } else {
1227 return mount_nodev(fs_type, flags, data, vbsf_read_super_26);
1228 }
1229}
1230# elif RTLNX_VER_MIN(2,6,18)
1231static int vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt)
1232{
1233 TRACE();
1234
1235 if (!VBSF_IS_MOUNT_VBOXSF_DATA(data)) {
1236 int rc;
1237 struct vbsf_mount_info_new mount_opts = { '\0' };
1238
1239 vbsf_init_mount_info(&mount_opts, dev_name);
1240 rc = vbsf_parse_mount_options(data, &mount_opts);
1241 if (rc)
1242 return rc;
1243 return get_sb_nodev(fs_type, flags, &mount_opts, vbsf_read_super_26,
1244 mnt);
1245 } else {
1246 return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26, mnt);
1247 }
1248}
1249# else /* 2.6.18 > version >= 2.5.4 */
1250static struct super_block *vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
1251{
1252 TRACE();
1253
1254 if (!VBSF_IS_MOUNT_VBOXSF_DATA(data)) {
1255 int rc;
1256 struct vbsf_mount_info_new mount_opts = { '\0' };
1257
1258 vbsf_init_mount_info(&mount_opts, dev_name);
1259 rc = vbsf_parse_mount_options(data, &mount_opts);
1260 if (rc)
1261 return ERR_PTR(rc);
1262 return get_sb_nodev(fs_type, flags, &mount_opts, vbsf_read_super_26);
1263 } else {
1264 return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26);
1265 }
1266}
1267# endif
1268#endif /* 5.1.0 > version >= 2.5.4 */
1269
1270#if RTLNX_VER_MAX(2,5,4) /* < 2.5.4 */
1271
1272static struct super_block *vbsf_read_super_24(struct super_block *sb, void *data, int flags)
1273{
1274 int err;
1275
1276 TRACE();
1277
1278 if (!VBSF_IS_MOUNT_VBOXSF_DATA(data)) {
1279 int rc;
1280 struct vbsf_mount_info_new mount_opts = { '\0' };
1281
1282 vbsf_init_mount_info(&mount_opts, NULL);
1283 rc = vbsf_parse_mount_options(data, &mount_opts);
1284 if (rc)
1285 return ERR_PTR(rc);
1286 err = vbsf_read_super_aux(sb, &mount_opts, flags);
1287 } else {
1288 err = vbsf_read_super_aux(sb, data, flags);
1289 }
1290 if (err) {
1291 printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
1292 return NULL;
1293 }
1294
1295 return sb;
1296}
1297
1298static DECLARE_FSTYPE(g_vboxsf_fs_type, "vboxsf", vbsf_read_super_24, 0);
1299
1300#endif /* < 2.5.4 */
1301
1302#if RTLNX_VER_MIN(5,1,0)
1303
1304/**
1305 * The following section of code uses the Linux filesystem mount API (also
1306 * known as the "filesystem context API") to parse string-based mount options.
1307 * The API is described here:
1308 * https://www.kernel.org/doc/Documentation/filesystems/mount_api.txt
1309 */
1310enum vbsf_cache_modes {
1311 VBSF_CACHE_DEFAULT,
1312 VBSF_CACHE_NONE,
1313 VBSF_CACHE_STRICT,
1314 VBSF_CACHE_READ,
1315 VBSF_CACHE_RW
1316};
1317
1318static const struct constant_table vbsf_param_cache_mode[] = {
1319 { "default", VBSF_CACHE_DEFAULT },
1320 { "none", VBSF_CACHE_NONE },
1321 { "strict", VBSF_CACHE_STRICT },
1322 { "read", VBSF_CACHE_READ },
1323 { "readwrite", VBSF_CACHE_RW },
1324 {}
1325};
1326
1327enum {
1328 Opt_iocharset, /* nls_name[] */
1329 Opt_nls, /* alias for iocharset */
1330 Opt_uid,
1331 Opt_gid,
1332 Opt_ttl,
1333 Opt_dmode,
1334 Opt_fmode,
1335 Opt_dmask,
1336 Opt_fmask,
1337 Opt_umask,
1338 Opt_maxiopages,
1339 Opt_dirbuf,
1340 Opt_dcachettl,
1341 Opt_inodettl,
1342 Opt_cachemode, /* enum vbsf_cache_mode */
1343 Opt_tag
1344};
1345
1346# if RTLNX_VER_MAX(5,6,0)
1347static const struct fs_parameter_spec vbsf_fs_specs[] = {
1348# else
1349static const struct fs_parameter_spec vbsf_fs_parameters[] = {
1350# endif
1351 fsparam_string("iocharset", Opt_iocharset),
1352 fsparam_string("nls", Opt_nls),
1353 fsparam_u32 ("uid", Opt_uid),
1354 fsparam_u32 ("gid", Opt_gid),
1355 fsparam_u32 ("ttl", Opt_ttl),
1356 fsparam_u32oct("dmode", Opt_dmode),
1357 fsparam_u32oct("fmode", Opt_fmode),
1358 fsparam_u32oct("dmask", Opt_dmask),
1359 fsparam_u32oct("fmask", Opt_fmask),
1360 fsparam_u32oct("umask", Opt_umask),
1361 fsparam_u32 ("maxiopages", Opt_maxiopages),
1362 fsparam_u32 ("dirbuf", Opt_dirbuf),
1363 fsparam_u32 ("dcachettl", Opt_dcachettl),
1364 fsparam_u32 ("inodettl", Opt_inodettl),
1365# if RTLNX_VER_MAX(5,6,0)
1366 fsparam_enum ("cache", Opt_cachemode),
1367# else
1368 fsparam_enum ("cache", Opt_cachemode, vbsf_param_cache_mode),
1369# endif
1370 fsparam_string("tag", Opt_tag),
1371 {}
1372};
1373
1374# if RTLNX_VER_MAX(5,6,0)
1375static const struct fs_parameter_enum vbsf_fs_enums[] = {
1376 { Opt_cachemode, "default", VBSF_CACHE_DEFAULT },
1377 { Opt_cachemode, "none", VBSF_CACHE_NONE },
1378 { Opt_cachemode, "strict", VBSF_CACHE_STRICT },
1379 { Opt_cachemode, "read", VBSF_CACHE_READ },
1380 { Opt_cachemode, "readwrite", VBSF_CACHE_RW },
1381 {}
1382};
1383
1384static const struct fs_parameter_description vbsf_fs_parameters = {
1385 .name = "vboxsf",
1386 .specs = vbsf_fs_specs,
1387 .enums = vbsf_fs_enums
1388};
1389# endif
1390
1391/**
1392 * Parse the (string-based) mount options passed in as -o foo,bar=123,etc.
1393 */
1394static int vbsf_parse_param(struct fs_context *fc, struct fs_parameter *param)
1395{
1396 struct fs_parse_result result;
1397 struct vbsf_mount_info_new *info = fc->fs_private;
1398 int opt;
1399
1400# if RTLNX_VER_MAX(5,6,0)
1401 opt = fs_parse(fc, &vbsf_fs_parameters, param, &result);
1402# else
1403 opt = fs_parse(fc, vbsf_fs_parameters, param, &result);
1404# endif
1405 if (opt < 0)
1406 return opt;
1407
1408 switch (opt) {
1409 case Opt_iocharset:
1410 case Opt_nls:
1411 RTStrCopy(info->nls_name, sizeof(info->nls_name), param->string);
1412 break;
1413 case Opt_uid:
1414 info->uid = result.uint_32;
1415 break;
1416 case Opt_gid:
1417 info->gid = result.uint_32;
1418 break;
1419 case Opt_ttl:
1420 info->ttl = result.uint_32;
1421 break;
1422 case Opt_dmode:
1423 if (result.uint_32 & ~0777)
1424 return invalf(fc, "Invalid dmode specified: '%o'", result.uint_32);
1425 info->dmode = result.uint_32;
1426 break;
1427 case Opt_fmode:
1428 if (result.uint_32 & ~0777)
1429 return invalf(fc, "Invalid fmode specified: '%o'", result.uint_32);
1430 info->fmode = result.uint_32;
1431 break;
1432 case Opt_dmask:
1433 if (result.uint_32 & ~07777)
1434 return invalf(fc, "Invalid dmask specified: '%o'", result.uint_32);
1435 info->dmask = result.uint_32;
1436 break;
1437 case Opt_fmask:
1438 if (result.uint_32 & ~07777)
1439 return invalf(fc, "Invalid fmask specified: '%o'", result.uint_32);
1440 info->fmask = result.uint_32;
1441 break;
1442 case Opt_umask:
1443 if (result.uint_32 & ~07777)
1444 return invalf(fc, "Invalid umask specified: '%o'", result.uint_32);
1445 info->dmask = info->fmask = result.uint_32;
1446 break;
1447 case Opt_maxiopages:
1448 info->cMaxIoPages = result.uint_32;
1449 break;
1450 case Opt_dirbuf:
1451 info->cbDirBuf = result.uint_32;
1452 break;
1453 case Opt_dcachettl:
1454 info->msDirCacheTTL = result.uint_32;
1455 break;
1456 case Opt_inodettl:
1457 info->msInodeTTL = result.uint_32;
1458 break;
1459 case Opt_cachemode:
1460 if (result.uint_32 == VBSF_CACHE_DEFAULT || result.uint_32 == VBSF_CACHE_STRICT)
1461 info->enmCacheMode = kVbsfCacheMode_Strict;
1462 else if (result.uint_32 == VBSF_CACHE_NONE)
1463 info->enmCacheMode = kVbsfCacheMode_None;
1464 else if (result.uint_32 == VBSF_CACHE_READ)
1465 info->enmCacheMode = kVbsfCacheMode_Read;
1466 else if (result.uint_32 == VBSF_CACHE_RW)
1467 info->enmCacheMode = kVbsfCacheMode_ReadWrite;
1468 else
1469 printk(KERN_WARNING "vboxsf: cache mode (%u) is out of range, using default instead.\n", result.uint_32);
1470 break;
1471 case Opt_tag:
1472 RTStrCopy(info->szTag, sizeof(info->szTag), param->string);
1473 break;
1474 default:
1475 return invalf(fc, "Invalid mount option: '%s'", param->key);
1476 }
1477
1478 return 0;
1479}
1480
1481/**
1482 * Parse the mount options provided whether by the mount.vboxsf utility
1483 * which supplies the mount information as a page of data or else as a
1484 * string in the following format: key[=val][,key[=val]]*.
1485 */
1486static int vbsf_parse_monolithic(struct fs_context *fc, void *data)
1487{
1488 struct vbsf_mount_info_new *info = fc->fs_private;
1489
1490 if (data) {
1491 if (VBSF_IS_MOUNT_VBOXSF_DATA(data)) {
1492 RT_BCOPY_UNFORTIFIED(info, data, sizeof(struct vbsf_mount_info_new));
1493 } else {
1494 /* this will call vbsf_parse_param() */
1495 return generic_parse_monolithic(fc, data);
1496 }
1497 }
1498
1499 return 0;
1500}
1501
1502/**
1503 * Clean up the filesystem-specific part of the filesystem context.
1504 */
1505static void vbsf_free_ctx(struct fs_context *fc)
1506{
1507 struct vbsf_mount_info_new *info = fc->fs_private;
1508
1509 if (info) {
1510 kfree(info);
1511 fc->fs_private = NULL;
1512 }
1513}
1514
1515/**
1516 * Create the mountable root and superblock which can then be used later for
1517 * mounting the shared folder. The superblock is populated by
1518 * vbsf_read_super_aux() which also sets up the shared folder mapping and the
1519 * related paperwork in preparation for mounting the shared folder.
1520 */
1521static int vbsf_get_tree(struct fs_context *fc)
1522{
1523 struct vbsf_mount_info_new *info = fc->fs_private;
1524
1525 if (!fc->source) {
1526 SFLOGRELBOTH(("vboxsf: No shared folder specified\n"));
1527 return invalf(fc, "vboxsf: No shared folder specified");
1528 }
1529
1530 /* fc->source (the shared folder name) is set after vbsf_init_fs_ctx() */
1531 RTStrCopy(info->name, sizeof(info->name), fc->source);
1532
1533# if RTLNX_VER_MAX(5,3,0)
1534 return vfs_get_super(fc, vfs_get_independent_super, vbsf_read_super_aux);
1535# else
1536 return get_tree_nodev(fc, vbsf_read_super_aux);
1537# endif
1538}
1539
1540/**
1541 * Reconfigures the superblock based on the mount information stored in the
1542 * filesystem context. Called via '-o remount' (aka mount(2) with MS_REMOUNT)
1543 * and is the equivalent of .fs_remount.
1544 */
1545static int vbsf_reconfigure(struct fs_context *fc)
1546{
1547 struct vbsf_mount_info_new *info = fc->fs_private;
1548 struct super_block *sb = fc->root->d_sb;
1549
1550 return vbsf_remount_fs(sb, info);
1551}
1552
1553static const struct fs_context_operations vbsf_context_ops = {
1554 .parse_param = vbsf_parse_param,
1555 .parse_monolithic = vbsf_parse_monolithic,
1556 .free = vbsf_free_ctx,
1557 .get_tree = vbsf_get_tree,
1558 .reconfigure = vbsf_reconfigure
1559};
1560
1561/**
1562 * Set up the filesystem mount context.
1563 */
1564static int vbsf_init_fs_context(struct fs_context *fc)
1565{
1566 struct vbsf_mount_info_new *info = fc->fs_private;
1567
1568 info = kzalloc(sizeof(*info), GFP_KERNEL);
1569 if (!info) {
1570 SFLOGRELBOTH(("vboxsf: Could not allocate memory for mount options\n"));
1571 return -ENOMEM;
1572 }
1573
1574 /* set default values for the mount information structure */
1575 info->ttl = info->msDirCacheTTL = info->msInodeTTL = -1;
1576 info->dmode = info->fmode = ~0U;
1577 info->enmCacheMode = kVbsfCacheMode_Strict;
1578 info->length = sizeof(struct vbsf_mount_info_new);
1579
1580 fc->fs_private = info;
1581 fc->ops = &vbsf_context_ops;
1582
1583 return 0;
1584}
1585#endif /* >= 5.1.0 */
1586
1587
1588#if RTLNX_VER_MIN(2,5,4)
1589/**
1590 * File system registration structure.
1591 */
1592static struct file_system_type g_vboxsf_fs_type = {
1593 .owner = THIS_MODULE,
1594 .name = "vboxsf",
1595# if RTLNX_VER_MIN(5,1,0)
1596 .init_fs_context = vbsf_init_fs_context,
1597# if RTLNX_VER_MAX(5,6,0)
1598 .parameters = &vbsf_fs_parameters,
1599# else
1600 .parameters = vbsf_fs_parameters,
1601# endif
1602# elif RTLNX_VER_MIN(2,6,39)
1603 .mount = sf_mount,
1604# else
1605 .get_sb = vbsf_get_sb,
1606# endif
1607 .kill_sb = kill_anon_super
1608};
1609#endif /* >= 2.5.4 */
1610
1611
1612/*********************************************************************************************************************************
1613* Module stuff *
1614*********************************************************************************************************************************/
1615
1616/**
1617 * Called on module initialization.
1618 */
1619static int __init init(void)
1620{
1621 int rc;
1622 SFLOGFLOW(("vboxsf: init\n"));
1623
1624 /* Check if modue loading was disabled. */
1625 if (!vbox_mod_should_load())
1626 return -EINVAL;
1627
1628 /*
1629 * Must be paranoid about the vbsf_mount_info_new size.
1630 */
1631 AssertCompile(sizeof(struct vbsf_mount_info_new) <= PAGE_SIZE);
1632 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
1633 printk(KERN_ERR
1634 "vboxsf: Mount information structure is too large %lu\n"
1635 "vboxsf: Must be less than or equal to %lu\n",
1636 (unsigned long)sizeof(struct vbsf_mount_info_new),
1637 (unsigned long)PAGE_SIZE);
1638 return -EINVAL;
1639 }
1640
1641 /*
1642 * Initialize stuff.
1643 */
1644 spin_lock_init(&g_SfHandleLock);
1645 rc = VbglR0SfInit();
1646 if (RT_SUCCESS(rc)) {
1647 /*
1648 * Try connect to the shared folder HGCM service.
1649 * It is possible it is not there.
1650 */
1651 rc = VbglR0SfConnect(&g_SfClient);
1652 if (RT_SUCCESS(rc)) {
1653 /*
1654 * Query host HGCM features and afterwards (must be last) shared folder features.
1655 */
1656 rc = VbglR0QueryHostFeatures(&g_fHostFeatures);
1657 if (RT_FAILURE(rc))
1658 {
1659 LogRel(("vboxsf: VbglR0QueryHostFeatures failed: rc=%Rrc (ignored)\n", rc));
1660 g_fHostFeatures = 0;
1661 }
1662 VbglR0SfHostReqQueryFeaturesSimple(&g_fSfFeatures, &g_uSfLastFunction);
1663 LogRel(("vboxsf: g_fHostFeatures=%#x g_fSfFeatures=%#RX64 g_uSfLastFunction=%u\n",
1664 g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
1665
1666 /*
1667 * Tell the shared folder service about our expectations:
1668 * - UTF-8 strings (rather than UTF-16)
1669 * - Wheter to return or follow (default) symbolic links.
1670 */
1671 rc = VbglR0SfHostReqSetUtf8Simple();
1672 if (RT_SUCCESS(rc)) {
1673 if (!g_fFollowSymlinks) {
1674 rc = VbglR0SfHostReqSetSymlinksSimple();
1675 if (RT_FAILURE(rc))
1676 printk(KERN_WARNING "vboxsf: Host unable to enable showing symlinks, rc=%d\n", rc);
1677 }
1678 /*
1679 * Now that we're ready for action, try register the
1680 * file system with the kernel.
1681 */
1682 rc = register_filesystem(&g_vboxsf_fs_type);
1683 if (rc == 0) {
1684 printk(KERN_INFO "vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) "\n");
1685#ifdef VERMAGIC_STRING
1686 LogRel(("vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) " on %s (LINUX_VERSION_CODE=%#x)\n",
1687 VERMAGIC_STRING, LINUX_VERSION_CODE));
1688#elif defined(UTS_RELEASE)
1689 LogRel(("vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) " on %s (LINUX_VERSION_CODE=%#x)\n",
1690 UTS_RELEASE, LINUX_VERSION_CODE));
1691#else
1692 LogRel(("vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) " (LINUX_VERSION_CODE=%#x)\n", LINUX_VERSION_CODE));
1693#endif
1694 return 0;
1695 }
1696
1697 /*
1698 * Failed. Bail out.
1699 */
1700 LogRel(("vboxsf: register_filesystem failed: rc=%d\n", rc));
1701 } else {
1702 LogRel(("vboxsf: VbglR0SfSetUtf8 failed, rc=%Rrc\n", rc));
1703 rc = -EPROTO;
1704 }
1705 VbglR0SfDisconnect(&g_SfClient);
1706 } else {
1707 LogRel(("vboxsf: VbglR0SfConnect failed, rc=%Rrc\n", rc));
1708 rc = rc == VERR_HGCM_SERVICE_NOT_FOUND ? -EHOSTDOWN : -ECONNREFUSED;
1709 }
1710 VbglR0SfTerm();
1711 } else {
1712 LogRel(("vboxsf: VbglR0SfInit failed, rc=%Rrc\n", rc));
1713 rc = -EPROTO;
1714 }
1715 return rc;
1716}
1717
1718
1719/**
1720 * Called on module finalization.
1721 */
1722static void __exit fini(void)
1723{
1724 SFLOGFLOW(("vboxsf: fini\n"));
1725
1726 unregister_filesystem(&g_vboxsf_fs_type);
1727 VbglR0SfDisconnect(&g_SfClient);
1728 VbglR0SfTerm();
1729}
1730
1731
1732/*
1733 * Module parameters.
1734 */
1735#if RTLNX_VER_MIN(2,5,52)
1736module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0);
1737MODULE_PARM_DESC(follow_symlinks,
1738 "Let host resolve symlinks rather than showing them");
1739#endif
1740
1741
1742/*
1743 * Module declaration related bits.
1744 */
1745module_init(init);
1746module_exit(fini);
1747
1748MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
1749MODULE_AUTHOR(VBOX_VENDOR);
1750MODULE_LICENSE("GPL and additional rights");
1751#ifdef MODULE_ALIAS_FS
1752MODULE_ALIAS_FS("vboxsf");
1753#endif
1754#ifdef MODULE_VERSION
1755MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
1756#endif
1757
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use