VirtualBox

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

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

linux/vboxsf: Return -EPERM when the host refuses to create symlinks. Added iocharset to /proc/mount output and skipped default dmode, fmode, dmask and fmask values as the first two couldn't be parsed by the mount helper. Fixed the mount helper so it can parse it in case someone gets smart and 'fixes' the code again. bugref:9172

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