VirtualBox

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

Last change on this file since 103067 was 103067, checked in by vboxsync, 4 months ago

Additions: Linux: vboxsf: Prevent array-index-out-of-bounds UBSAN warnings, bugref:10585.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use