VirtualBox

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

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

linux/vboxsf: vbsf_remount_fs() calls ilookup(root_inode) which increases its reference count via iget() but is missing a corresponding iput()

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