VirtualBox

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

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

linux/vboxsf: Added more mount options: dcachettl=MILLISECONDS, inodettl=MILLISECONDS, dirbuf=BYTES and cache={default/strict|none|read|readwrite}. The readwrite cache mode isn't fully implemented yet (works same as 'read'). bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.8 KB
Line 
1/* $Id: vfsmod.c 77953 2019-03-29 17:07:16Z vboxsync $ */
2/** @file
3 * vboxsf - VBox Linux Shared Folders VFS, module init/term, super block management.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person
10 * obtaining a copy of this software and associated documentation
11 * files (the "Software"), to deal in the Software without
12 * restriction, including without limitation the rights to use,
13 * copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following
16 * conditions:
17 *
18 * The above copyright notice and this permission notice shall be
19 * included in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31/**
32 * @note Anyone wishing to make changes here might wish to take a look at
33 * https://github.com/torvalds/linux/blob/master/Documentation/filesystems/vfs.txt
34 * which seems to be the closest there is to official documentation on
35 * writing filesystem drivers for Linux.
36 *
37 * See also: http://us1.samba.org/samba/ftp/cifs-cvs/ols2006-fs-tutorial-smf.odp
38 */
39
40
41/*********************************************************************************************************************************
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 LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
49# include <uapi/linux/mount.h> /* for MS_REMOUNT */
50#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
51# include <linux/mount.h>
52#endif
53#include <linux/seq_file.h>
54#include <linux/vfs.h>
55#include <VBox/err.h>
56#include <iprt/path.h>
57
58
59/*********************************************************************************************************************************
60* Defined Constants And Macros *
61*********************************************************************************************************************************/
62#define VBSF_DEFAULT_MAX_IO_PAGES RT_MIN(_16K / sizeof(RTGCPHYS64) /* => 8MB buffer */, VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
63#define VBSF_DEFAULT_DIR_BUF_SIZE _64K
64
65
66/*********************************************************************************************************************************
67* Global Variables *
68*********************************************************************************************************************************/
69VBGLSFCLIENT g_SfClient;
70uint32_t g_fHostFeatures = 0;
71/** Last valid shared folders function number. */
72uint32_t g_uSfLastFunction = SHFL_FN_SET_FILE_SIZE;
73/** Shared folders features. */
74uint64_t g_fSfFeatures = 0;
75
76/** Protects all the vbsf_inode_info::HandleList lists. */
77spinlock_t g_SfHandleLock;
78
79/** The 'follow_symlinks' module parameter.
80 * @todo Figure out how do this for 2.4.x! */
81static int g_fFollowSymlinks = 0;
82
83/* forward declaration */
84static struct super_operations g_vbsf_super_ops;
85
86
87
88/**
89 * Copies options from the mount info structure into @a pSuperInfo.
90 *
91 * This is used both by vbsf_super_info_alloc_and_map_it() and
92 * vbsf_remount_fs().
93 */
94static void vbsf_super_info_copy_remount_options(struct vbsf_super_info *pSuperInfo, struct vbsf_mount_info_new *info)
95{
96 pSuperInfo->uid = info->uid;
97 pSuperInfo->gid = info->gid;
98
99 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, szTag)) {
100 /* new fields */
101 pSuperInfo->dmode = info->dmode;
102 pSuperInfo->fmode = info->fmode;
103 pSuperInfo->dmask = info->dmask;
104 pSuperInfo->fmask = info->fmask;
105 } else {
106 pSuperInfo->dmode = ~0;
107 pSuperInfo->fmode = ~0;
108 }
109
110 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cMaxIoPages)) {
111 AssertCompile(sizeof(pSuperInfo->szTag) >= sizeof(info->szTag));
112 memcpy(pSuperInfo->szTag, info->szTag, sizeof(info->szTag));
113 pSuperInfo->szTag[sizeof(pSuperInfo->szTag) - 1] = '\0';
114 } else {
115 pSuperInfo->szTag[0] = '\0';
116 }
117
118 /* The max number of pages in an I/O request. This must take into
119 account that the physical heap generally grows in 64 KB chunks,
120 so we should not try push that limit. It also needs to take
121 into account that the host will allocate temporary heap buffers
122 for the I/O bytes we send/receive, so don't push the host heap
123 too hard as we'd have to retry with smaller requests when this
124 happens, which isn't too efficient. */
125 pSuperInfo->cMaxIoPages = VBSF_DEFAULT_MAX_IO_PAGES;
126 if ( (unsigned)info->length >= sizeof(struct vbsf_mount_info_new)
127 && info->cMaxIoPages > 0) {
128 if (info->cMaxIoPages <= VMMDEV_MAX_HGCM_DATA_SIZE >> PAGE_SHIFT)
129 pSuperInfo->cMaxIoPages = RT_MAX(info->cMaxIoPages, 2); /* read_iter/write_iter requires a minimum of 2. */
130 else
131 printk(KERN_WARNING "vboxsf: max I/O page count (%#x) is out of range, using default (%#x) instead.\n",
132 info->cMaxIoPages, pSuperInfo->cMaxIoPages);
133 }
134
135 pSuperInfo->cbDirBuf = VBSF_DEFAULT_DIR_BUF_SIZE;
136 if ( (unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, cbDirBuf)
137 && info->cbDirBuf > 0) {
138 if (info->cbDirBuf <= _16M)
139 pSuperInfo->cbDirBuf = RT_ALIGN_32(info->cbDirBuf, PAGE_SIZE);
140 else
141 printk(KERN_WARNING "vboxsf: max directory buffer size (%#x) is out of range, using default (%#x) instead.\n",
142 info->cMaxIoPages, pSuperInfo->cMaxIoPages);
143 }
144
145 /*
146 * TTLs.
147 */
148 pSuperInfo->msTTL = info->ttl;
149 if (info->ttl > 0)
150 pSuperInfo->cJiffiesDirCacheTTL = msecs_to_jiffies(info->ttl);
151 else if (info->ttl == 0 || info->ttl != -1)
152 pSuperInfo->cJiffiesDirCacheTTL = pSuperInfo->msTTL = 0;
153 else
154 pSuperInfo->cJiffiesDirCacheTTL = msecs_to_jiffies(VBSF_DEFAULT_TTL_MS);
155 pSuperInfo->cJiffiesInodeTTL = pSuperInfo->cJiffiesDirCacheTTL;
156
157 pSuperInfo->msDirCacheTTL = -1;
158 if ( (unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, msDirCacheTTL)
159 && info->msDirCacheTTL >= 0) {
160 if (info->msDirCacheTTL > 0) {
161 pSuperInfo->msDirCacheTTL = info->msDirCacheTTL;
162 pSuperInfo->cJiffiesDirCacheTTL = msecs_to_jiffies(info->msDirCacheTTL);
163 } else {
164 pSuperInfo->msDirCacheTTL = 0;
165 pSuperInfo->cJiffiesDirCacheTTL = 0;
166 }
167 }
168
169 pSuperInfo->msInodeTTL = -1;
170 if ( (unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, msInodeTTL)
171 && info->msInodeTTL >= 0) {
172 if (info->msInodeTTL > 0) {
173 pSuperInfo->msInodeTTL = info->msInodeTTL;
174 pSuperInfo->cJiffiesInodeTTL = msecs_to_jiffies(info->msInodeTTL);
175 } else {
176 pSuperInfo->msInodeTTL = 0;
177 pSuperInfo->cJiffiesInodeTTL = 0;
178 }
179 }
180
181 /*
182 * Caching.
183 */
184 pSuperInfo->enmCacheMode = kVbsfCacheMode_Strict;
185 if ((unsigned)info->length >= RT_UOFFSETOF(struct vbsf_mount_info_new, enmCacheMode)) {
186 switch (info->enmCacheMode) {
187 case kVbsfCacheMode_Default:
188 case kVbsfCacheMode_Strict:
189 break;
190 case kVbsfCacheMode_None:
191 case kVbsfCacheMode_Read:
192 case kVbsfCacheMode_ReadWrite:
193 pSuperInfo->enmCacheMode = info->enmCacheMode;
194 break;
195 default:
196 printk(KERN_WARNING "vboxsf: cache mode (%#x) is out of range, using default instead.\n", info->enmCacheMode);
197 break;
198 }
199 }
200}
201
202/**
203 * Allocate the super info structure and try map the host share.
204 */
205static int vbsf_super_info_alloc_and_map_it(struct vbsf_mount_info_new *info, struct vbsf_super_info **sf_gp)
206{
207 int rc;
208 SHFLSTRING *str_name;
209 size_t name_len, str_len;
210 struct vbsf_super_info *pSuperInfo;
211
212 TRACE();
213
214 /*
215 * Validate info.
216 */
217 if ( info->nullchar != '\0'
218 || info->signature[0] != VBSF_MOUNT_SIGNATURE_BYTE_0
219 || info->signature[1] != VBSF_MOUNT_SIGNATURE_BYTE_1
220 || info->signature[2] != VBSF_MOUNT_SIGNATURE_BYTE_2) {
221 SFLOGRELBOTH(("vboxsf: Invalid info signature: %#x %#x %#x %#x!\n",
222 info->nullchar, info->signature[0], info->signature[1], info->signature[2]));
223 return -EINVAL;
224 }
225 name_len = RTStrNLen(info->name, sizeof(info->name));
226 if (name_len >= sizeof(info->name)) {
227 SFLOGRELBOTH(("vboxsf: Specified shared folder name is not zero terminated!\n"));
228 return -EINVAL;
229 }
230 if (RTStrNLen(info->nls_name, sizeof(info->nls_name)) >= sizeof(info->nls_name)) {
231 SFLOGRELBOTH(("vboxsf: Specified nls name is not zero terminated!\n"));
232 return -EINVAL;
233 }
234
235 /*
236 * Allocate memory.
237 */
238 str_len = offsetof(SHFLSTRING, String.utf8) + name_len + 1;
239 str_name = (PSHFLSTRING)kmalloc(str_len, GFP_KERNEL);
240 pSuperInfo = (struct vbsf_super_info *)kmalloc(sizeof(*pSuperInfo), GFP_KERNEL);
241 if (pSuperInfo && str_name) {
242 RT_ZERO(*pSuperInfo);
243
244 str_name->u16Length = name_len;
245 str_name->u16Size = name_len + 1;
246 memcpy(str_name->String.utf8, info->name, name_len + 1);
247
248 /*
249 * Init the NLS support, if needed.
250 */
251 rc = 0;
252#define _IS_UTF8(_str) (strcmp(_str, "utf8") == 0)
253#define _IS_EMPTY(_str) (strcmp(_str, "") == 0)
254
255 /* Check if NLS charset is valid and not points to UTF8 table */
256 pSuperInfo->fNlsIsUtf8 = true;
257 if (info->nls_name[0]) {
258 if (_IS_UTF8(info->nls_name)) {
259 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=utf8\n"));
260 pSuperInfo->nls = NULL;
261 } else {
262 pSuperInfo->fNlsIsUtf8 = false;
263 pSuperInfo->nls = load_nls(info->nls_name);
264 if (pSuperInfo->nls) {
265 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=%s -> %p\n", info->nls_name, pSuperInfo->nls));
266 } else {
267 SFLOGRELBOTH(("vboxsf: Failed to load nls '%s'!\n", info->nls_name));
268 rc = -EINVAL;
269 }
270 }
271 } else {
272#ifdef CONFIG_NLS_DEFAULT
273 /* If no NLS charset specified, try to load the default
274 * one if it's not points to UTF8. */
275 if (!_IS_UTF8(CONFIG_NLS_DEFAULT)
276 && !_IS_EMPTY(CONFIG_NLS_DEFAULT)) {
277 pSuperInfo->fNlsIsUtf8 = false;
278 pSuperInfo->nls = load_nls_default();
279 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: CONFIG_NLS_DEFAULT=%s -> %p\n", CONFIG_NLS_DEFAULT, pSuperInfo->nls));
280 } else {
281 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=utf8 (default %s)\n", CONFIG_NLS_DEFAULT));
282 pSuperInfo->nls = NULL;
283 }
284#else
285 SFLOGFLOW(("vbsf_super_info_alloc_and_map_it: nls=utf8 (no default)\n"));
286 pSuperInfo->nls = NULL;
287#endif
288 }
289#undef _IS_UTF8
290#undef _IS_EMPTY
291 if (rc == 0) {
292 /*
293 * Try mount it.
294 */
295 rc = VbglR0SfHostReqMapFolderWithContigSimple(str_name, virt_to_phys(str_name), RTPATH_DELIMITER,
296 true /*fCaseSensitive*/, &pSuperInfo->map.root);
297 if (RT_SUCCESS(rc)) {
298 kfree(str_name);
299
300 /* The rest is shared with remount. */
301 vbsf_super_info_copy_remount_options(pSuperInfo, info);
302
303 *sf_gp = pSuperInfo;
304 return 0;
305 }
306
307 /*
308 * bail out:
309 */
310 if (rc == VERR_FILE_NOT_FOUND) {
311 LogRel(("vboxsf: SHFL_FN_MAP_FOLDER failed for '%s': share not found\n", info->name));
312 rc = -ENXIO;
313 } else {
314 LogRel(("vboxsf: SHFL_FN_MAP_FOLDER failed for '%s': %Rrc\n", info->name, rc));
315 rc = -EPROTO;
316 }
317 if (pSuperInfo->nls)
318 unload_nls(pSuperInfo->nls);
319 }
320 } else {
321 SFLOGRELBOTH(("vboxsf: Could not allocate memory for super info!\n"));
322 rc = -ENOMEM;
323 }
324 if (str_name)
325 kfree(str_name);
326 if (pSuperInfo)
327 kfree(pSuperInfo);
328 return rc;
329}
330
331/* unmap the share and free super info [pSuperInfo] */
332static void vbsf_super_info_free(struct vbsf_super_info *pSuperInfo)
333{
334 int rc;
335
336 TRACE();
337 rc = VbglR0SfHostReqUnmapFolderSimple(pSuperInfo->map.root);
338 if (RT_FAILURE(rc))
339 LogFunc(("VbglR0SfHostReqUnmapFolderSimple failed rc=%Rrc\n", rc));
340
341 if (pSuperInfo->nls)
342 unload_nls(pSuperInfo->nls);
343
344 kfree(pSuperInfo);
345}
346
347
348/**
349 * Initialize backing device related matters.
350 */
351static int vbsf_init_backing_dev(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
352{
353 int rc = 0;
354/** @todo this needs sorting out between 3.19 and 4.11 */
355#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
356 /* Each new shared folder map gets a new uint64_t identifier,
357 * allocated in sequence. We ASSUME the sequence will not wrap. */
358#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
359 static uint64_t s_u64Sequence = 0;
360 uint64_t u64CurrentSequence = ASMAtomicIncU64(&s_u64Sequence);
361#endif
362 struct backing_dev_info *bdi;
363
364# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
365 rc = super_setup_bdi_name(sb, "vboxsf-%llu", (unsigned long long)u64CurrentSequence);
366 if (!rc)
367 bdi = sb->s_bdi;
368 else
369 return rc;
370# else
371 bdi = &pSuperInfo->bdi;
372# endif
373
374 bdi->ra_pages = 0; /* No readahead */
375
376# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
377 bdi->capabilities = 0
378# ifdef BDI_CAP_MAP_DIRECT
379 | BDI_CAP_MAP_DIRECT /* MAP_SHARED */
380# endif
381# ifdef BDI_CAP_MAP_COPY
382 | BDI_CAP_MAP_COPY /* MAP_PRIVATE */
383# endif
384# ifdef BDI_CAP_READ_MAP
385 | BDI_CAP_READ_MAP /* can be mapped for reading */
386# endif
387# ifdef BDI_CAP_WRITE_MAP
388 | BDI_CAP_WRITE_MAP /* can be mapped for writing */
389# endif
390# ifdef BDI_CAP_EXEC_MAP
391 | BDI_CAP_EXEC_MAP /* can be mapped for execution */
392# endif
393# ifdef BDI_CAP_STRICTLIMIT
394# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) /* Trouble with 3.16.x/debian8. Process stops after dirty page throttling.
395 * Only tested successfully with 4.19. Maybe skip altogether? */
396 | BDI_CAP_STRICTLIMIT;
397# endif
398# endif
399 ;
400# ifdef BDI_CAP_STRICTLIMIT
401 /* Smalles possible amount of dirty pages: %1 of RAM. We set this to
402 try reduce amount of data that's out of sync with the host side.
403 Besides, writepages isn't implemented, so flushing is extremely slow.
404 Note! Extremely slow linux 3.0.0 msync doesn't seem to be related to this setting. */
405 bdi_set_max_ratio(bdi, 1);
406# endif
407# endif /* >= 2.6.12 */
408
409# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
410 rc = bdi_init(&pSuperInfo->bdi);
411# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
412 if (!rc)
413 rc = bdi_register(&pSuperInfo->bdi, NULL, "vboxsf-%llu", (unsigned long long)u64CurrentSequence);
414# endif /* >= 2.6.26 */
415# endif /* 4.11.0 > version >= 2.6.24 */
416#endif /* >= 2.6.0 */
417 return rc;
418}
419
420
421/**
422 * Undoes what vbsf_init_backing_dev did.
423 */
424static void vbsf_done_backing_dev(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
425{
426#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
427 bdi_destroy(&pSuperInfo->bdi); /* includes bdi_unregister() */
428#endif
429}
430
431
432/**
433 * Creates the root inode and attaches it to the super block.
434 *
435 * @returns 0 on success, negative errno on failure.
436 * @param sb The super block.
437 * @param pSuperInfo Our super block info.
438 */
439static int vbsf_create_root_inode(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
440{
441 SHFLFSOBJINFO fsinfo;
442 int rc;
443
444 /*
445 * Allocate and initialize the memory for our inode info structure.
446 */
447 struct vbsf_inode_info *sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
448 SHFLSTRING *path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
449 if (sf_i && path) {
450 sf_i->handle = SHFL_HANDLE_NIL;
451 sf_i->force_restat = false;
452 RTListInit(&sf_i->HandleList);
453#ifdef VBOX_STRICT
454 sf_i->u32Magic = SF_INODE_INFO_MAGIC;
455#endif
456 sf_i->path = path;
457
458 path->u16Length = 1;
459 path->u16Size = 2;
460 path->String.utf8[0] = '/';
461 path->String.utf8[1] = 0;
462
463 /*
464 * Stat the root directory (for inode info).
465 */
466 rc = vbsf_stat(__func__, pSuperInfo, sf_i->path, &fsinfo, 0);
467 if (rc == 0) {
468 /*
469 * Create the actual inode structure.
470 * Note! ls -la does display '.' and '..' entries with st_ino == 0, so root is #1.
471 */
472#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
473 struct inode *iroot = iget_locked(sb, 1);
474#else
475 struct inode *iroot = iget(sb, 1);
476#endif
477 if (iroot) {
478 vbsf_init_inode(iroot, sf_i, &fsinfo, pSuperInfo);
479 VBSF_SET_INODE_INFO(iroot, sf_i);
480
481#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
482 unlock_new_inode(iroot);
483#endif
484
485 /*
486 * Now make it a root inode.
487 */
488#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
489 sb->s_root = d_make_root(iroot);
490#else
491 sb->s_root = d_alloc_root(iroot);
492#endif
493 if (sb->s_root) {
494
495 return 0;
496 }
497
498 SFLOGRELBOTH(("vboxsf: d_make_root failed!\n"));
499#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) /* d_make_root calls iput */
500 iput(iroot);
501#endif
502 /* iput() will call vbsf_evict_inode()/vbsf_clear_inode(). */
503 sf_i = NULL;
504 path = NULL;
505
506 rc = -ENOMEM;
507 } else {
508 SFLOGRELBOTH(("vboxsf: failed to allocate root inode!\n"));
509 rc = -ENOMEM;
510 }
511 } else
512 SFLOGRELBOTH(("vboxsf: could not stat root of share: %d\n", rc));
513 } else {
514 SFLOGRELBOTH(("vboxsf: Could not allocate memory for root inode info!\n"));
515 rc = -ENOMEM;
516 }
517 if (sf_i)
518 kfree(sf_i);
519 if (path)
520 kfree(path);
521 return rc;
522}
523
524
525/**
526 * This is called by vbsf_read_super_24() and vbsf_read_super_26() when vfs mounts
527 * the fs and wants to read super_block.
528 *
529 * Calls vbsf_super_info_alloc_and_map_it() to map the folder and allocate super
530 * information structure.
531 *
532 * Initializes @a sb, initializes root inode and dentry.
533 *
534 * Should respect @a flags.
535 */
536static int vbsf_read_super_aux(struct super_block *sb, void *data, int flags)
537{
538 int rc;
539 struct vbsf_super_info *pSuperInfo;
540
541 TRACE();
542 if (!data) {
543 SFLOGRELBOTH(("vboxsf: No mount data. Is mount.vboxsf installed (typically in /sbin)?\n"));
544 return -EINVAL;
545 }
546
547 if (flags & MS_REMOUNT) {
548 SFLOGRELBOTH(("vboxsf: Remounting is not supported!\n"));
549 return -ENOSYS;
550 }
551
552 /*
553 * Create our super info structure and map the shared folder.
554 */
555 rc = vbsf_super_info_alloc_and_map_it((struct vbsf_mount_info_new *)data, &pSuperInfo);
556 if (rc == 0) {
557 /*
558 * Initialize the super block structure (must be done before
559 * root inode creation).
560 */
561 sb->s_magic = 0xface;
562 sb->s_blocksize = 1024;
563#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
564 /* Required for seek/sendfile (see 'loff_t max' in fs/read_write.c / do_sendfile()). */
565# if defined MAX_LFS_FILESIZE
566 sb->s_maxbytes = MAX_LFS_FILESIZE;
567# elif BITS_PER_LONG == 32
568 sb->s_maxbytes = (loff_t)ULONG_MAX << PAGE_SHIFT;
569# else
570 sb->s_maxbytes = INT64_MAX;
571# endif
572#endif
573 sb->s_op = &g_vbsf_super_ops;
574#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
575 sb->s_d_op = &vbsf_dentry_ops;
576#endif
577
578 /*
579 * Initialize the backing device. This is important for memory mapped
580 * files among other things.
581 */
582 rc = vbsf_init_backing_dev(sb, pSuperInfo);
583 if (rc == 0) {
584 /*
585 * Create the root inode and we're done.
586 */
587 rc = vbsf_create_root_inode(sb, pSuperInfo);
588 if (rc == 0) {
589 VBSF_SET_SUPER_INFO(sb, pSuperInfo);
590 SFLOGFLOW(("vbsf_read_super_aux: returns successfully\n"));
591 return 0;
592 }
593 vbsf_done_backing_dev(sb, pSuperInfo);
594 } else
595 SFLOGRELBOTH(("vboxsf: backing device information initialization failed: %d\n", rc));
596 vbsf_super_info_free(pSuperInfo);
597 }
598 return rc;
599}
600
601
602/**
603 * This is called when vfs is about to destroy the @a inode.
604 *
605 * We must free the inode info structure here.
606 */
607#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
608static void vbsf_evict_inode(struct inode *inode)
609#else
610static void vbsf_clear_inode(struct inode *inode)
611#endif
612{
613 struct vbsf_inode_info *sf_i;
614
615 TRACE();
616
617 /*
618 * Flush stuff.
619 */
620#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
621 truncate_inode_pages(&inode->i_data, 0);
622# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
623 clear_inode(inode);
624# else
625 end_writeback(inode);
626# endif
627#endif
628 /*
629 * Clean up our inode info.
630 */
631 sf_i = VBSF_GET_INODE_INFO(inode);
632 if (sf_i) {
633 VBSF_SET_INODE_INFO(inode, NULL);
634
635 Assert(sf_i->u32Magic == SF_INODE_INFO_MAGIC);
636 BUG_ON(!sf_i->path);
637 kfree(sf_i->path);
638 vbsf_handle_drop_chain(sf_i);
639# ifdef VBOX_STRICT
640 sf_i->u32Magic = SF_INODE_INFO_MAGIC_DEAD;
641# endif
642 kfree(sf_i);
643 }
644}
645
646
647/* this is called by vfs when it wants to populate [inode] with data.
648 the only thing that is known about inode at this point is its index
649 hence we can't do anything here, and let lookup/whatever with the
650 job to properly fill then [inode] */
651#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
652static void vbsf_read_inode(struct inode *inode)
653{
654}
655#endif
656
657
658/* vfs is done with [sb] (umount called) call [vbsf_super_info_free] to unmap
659 the folder and free [pSuperInfo] */
660static void vbsf_put_super(struct super_block *sb)
661{
662 struct vbsf_super_info *pSuperInfo;
663
664 pSuperInfo = VBSF_GET_SUPER_INFO(sb);
665 BUG_ON(!pSuperInfo);
666 vbsf_done_backing_dev(sb, pSuperInfo);
667 vbsf_super_info_free(pSuperInfo);
668}
669
670
671/**
672 * Get file system statistics.
673 */
674#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
675static int vbsf_statfs(struct dentry *dentry, struct kstatfs *stat)
676#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73)
677static int vbsf_statfs(struct super_block *sb, struct kstatfs *stat)
678#else
679static int vbsf_statfs(struct super_block *sb, struct statfs *stat)
680#endif
681{
682#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
683 struct super_block *sb = dentry->d_inode->i_sb;
684#endif
685 int rc;
686 VBOXSFVOLINFOREQ *pReq = (VBOXSFVOLINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
687 if (pReq) {
688 SHFLVOLINFO *pVolInfo = &pReq->VolInfo;
689 struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
690 rc = VbglR0SfHostReqQueryVolInfo(pSuperInfo->map.root, pReq, SHFL_HANDLE_ROOT);
691 if (RT_SUCCESS(rc)) {
692 stat->f_type = UINT32_C(0x786f4256); /* 'VBox' little endian */
693 stat->f_bsize = pVolInfo->ulBytesPerAllocationUnit;
694#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73)
695 stat->f_frsize = pVolInfo->ulBytesPerAllocationUnit;
696#endif
697 stat->f_blocks = pVolInfo->ullTotalAllocationBytes
698 / pVolInfo->ulBytesPerAllocationUnit;
699 stat->f_bfree = pVolInfo->ullAvailableAllocationBytes
700 / pVolInfo->ulBytesPerAllocationUnit;
701 stat->f_bavail = pVolInfo->ullAvailableAllocationBytes
702 / pVolInfo->ulBytesPerAllocationUnit;
703 stat->f_files = 1000;
704 stat->f_ffree = 1000000; /* don't return 0 here since the guest may think
705 * that it is not possible to create any more files */
706 stat->f_fsid.val[0] = 0;
707 stat->f_fsid.val[1] = 0;
708 stat->f_namelen = 255;
709#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
710 stat->f_flags = 0; /* not valid */
711#endif
712 RT_ZERO(stat->f_spare);
713 rc = 0;
714 } else
715 rc = -RTErrConvertToErrno(rc);
716 VbglR0PhysHeapFree(pReq);
717 } else
718 rc = -ENOMEM;
719 return rc;
720}
721
722static int vbsf_remount_fs(struct super_block *sb, int *flags, char *data)
723{
724#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
725 struct vbsf_super_info *pSuperInfo = pSuperInfo = VBSF_GET_SUPER_INFO(sb);
726 struct vbsf_inode_info *sf_i;
727 struct inode *iroot;
728 SHFLFSOBJINFO fsinfo;
729 int err;
730 Assert(pSuperInfo);
731
732 if (data && data[0] != 0) {
733 struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
734 if ( info->nullchar == '\0'
735 && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
736 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
737 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
738 vbsf_super_info_copy_remount_options(pSuperInfo, info);
739 }
740 }
741
742 iroot = ilookup(sb, 0);
743 if (!iroot)
744 return -ENOSYS;
745
746 sf_i = VBSF_GET_INODE_INFO(iroot);
747 err = vbsf_stat(__func__, pSuperInfo, sf_i->path, &fsinfo, 0);
748 BUG_ON(err != 0);
749 vbsf_init_inode(iroot, sf_i, &fsinfo, pSuperInfo);
750 /*unlock_new_inode(iroot); */
751 return 0;
752#else /* LINUX_VERSION_CODE < 2.4.23 */
753 return -ENOSYS;
754#endif /* LINUX_VERSION_CODE < 2.4.23 */
755}
756
757
758/**
759 * Show mount options.
760 *
761 * This is needed by the VBoxService automounter in order for it to pick up
762 * the the 'szTag' option value it sets on its mount.
763 */
764#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
765static int vbsf_show_options(struct seq_file *m, struct vfsmount *mnt)
766#else
767static int vbsf_show_options(struct seq_file *m, struct dentry *root)
768#endif
769{
770#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
771 struct super_block *sb = mnt->mnt_sb;
772#else
773 struct super_block *sb = root->d_sb;
774#endif
775 struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
776 if (pSuperInfo) {
777 /* Performance related options: */
778 if (pSuperInfo->msTTL != -1)
779 seq_printf(m, ",ttl=%d", pSuperInfo->msTTL);
780 if (pSuperInfo->msDirCacheTTL >= 0)
781 seq_printf(m, ",dcachettl=%d", pSuperInfo->msDirCacheTTL);
782 if (pSuperInfo->msInodeTTL >= 0)
783 seq_printf(m, ",inodettl=%d", pSuperInfo->msInodeTTL);
784 if (pSuperInfo->cMaxIoPages != VBSF_DEFAULT_MAX_IO_PAGES)
785 seq_printf(m, ",maxiopages=%u", pSuperInfo->cMaxIoPages);
786 if (pSuperInfo->cbDirBuf != VBSF_DEFAULT_DIR_BUF_SIZE)
787 seq_printf(m, ",dirbuf=%u", pSuperInfo->cbDirBuf);
788 switch (pSuperInfo->enmCacheMode) {
789 default: AssertFailed();
790 case kVbsfCacheMode_Strict:
791 break;
792 case kVbsfCacheMode_None: seq_puts(m, ",cache=none"); break;
793 case kVbsfCacheMode_Read: seq_puts(m, ",cache=read"); break;
794 case kVbsfCacheMode_ReadWrite: seq_puts(m, ",cache=readwrite"); break;
795 }
796
797 /* Attributes and NLS: */
798 seq_printf(m, ",iocharset=%s", pSuperInfo->nls ? pSuperInfo->nls->charset : "utf8");
799 seq_printf(m, ",uid=%u,gid=%u", pSuperInfo->uid, pSuperInfo->gid);
800 if (pSuperInfo->dmode != ~0)
801 seq_printf(m, ",dmode=0%o", pSuperInfo->dmode);
802 if (pSuperInfo->fmode != ~0)
803 seq_printf(m, ",fmode=0%o", pSuperInfo->fmode);
804 if (pSuperInfo->dmask != 0)
805 seq_printf(m, ",dmask=0%o", pSuperInfo->dmask);
806 if (pSuperInfo->fmask != 0)
807 seq_printf(m, ",fmask=0%o", pSuperInfo->fmask);
808
809 /* Misc: */
810 if (pSuperInfo->szTag[0] != '\0') {
811 seq_puts(m, ",tag=");
812 seq_escape(m, pSuperInfo->szTag, " \t\n\\");
813 }
814 }
815 return 0;
816}
817
818
819/**
820 * Super block operations.
821 */
822static struct super_operations g_vbsf_super_ops = {
823#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
824 .clear_inode = vbsf_clear_inode,
825#else
826 .evict_inode = vbsf_evict_inode,
827#endif
828#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
829 .read_inode = vbsf_read_inode,
830#endif
831 .put_super = vbsf_put_super,
832 .statfs = vbsf_statfs,
833 .remount_fs = vbsf_remount_fs,
834 .show_options = vbsf_show_options
835};
836
837
838
839/*********************************************************************************************************************************
840* File system type related stuff. *
841*********************************************************************************************************************************/
842
843#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 4)
844
845static int vbsf_read_super_26(struct super_block *sb, void *data, int flags)
846{
847 int err;
848
849 TRACE();
850 err = vbsf_read_super_aux(sb, data, flags);
851 if (err)
852 printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
853
854 return err;
855}
856
857# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
858static struct super_block *vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
859{
860 TRACE();
861 return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26);
862}
863# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
864static int vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt)
865{
866 TRACE();
867 return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26, mnt);
868}
869# else /* LINUX_VERSION_CODE >= 2.6.39 */
870static struct dentry *sf_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
871{
872 TRACE();
873 return mount_nodev(fs_type, flags, data, vbsf_read_super_26);
874}
875# endif /* LINUX_VERSION_CODE >= 2.6.39 */
876
877/**
878 * File system registration structure.
879 */
880static struct file_system_type g_vboxsf_fs_type = {
881 .owner = THIS_MODULE,
882 .name = "vboxsf",
883# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
884 .get_sb = vbsf_get_sb,
885# else
886 .mount = sf_mount,
887# endif
888 .kill_sb = kill_anon_super
889};
890
891#else /* LINUX_VERSION_CODE < 2.5.4 */
892
893static struct super_block *vbsf_read_super_24(struct super_block *sb, void *data, int flags)
894{
895 int err;
896
897 TRACE();
898 err = vbsf_read_super_aux(sb, data, flags);
899 if (err) {
900 printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
901 return NULL;
902 }
903
904 return sb;
905}
906
907static DECLARE_FSTYPE(g_vboxsf_fs_type, "vboxsf", vbsf_read_super_24, 0);
908
909#endif /* LINUX_VERSION_CODE < 2.5.4 */
910
911
912
913/*********************************************************************************************************************************
914* Module stuff *
915*********************************************************************************************************************************/
916
917/**
918 * Called on module initialization.
919 */
920static int __init init(void)
921{
922 int rc;
923 SFLOGFLOW(("vboxsf: init\n"));
924
925 /*
926 * Must be paranoid about the vbsf_mount_info_new size.
927 */
928 AssertCompile(sizeof(struct vbsf_mount_info_new) <= PAGE_SIZE);
929 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
930 printk(KERN_ERR
931 "vboxsf: Mount information structure is too large %lu\n"
932 "vboxsf: Must be less than or equal to %lu\n",
933 (unsigned long)sizeof(struct vbsf_mount_info_new),
934 (unsigned long)PAGE_SIZE);
935 return -EINVAL;
936 }
937
938 /*
939 * Initialize stuff.
940 */
941 spin_lock_init(&g_SfHandleLock);
942 rc = VbglR0SfInit();
943 if (RT_SUCCESS(rc)) {
944 /*
945 * Try connect to the shared folder HGCM service.
946 * It is possible it is not there.
947 */
948 rc = VbglR0SfConnect(&g_SfClient);
949 if (RT_SUCCESS(rc)) {
950 /*
951 * Query host HGCM features and afterwards (must be last) shared folder features.
952 */
953 rc = VbglR0QueryHostFeatures(&g_fHostFeatures);
954 if (RT_FAILURE(rc))
955 {
956 LogRel(("vboxsf: VbglR0QueryHostFeatures failed: rc=%Rrc (ignored)\n", rc));
957 g_fHostFeatures = 0;
958 }
959 VbglR0SfHostReqQueryFeaturesSimple(&g_fSfFeatures, &g_uSfLastFunction);
960 LogRel(("vboxsf: g_fHostFeatures=%#x g_fSfFeatures=%#RX64 g_uSfLastFunction=%u\n",
961 g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
962
963 /*
964 * Tell the shared folder service about our expectations:
965 * - UTF-8 strings (rather than UTF-16)
966 * - Wheter to return or follow (default) symbolic links.
967 */
968 rc = VbglR0SfHostReqSetUtf8Simple();
969 if (RT_SUCCESS(rc)) {
970 if (!g_fFollowSymlinks) {
971 rc = VbglR0SfHostReqSetSymlinksSimple();
972 if (RT_FAILURE(rc))
973 printk(KERN_WARNING "vboxsf: Host unable to enable showing symlinks, rc=%d\n", rc);
974 }
975 /*
976 * Now that we're ready for action, try register the
977 * file system with the kernel.
978 */
979 rc = register_filesystem(&g_vboxsf_fs_type);
980 if (rc == 0) {
981 printk(KERN_INFO "vboxsf: Successfully loaded version " VBOX_VERSION_STRING "\n");
982 return 0;
983 }
984
985 /*
986 * Failed. Bail out.
987 */
988 LogRel(("vboxsf: register_filesystem failed: rc=%d\n", rc));
989 } else {
990 LogRel(("vboxsf: VbglR0SfSetUtf8 failed, rc=%Rrc\n", rc));
991 rc = -EPROTO;
992 }
993 VbglR0SfDisconnect(&g_SfClient);
994 } else {
995 LogRel(("vboxsf: VbglR0SfConnect failed, rc=%Rrc\n", rc));
996 rc = rc == VERR_HGCM_SERVICE_NOT_FOUND ? -EHOSTDOWN : -ECONNREFUSED;
997 }
998 VbglR0SfTerm();
999 } else {
1000 LogRel(("vboxsf: VbglR0SfInit failed, rc=%Rrc\n", rc));
1001 rc = -EPROTO;
1002 }
1003 return rc;
1004}
1005
1006
1007/**
1008 * Called on module finalization.
1009 */
1010static void __exit fini(void)
1011{
1012 SFLOGFLOW(("vboxsf: fini\n"));
1013
1014 unregister_filesystem(&g_vboxsf_fs_type);
1015 VbglR0SfDisconnect(&g_SfClient);
1016 VbglR0SfTerm();
1017}
1018
1019
1020/*
1021 * Module parameters.
1022 */
1023#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 52)
1024module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0);
1025MODULE_PARM_DESC(follow_symlinks,
1026 "Let host resolve symlinks rather than showing them");
1027#endif
1028
1029
1030/*
1031 * Module declaration related bits.
1032 */
1033module_init(init);
1034module_exit(fini);
1035
1036MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
1037MODULE_AUTHOR(VBOX_VENDOR);
1038MODULE_LICENSE("GPL and additional rights");
1039#ifdef MODULE_ALIAS_FS
1040MODULE_ALIAS_FS("vboxsf");
1041#endif
1042#ifdef MODULE_VERSION
1043MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
1044#endif
1045
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