VirtualBox

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

Last change on this file since 87014 was 87014, checked in by vboxsync, 4 years ago

linux/vboxsf: Add support for parsing string-based mount options using the Linux Filesystem Mount API aka fs_context (kernel versions >= 5.1.0) bugref:9816

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

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