VirtualBox

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

Last change on this file since 95416 was 95416, checked in by vboxsync, 2 years ago

linux/vboxsf: Removed one RT_FALL_THRU() in vbsf_super_info_copy_remount_options that made no sense and didn't have any comment justifying it. bugref:10247

  • 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 95416 2022-06-29 00:59:01Z vboxsync $ */
2/** @file
3 * vboxsf - VBox Linux Shared Folders VFS, module init/term, super block management.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/**
32 * @note Anyone wishing to make changes here might wish to take a look at
33 * https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfs.txt
34 * which seems to be the closest there is to official documentation on
35 * writing filesystem drivers for Linux.
36 *
37 * See also: http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
38 */
39
40
41/*********************************************************************************************************************************
42* Header Files *
43*********************************************************************************************************************************/
44#include "vfsmod.h"
45#include "version-generated.h"
46#include "revision-generated.h"
47#include "product-generated.h"
48#if 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 memcpy(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 memcpy(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 path->String.utf8[0] = '/';
477 path->String.utf8[1] = 0;
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 strlcpy(info->nls_name, param->string, sizeof(info->nls_name));
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 strlcpy(info->szTag, param->string, sizeof(info->szTag));
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 memcpy(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 strlcpy(info->name, fc->source, sizeof(info->name));
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 /*
1625 * Must be paranoid about the vbsf_mount_info_new size.
1626 */
1627 AssertCompile(sizeof(struct vbsf_mount_info_new) <= PAGE_SIZE);
1628 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
1629 printk(KERN_ERR
1630 "vboxsf: Mount information structure is too large %lu\n"
1631 "vboxsf: Must be less than or equal to %lu\n",
1632 (unsigned long)sizeof(struct vbsf_mount_info_new),
1633 (unsigned long)PAGE_SIZE);
1634 return -EINVAL;
1635 }
1636
1637 /*
1638 * Initialize stuff.
1639 */
1640 spin_lock_init(&g_SfHandleLock);
1641 rc = VbglR0SfInit();
1642 if (RT_SUCCESS(rc)) {
1643 /*
1644 * Try connect to the shared folder HGCM service.
1645 * It is possible it is not there.
1646 */
1647 rc = VbglR0SfConnect(&g_SfClient);
1648 if (RT_SUCCESS(rc)) {
1649 /*
1650 * Query host HGCM features and afterwards (must be last) shared folder features.
1651 */
1652 rc = VbglR0QueryHostFeatures(&g_fHostFeatures);
1653 if (RT_FAILURE(rc))
1654 {
1655 LogRel(("vboxsf: VbglR0QueryHostFeatures failed: rc=%Rrc (ignored)\n", rc));
1656 g_fHostFeatures = 0;
1657 }
1658 VbglR0SfHostReqQueryFeaturesSimple(&g_fSfFeatures, &g_uSfLastFunction);
1659 LogRel(("vboxsf: g_fHostFeatures=%#x g_fSfFeatures=%#RX64 g_uSfLastFunction=%u\n",
1660 g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
1661
1662 /*
1663 * Tell the shared folder service about our expectations:
1664 * - UTF-8 strings (rather than UTF-16)
1665 * - Wheter to return or follow (default) symbolic links.
1666 */
1667 rc = VbglR0SfHostReqSetUtf8Simple();
1668 if (RT_SUCCESS(rc)) {
1669 if (!g_fFollowSymlinks) {
1670 rc = VbglR0SfHostReqSetSymlinksSimple();
1671 if (RT_FAILURE(rc))
1672 printk(KERN_WARNING "vboxsf: Host unable to enable showing symlinks, rc=%d\n", rc);
1673 }
1674 /*
1675 * Now that we're ready for action, try register the
1676 * file system with the kernel.
1677 */
1678 rc = register_filesystem(&g_vboxsf_fs_type);
1679 if (rc == 0) {
1680 printk(KERN_INFO "vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) "\n");
1681#ifdef VERMAGIC_STRING
1682 LogRel(("vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) " on %s (LINUX_VERSION_CODE=%#x)\n",
1683 VERMAGIC_STRING, LINUX_VERSION_CODE));
1684#elif defined(UTS_RELEASE)
1685 LogRel(("vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) " on %s (LINUX_VERSION_CODE=%#x)\n",
1686 UTS_RELEASE, LINUX_VERSION_CODE));
1687#else
1688 LogRel(("vboxsf: Successfully loaded version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) " (LINUX_VERSION_CODE=%#x)\n", LINUX_VERSION_CODE));
1689#endif
1690 return 0;
1691 }
1692
1693 /*
1694 * Failed. Bail out.
1695 */
1696 LogRel(("vboxsf: register_filesystem failed: rc=%d\n", rc));
1697 } else {
1698 LogRel(("vboxsf: VbglR0SfSetUtf8 failed, rc=%Rrc\n", rc));
1699 rc = -EPROTO;
1700 }
1701 VbglR0SfDisconnect(&g_SfClient);
1702 } else {
1703 LogRel(("vboxsf: VbglR0SfConnect failed, rc=%Rrc\n", rc));
1704 rc = rc == VERR_HGCM_SERVICE_NOT_FOUND ? -EHOSTDOWN : -ECONNREFUSED;
1705 }
1706 VbglR0SfTerm();
1707 } else {
1708 LogRel(("vboxsf: VbglR0SfInit failed, rc=%Rrc\n", rc));
1709 rc = -EPROTO;
1710 }
1711 return rc;
1712}
1713
1714
1715/**
1716 * Called on module finalization.
1717 */
1718static void __exit fini(void)
1719{
1720 SFLOGFLOW(("vboxsf: fini\n"));
1721
1722 unregister_filesystem(&g_vboxsf_fs_type);
1723 VbglR0SfDisconnect(&g_SfClient);
1724 VbglR0SfTerm();
1725}
1726
1727
1728/*
1729 * Module parameters.
1730 */
1731#if RTLNX_VER_MIN(2,5,52)
1732module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0);
1733MODULE_PARM_DESC(follow_symlinks,
1734 "Let host resolve symlinks rather than showing them");
1735#endif
1736
1737
1738/*
1739 * Module declaration related bits.
1740 */
1741module_init(init);
1742module_exit(fini);
1743
1744MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
1745MODULE_AUTHOR(VBOX_VENDOR);
1746MODULE_LICENSE("GPL and additional rights");
1747#ifdef MODULE_ALIAS_FS
1748MODULE_ALIAS_FS("vboxsf");
1749#endif
1750#ifdef MODULE_VERSION
1751MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
1752#endif
1753
Note: See TracBrowser for help on using the repository browser.

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