VirtualBox

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

Last change on this file since 78412 was 78204, checked in by vboxsync, 6 years ago

linux/vboxsf: Warnings. bugref:9172

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