VirtualBox

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

Last change on this file since 78020 was 77976, checked in by vboxsync, 6 years ago

linux/vboxsf: Update inode info in vbsf_reg_open since we got accurate info from the host, allowing us to catch host mtime changes and timely invalidate the page cache. Get correct file position on O_APPEND from the host. bugref:9172

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.9 KB
Line 
1/* $Id: vfsmod.c 77976 2019-04-01 11:12:02Z 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 (SHFL_FEATURE_XXX). */
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#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
355 /* Each new shared folder map gets a new uint64_t identifier,
356 * allocated in sequence. We ASSUME the sequence will not wrap. */
357# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
358 static uint64_t s_u64Sequence = 0;
359 uint64_t idSeqMine = ASMAtomicIncU64(&s_u64Sequence);
360# endif
361 struct backing_dev_info *bdi;
362
363# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
364 rc = super_setup_bdi_name(sb, "vboxsf-%llu", (unsigned long long)idSeqMine);
365 if (!rc)
366 bdi = sb->s_bdi;
367 else
368 return rc;
369# else
370 bdi = &pSuperInfo->bdi;
371# endif
372
373 bdi->ra_pages = 0; /* No readahead */
374
375# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12)
376 bdi->capabilities = 0
377# ifdef BDI_CAP_MAP_DIRECT
378 | BDI_CAP_MAP_DIRECT /* MAP_SHARED */
379# endif
380# ifdef BDI_CAP_MAP_COPY
381 | BDI_CAP_MAP_COPY /* MAP_PRIVATE */
382# endif
383# ifdef BDI_CAP_READ_MAP
384 | BDI_CAP_READ_MAP /* can be mapped for reading */
385# endif
386# ifdef BDI_CAP_WRITE_MAP
387 | BDI_CAP_WRITE_MAP /* can be mapped for writing */
388# endif
389# ifdef BDI_CAP_EXEC_MAP
390 | BDI_CAP_EXEC_MAP /* can be mapped for execution */
391# endif
392# ifdef BDI_CAP_STRICTLIMIT
393# if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0) /* Trouble with 3.16.x/debian8. Process stops after dirty page throttling.
394 * Only tested successfully with 4.19. Maybe skip altogether? */
395 | BDI_CAP_STRICTLIMIT;
396# endif
397# endif
398 ;
399# ifdef BDI_CAP_STRICTLIMIT
400 /* Smalles possible amount of dirty pages: %1 of RAM. We set this to
401 try reduce amount of data that's out of sync with the host side.
402 Besides, writepages isn't implemented, so flushing is extremely slow.
403 Note! Extremely slow linux 3.0.0 msync doesn't seem to be related to this setting. */
404 bdi_set_max_ratio(bdi, 1);
405# endif
406# endif /* >= 2.6.12 */
407
408# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
409 rc = bdi_init(&pSuperInfo->bdi);
410# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
411 if (!rc)
412 rc = bdi_register(&pSuperInfo->bdi, NULL, "vboxsf-%llu", (unsigned long long)idSeqMine);
413# endif /* >= 2.6.26 */
414# endif /* 4.11.0 > version >= 2.6.24 */
415#endif /* >= 2.6.0 */
416 return rc;
417}
418
419
420/**
421 * Undoes what vbsf_init_backing_dev did.
422 */
423static void vbsf_done_backing_dev(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
424{
425#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) && LINUX_VERSION_CODE <= KERNEL_VERSION(3, 19, 0)
426 bdi_destroy(&pSuperInfo->bdi); /* includes bdi_unregister() */
427#endif
428}
429
430
431/**
432 * Creates the root inode and attaches it to the super block.
433 *
434 * @returns 0 on success, negative errno on failure.
435 * @param sb The super block.
436 * @param pSuperInfo Our super block info.
437 */
438static int vbsf_create_root_inode(struct super_block *sb, struct vbsf_super_info *pSuperInfo)
439{
440 SHFLFSOBJINFO fsinfo;
441 int rc;
442
443 /*
444 * Allocate and initialize the memory for our inode info structure.
445 */
446 struct vbsf_inode_info *sf_i = kmalloc(sizeof(*sf_i), GFP_KERNEL);
447 SHFLSTRING *path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL);
448 if (sf_i && path) {
449 sf_i->handle = SHFL_HANDLE_NIL;
450 sf_i->force_restat = false;
451 RTListInit(&sf_i->HandleList);
452#ifdef VBOX_STRICT
453 sf_i->u32Magic = SF_INODE_INFO_MAGIC;
454#endif
455 sf_i->path = path;
456
457 path->u16Length = 1;
458 path->u16Size = 2;
459 path->String.utf8[0] = '/';
460 path->String.utf8[1] = 0;
461
462 /*
463 * Stat the root directory (for inode info).
464 */
465 rc = vbsf_stat(__func__, pSuperInfo, sf_i->path, &fsinfo, 0);
466 if (rc == 0) {
467 /*
468 * Create the actual inode structure.
469 * Note! ls -la does display '.' and '..' entries with st_ino == 0, so root is #1.
470 */
471#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
472 struct inode *iroot = iget_locked(sb, 1);
473#else
474 struct inode *iroot = iget(sb, 1);
475#endif
476 if (iroot) {
477 vbsf_init_inode(iroot, sf_i, &fsinfo, pSuperInfo);
478 VBSF_SET_INODE_INFO(iroot, sf_i);
479
480#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
481 unlock_new_inode(iroot);
482#endif
483
484 /*
485 * Now make it a root inode.
486 */
487#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
488 sb->s_root = d_make_root(iroot);
489#else
490 sb->s_root = d_alloc_root(iroot);
491#endif
492 if (sb->s_root) {
493
494 return 0;
495 }
496
497 SFLOGRELBOTH(("vboxsf: d_make_root failed!\n"));
498#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) /* d_make_root calls iput */
499 iput(iroot);
500#endif
501 /* iput() will call vbsf_evict_inode()/vbsf_clear_inode(). */
502 sf_i = NULL;
503 path = NULL;
504
505 rc = -ENOMEM;
506 } else {
507 SFLOGRELBOTH(("vboxsf: failed to allocate root inode!\n"));
508 rc = -ENOMEM;
509 }
510 } else
511 SFLOGRELBOTH(("vboxsf: could not stat root of share: %d\n", rc));
512 } else {
513 SFLOGRELBOTH(("vboxsf: Could not allocate memory for root inode info!\n"));
514 rc = -ENOMEM;
515 }
516 if (sf_i)
517 kfree(sf_i);
518 if (path)
519 kfree(path);
520 return rc;
521}
522
523
524/**
525 * This is called by vbsf_read_super_24() and vbsf_read_super_26() when vfs mounts
526 * the fs and wants to read super_block.
527 *
528 * Calls vbsf_super_info_alloc_and_map_it() to map the folder and allocate super
529 * information structure.
530 *
531 * Initializes @a sb, initializes root inode and dentry.
532 *
533 * Should respect @a flags.
534 */
535static int vbsf_read_super_aux(struct super_block *sb, void *data, int flags)
536{
537 int rc;
538 struct vbsf_super_info *pSuperInfo;
539
540 TRACE();
541 if (!data) {
542 SFLOGRELBOTH(("vboxsf: No mount data. Is mount.vboxsf installed (typically in /sbin)?\n"));
543 return -EINVAL;
544 }
545
546 if (flags & MS_REMOUNT) {
547 SFLOGRELBOTH(("vboxsf: Remounting is not supported!\n"));
548 return -ENOSYS;
549 }
550
551 /*
552 * Create our super info structure and map the shared folder.
553 */
554 rc = vbsf_super_info_alloc_and_map_it((struct vbsf_mount_info_new *)data, &pSuperInfo);
555 if (rc == 0) {
556 /*
557 * Initialize the super block structure (must be done before
558 * root inode creation).
559 */
560 sb->s_magic = 0xface;
561 sb->s_blocksize = 1024;
562#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 3)
563 /* Required for seek/sendfile (see 'loff_t max' in fs/read_write.c / do_sendfile()). */
564# if defined MAX_LFS_FILESIZE
565 sb->s_maxbytes = MAX_LFS_FILESIZE;
566# elif BITS_PER_LONG == 32
567 sb->s_maxbytes = (loff_t)ULONG_MAX << PAGE_SHIFT;
568# else
569 sb->s_maxbytes = INT64_MAX;
570# endif
571#endif
572#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
573 sb->s_time_gran = 1; /* This might be a little optimistic for windows hosts, where it should be 100. */
574#endif
575 sb->s_op = &g_vbsf_super_ops;
576#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38)
577 sb->s_d_op = &vbsf_dentry_ops;
578#endif
579
580 /*
581 * Initialize the backing device. This is important for memory mapped
582 * files among other things.
583 */
584 rc = vbsf_init_backing_dev(sb, pSuperInfo);
585 if (rc == 0) {
586 /*
587 * Create the root inode and we're done.
588 */
589 rc = vbsf_create_root_inode(sb, pSuperInfo);
590 if (rc == 0) {
591 VBSF_SET_SUPER_INFO(sb, pSuperInfo);
592 SFLOGFLOW(("vbsf_read_super_aux: returns successfully\n"));
593 return 0;
594 }
595 vbsf_done_backing_dev(sb, pSuperInfo);
596 } else
597 SFLOGRELBOTH(("vboxsf: backing device information initialization failed: %d\n", rc));
598 vbsf_super_info_free(pSuperInfo);
599 }
600 return rc;
601}
602
603
604/**
605 * This is called when vfs is about to destroy the @a inode.
606 *
607 * We must free the inode info structure here.
608 */
609#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
610static void vbsf_evict_inode(struct inode *inode)
611#else
612static void vbsf_clear_inode(struct inode *inode)
613#endif
614{
615 struct vbsf_inode_info *sf_i;
616
617 TRACE();
618
619 /*
620 * Flush stuff.
621 */
622#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
623 truncate_inode_pages(&inode->i_data, 0);
624# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
625 clear_inode(inode);
626# else
627 end_writeback(inode);
628# endif
629#endif
630 /*
631 * Clean up our inode info.
632 */
633 sf_i = VBSF_GET_INODE_INFO(inode);
634 if (sf_i) {
635 VBSF_SET_INODE_INFO(inode, NULL);
636
637 Assert(sf_i->u32Magic == SF_INODE_INFO_MAGIC);
638 BUG_ON(!sf_i->path);
639 kfree(sf_i->path);
640 vbsf_handle_drop_chain(sf_i);
641# ifdef VBOX_STRICT
642 sf_i->u32Magic = SF_INODE_INFO_MAGIC_DEAD;
643# endif
644 kfree(sf_i);
645 }
646}
647
648
649/* this is called by vfs when it wants to populate [inode] with data.
650 the only thing that is known about inode at this point is its index
651 hence we can't do anything here, and let lookup/whatever with the
652 job to properly fill then [inode] */
653#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
654static void vbsf_read_inode(struct inode *inode)
655{
656}
657#endif
658
659
660/* vfs is done with [sb] (umount called) call [vbsf_super_info_free] to unmap
661 the folder and free [pSuperInfo] */
662static void vbsf_put_super(struct super_block *sb)
663{
664 struct vbsf_super_info *pSuperInfo;
665
666 pSuperInfo = VBSF_GET_SUPER_INFO(sb);
667 BUG_ON(!pSuperInfo);
668 vbsf_done_backing_dev(sb, pSuperInfo);
669 vbsf_super_info_free(pSuperInfo);
670}
671
672
673/**
674 * Get file system statistics.
675 */
676#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
677static int vbsf_statfs(struct dentry *dentry, struct kstatfs *stat)
678#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73)
679static int vbsf_statfs(struct super_block *sb, struct kstatfs *stat)
680#else
681static int vbsf_statfs(struct super_block *sb, struct statfs *stat)
682#endif
683{
684#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
685 struct super_block *sb = dentry->d_inode->i_sb;
686#endif
687 int rc;
688 VBOXSFVOLINFOREQ *pReq = (VBOXSFVOLINFOREQ *)VbglR0PhysHeapAlloc(sizeof(*pReq));
689 if (pReq) {
690 SHFLVOLINFO *pVolInfo = &pReq->VolInfo;
691 struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
692 rc = VbglR0SfHostReqQueryVolInfo(pSuperInfo->map.root, pReq, SHFL_HANDLE_ROOT);
693 if (RT_SUCCESS(rc)) {
694 stat->f_type = UINT32_C(0x786f4256); /* 'VBox' little endian */
695 stat->f_bsize = pVolInfo->ulBytesPerAllocationUnit;
696#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 73)
697 stat->f_frsize = pVolInfo->ulBytesPerAllocationUnit;
698#endif
699 stat->f_blocks = pVolInfo->ullTotalAllocationBytes
700 / pVolInfo->ulBytesPerAllocationUnit;
701 stat->f_bfree = pVolInfo->ullAvailableAllocationBytes
702 / pVolInfo->ulBytesPerAllocationUnit;
703 stat->f_bavail = pVolInfo->ullAvailableAllocationBytes
704 / pVolInfo->ulBytesPerAllocationUnit;
705 stat->f_files = 1000;
706 stat->f_ffree = 1000000; /* don't return 0 here since the guest may think
707 * that it is not possible to create any more files */
708 stat->f_fsid.val[0] = 0;
709 stat->f_fsid.val[1] = 0;
710 stat->f_namelen = 255;
711#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
712 stat->f_flags = 0; /* not valid */
713#endif
714 RT_ZERO(stat->f_spare);
715 rc = 0;
716 } else
717 rc = -RTErrConvertToErrno(rc);
718 VbglR0PhysHeapFree(pReq);
719 } else
720 rc = -ENOMEM;
721 return rc;
722}
723
724static int vbsf_remount_fs(struct super_block *sb, int *flags, char *data)
725{
726#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 23)
727 struct vbsf_super_info *pSuperInfo = pSuperInfo = VBSF_GET_SUPER_INFO(sb);
728 struct vbsf_inode_info *sf_i;
729 struct inode *iroot;
730 SHFLFSOBJINFO fsinfo;
731 int err;
732 Assert(pSuperInfo);
733
734 if (data && data[0] != 0) {
735 struct vbsf_mount_info_new *info = (struct vbsf_mount_info_new *)data;
736 if ( info->nullchar == '\0'
737 && info->signature[0] == VBSF_MOUNT_SIGNATURE_BYTE_0
738 && info->signature[1] == VBSF_MOUNT_SIGNATURE_BYTE_1
739 && info->signature[2] == VBSF_MOUNT_SIGNATURE_BYTE_2) {
740 vbsf_super_info_copy_remount_options(pSuperInfo, info);
741 }
742 }
743
744 iroot = ilookup(sb, 0);
745 if (!iroot)
746 return -ENOSYS;
747
748 sf_i = VBSF_GET_INODE_INFO(iroot);
749 err = vbsf_stat(__func__, pSuperInfo, sf_i->path, &fsinfo, 0);
750 BUG_ON(err != 0);
751 vbsf_init_inode(iroot, sf_i, &fsinfo, pSuperInfo);
752 /*unlock_new_inode(iroot); */
753 return 0;
754#else /* LINUX_VERSION_CODE < 2.4.23 */
755 return -ENOSYS;
756#endif /* LINUX_VERSION_CODE < 2.4.23 */
757}
758
759
760/**
761 * Show mount options.
762 *
763 * This is needed by the VBoxService automounter in order for it to pick up
764 * the the 'szTag' option value it sets on its mount.
765 */
766#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
767static int vbsf_show_options(struct seq_file *m, struct vfsmount *mnt)
768#else
769static int vbsf_show_options(struct seq_file *m, struct dentry *root)
770#endif
771{
772#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0)
773 struct super_block *sb = mnt->mnt_sb;
774#else
775 struct super_block *sb = root->d_sb;
776#endif
777 struct vbsf_super_info *pSuperInfo = VBSF_GET_SUPER_INFO(sb);
778 if (pSuperInfo) {
779 /* Performance related options: */
780 if (pSuperInfo->msTTL != -1)
781 seq_printf(m, ",ttl=%d", pSuperInfo->msTTL);
782 if (pSuperInfo->msDirCacheTTL >= 0)
783 seq_printf(m, ",dcachettl=%d", pSuperInfo->msDirCacheTTL);
784 if (pSuperInfo->msInodeTTL >= 0)
785 seq_printf(m, ",inodettl=%d", pSuperInfo->msInodeTTL);
786 if (pSuperInfo->cMaxIoPages != VBSF_DEFAULT_MAX_IO_PAGES)
787 seq_printf(m, ",maxiopages=%u", pSuperInfo->cMaxIoPages);
788 if (pSuperInfo->cbDirBuf != VBSF_DEFAULT_DIR_BUF_SIZE)
789 seq_printf(m, ",dirbuf=%u", pSuperInfo->cbDirBuf);
790 switch (pSuperInfo->enmCacheMode) {
791 default: AssertFailed();
792 case kVbsfCacheMode_Strict:
793 break;
794 case kVbsfCacheMode_None: seq_puts(m, ",cache=none"); break;
795 case kVbsfCacheMode_Read: seq_puts(m, ",cache=read"); break;
796 case kVbsfCacheMode_ReadWrite: seq_puts(m, ",cache=readwrite"); break;
797 }
798
799 /* Attributes and NLS: */
800 seq_printf(m, ",iocharset=%s", pSuperInfo->nls ? pSuperInfo->nls->charset : "utf8");
801 seq_printf(m, ",uid=%u,gid=%u", pSuperInfo->uid, pSuperInfo->gid);
802 if (pSuperInfo->dmode != ~0)
803 seq_printf(m, ",dmode=0%o", pSuperInfo->dmode);
804 if (pSuperInfo->fmode != ~0)
805 seq_printf(m, ",fmode=0%o", pSuperInfo->fmode);
806 if (pSuperInfo->dmask != 0)
807 seq_printf(m, ",dmask=0%o", pSuperInfo->dmask);
808 if (pSuperInfo->fmask != 0)
809 seq_printf(m, ",fmask=0%o", pSuperInfo->fmask);
810
811 /* Misc: */
812 if (pSuperInfo->szTag[0] != '\0') {
813 seq_puts(m, ",tag=");
814 seq_escape(m, pSuperInfo->szTag, " \t\n\\");
815 }
816 }
817 return 0;
818}
819
820
821/**
822 * Super block operations.
823 */
824static struct super_operations g_vbsf_super_ops = {
825#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
826 .clear_inode = vbsf_clear_inode,
827#else
828 .evict_inode = vbsf_evict_inode,
829#endif
830#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
831 .read_inode = vbsf_read_inode,
832#endif
833 .put_super = vbsf_put_super,
834 .statfs = vbsf_statfs,
835 .remount_fs = vbsf_remount_fs,
836 .show_options = vbsf_show_options
837};
838
839
840
841/*********************************************************************************************************************************
842* File system type related stuff. *
843*********************************************************************************************************************************/
844
845#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 4)
846
847static int vbsf_read_super_26(struct super_block *sb, void *data, int flags)
848{
849 int err;
850
851 TRACE();
852 err = vbsf_read_super_aux(sb, data, flags);
853 if (err)
854 printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
855
856 return err;
857}
858
859# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
860static struct super_block *vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
861{
862 TRACE();
863 return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26);
864}
865# elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
866static int vbsf_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt)
867{
868 TRACE();
869 return get_sb_nodev(fs_type, flags, data, vbsf_read_super_26, mnt);
870}
871# else /* LINUX_VERSION_CODE >= 2.6.39 */
872static struct dentry *sf_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data)
873{
874 TRACE();
875 return mount_nodev(fs_type, flags, data, vbsf_read_super_26);
876}
877# endif /* LINUX_VERSION_CODE >= 2.6.39 */
878
879/**
880 * File system registration structure.
881 */
882static struct file_system_type g_vboxsf_fs_type = {
883 .owner = THIS_MODULE,
884 .name = "vboxsf",
885# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
886 .get_sb = vbsf_get_sb,
887# else
888 .mount = sf_mount,
889# endif
890 .kill_sb = kill_anon_super
891};
892
893#else /* LINUX_VERSION_CODE < 2.5.4 */
894
895static struct super_block *vbsf_read_super_24(struct super_block *sb, void *data, int flags)
896{
897 int err;
898
899 TRACE();
900 err = vbsf_read_super_aux(sb, data, flags);
901 if (err) {
902 printk(KERN_DEBUG "vbsf_read_super_aux err=%d\n", err);
903 return NULL;
904 }
905
906 return sb;
907}
908
909static DECLARE_FSTYPE(g_vboxsf_fs_type, "vboxsf", vbsf_read_super_24, 0);
910
911#endif /* LINUX_VERSION_CODE < 2.5.4 */
912
913
914
915/*********************************************************************************************************************************
916* Module stuff *
917*********************************************************************************************************************************/
918
919/**
920 * Called on module initialization.
921 */
922static int __init init(void)
923{
924 int rc;
925 SFLOGFLOW(("vboxsf: init\n"));
926
927 /*
928 * Must be paranoid about the vbsf_mount_info_new size.
929 */
930 AssertCompile(sizeof(struct vbsf_mount_info_new) <= PAGE_SIZE);
931 if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE) {
932 printk(KERN_ERR
933 "vboxsf: Mount information structure is too large %lu\n"
934 "vboxsf: Must be less than or equal to %lu\n",
935 (unsigned long)sizeof(struct vbsf_mount_info_new),
936 (unsigned long)PAGE_SIZE);
937 return -EINVAL;
938 }
939
940 /*
941 * Initialize stuff.
942 */
943 spin_lock_init(&g_SfHandleLock);
944 rc = VbglR0SfInit();
945 if (RT_SUCCESS(rc)) {
946 /*
947 * Try connect to the shared folder HGCM service.
948 * It is possible it is not there.
949 */
950 rc = VbglR0SfConnect(&g_SfClient);
951 if (RT_SUCCESS(rc)) {
952 /*
953 * Query host HGCM features and afterwards (must be last) shared folder features.
954 */
955 rc = VbglR0QueryHostFeatures(&g_fHostFeatures);
956 if (RT_FAILURE(rc))
957 {
958 LogRel(("vboxsf: VbglR0QueryHostFeatures failed: rc=%Rrc (ignored)\n", rc));
959 g_fHostFeatures = 0;
960 }
961 VbglR0SfHostReqQueryFeaturesSimple(&g_fSfFeatures, &g_uSfLastFunction);
962 LogRel(("vboxsf: g_fHostFeatures=%#x g_fSfFeatures=%#RX64 g_uSfLastFunction=%u\n",
963 g_fHostFeatures, g_fSfFeatures, g_uSfLastFunction));
964
965 /*
966 * Tell the shared folder service about our expectations:
967 * - UTF-8 strings (rather than UTF-16)
968 * - Wheter to return or follow (default) symbolic links.
969 */
970 rc = VbglR0SfHostReqSetUtf8Simple();
971 if (RT_SUCCESS(rc)) {
972 if (!g_fFollowSymlinks) {
973 rc = VbglR0SfHostReqSetSymlinksSimple();
974 if (RT_FAILURE(rc))
975 printk(KERN_WARNING "vboxsf: Host unable to enable showing symlinks, rc=%d\n", rc);
976 }
977 /*
978 * Now that we're ready for action, try register the
979 * file system with the kernel.
980 */
981 rc = register_filesystem(&g_vboxsf_fs_type);
982 if (rc == 0) {
983 printk(KERN_INFO "vboxsf: Successfully loaded version " VBOX_VERSION_STRING "\n");
984 return 0;
985 }
986
987 /*
988 * Failed. Bail out.
989 */
990 LogRel(("vboxsf: register_filesystem failed: rc=%d\n", rc));
991 } else {
992 LogRel(("vboxsf: VbglR0SfSetUtf8 failed, rc=%Rrc\n", rc));
993 rc = -EPROTO;
994 }
995 VbglR0SfDisconnect(&g_SfClient);
996 } else {
997 LogRel(("vboxsf: VbglR0SfConnect failed, rc=%Rrc\n", rc));
998 rc = rc == VERR_HGCM_SERVICE_NOT_FOUND ? -EHOSTDOWN : -ECONNREFUSED;
999 }
1000 VbglR0SfTerm();
1001 } else {
1002 LogRel(("vboxsf: VbglR0SfInit failed, rc=%Rrc\n", rc));
1003 rc = -EPROTO;
1004 }
1005 return rc;
1006}
1007
1008
1009/**
1010 * Called on module finalization.
1011 */
1012static void __exit fini(void)
1013{
1014 SFLOGFLOW(("vboxsf: fini\n"));
1015
1016 unregister_filesystem(&g_vboxsf_fs_type);
1017 VbglR0SfDisconnect(&g_SfClient);
1018 VbglR0SfTerm();
1019}
1020
1021
1022/*
1023 * Module parameters.
1024 */
1025#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 52)
1026module_param_named(follow_symlinks, g_fFollowSymlinks, int, 0);
1027MODULE_PARM_DESC(follow_symlinks,
1028 "Let host resolve symlinks rather than showing them");
1029#endif
1030
1031
1032/*
1033 * Module declaration related bits.
1034 */
1035module_init(init);
1036module_exit(fini);
1037
1038MODULE_DESCRIPTION(VBOX_PRODUCT " VFS Module for Host File System Access");
1039MODULE_AUTHOR(VBOX_VENDOR);
1040MODULE_LICENSE("GPL and additional rights");
1041#ifdef MODULE_ALIAS_FS
1042MODULE_ALIAS_FS("vboxsf");
1043#endif
1044#ifdef MODULE_VERSION
1045MODULE_VERSION(VBOX_VERSION_STRING " r" RT_XSTR(VBOX_SVN_REV));
1046#endif
1047
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