VirtualBox

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

Last change on this file since 79594 was 79472, checked in by vboxsync, 5 years ago

linux/vboxsf: Fixed writable mmap on 2.6.34 thru 4.9, needed to set s_bdi in the superblock. bugref:9172

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