vfsmod.c revision d3e0466e19699ab16033a59cd252b173e568abd1
/** @file
*
* vboxsf -- VirtualBox Guest Additions for Linux:
* Virtual File System for VirtualBox Shared Folders
*
* Module initialization/finalization
* File system registration/deregistration
* Superblock reading
* Few utility functions
*/
/*
* Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/**
* @note Anyone wishing to make changes here might wish to take a look at
* which seems to be the closest there is to official documentation on
* writing filesystem drivers for Linux.
*/
#include "vfsmod.h"
MODULE_LICENSE("GPL");
#ifdef MODULE_VERSION
#endif
/* globals */
/* forward declarations */
static struct super_operations sf_super_ops;
/* allocate global info, try to map host share */
{
struct sf_glob_info *sf_g;
TRACE();
if (!sf_g)
{
LogRelFunc(("could not allocate memory for global info\n"));
goto fail0;
}
{
/* An old version of mount.vboxsf made the syscall. Translate the
* old parameters to the new structure. */
static struct vbsf_mount_info_new info_compat;
info = &info_compat;
}
if (name_len > 0xfffe)
{
err = -ENAMETOOLONG;
LogFunc(("map name too big\n"));
goto fail1;
}
if (!str_name)
{
LogRelFunc(("could not allocate memory for host name\n"));
goto fail1;
}
/* Check if NLS charset is valid and not points to UTF8 table */
{
else
{
{
goto fail1;
}
}
}
else
{
#ifdef CONFIG_NLS_DEFAULT
/* If no NLS charset specified, try to load the default
* one if it's not points to UTF8. */
else
#else
#endif
}
if (RT_FAILURE(rc))
{
goto fail2;
}
{
/* new fields */
}
else
{
}
return 0;
return err;
}
/* unmap the share and free global info [sf_g] */
static void
{
int rc;
TRACE();
if (RT_FAILURE(rc))
}
/**
* This is called (by sf_read_super_[24|26] when vfs mounts the fs and
* wants to read super_block.
*
* calls [sf_glob_alloc] to map the folder and allocate global
* information structure.
*
* initializes [sb], initializes root inode and dentry.
*
* should respect [flags]
*/
{
int err;
struct sf_inode_info *sf_i;
struct sf_glob_info *sf_g;
struct vbsf_mount_info_new *info;
bool fInodePut = true;
TRACE();
if (!data)
{
LogFunc(("no mount info specified\n"));
return -EINVAL;
}
if (flags & MS_REMOUNT)
{
LogFunc(("remounting is not supported\n"));
return -ENOSYS;
}
if (err)
goto fail0;
if (!sf_i)
{
LogRelFunc(("could not allocate memory for root inode info\n"));
goto fail1;
}
{
LogRelFunc(("could not allocate memory for root inode path\n"));
goto fail2;
}
sf_i->force_reread = 0;
if (err)
{
LogFunc(("could not stat root of share\n"));
goto fail3;
}
*
* Must by less than or equal to INT64_MAX despite the fact that the
* declaration of this variable is unsigned long long. See determination
* of 'loff_t max' in fs/read_write.c / do_sendfile(). I don't know the
* correct limit but MAX_LFS_FILESIZE (8TB-1 on 32-bit boxes) takes the
* page cache into account and is the suggested limit. */
# if defined MAX_LFS_FILESIZE
# else
# endif
#endif
#else
#endif
if (!iroot)
{
LogFunc(("could not get root inode\n"));
goto fail3;
}
if (sf_init_backing_dev(sf_g))
{
LogFunc(("could not init bdi\n"));
#endif
goto fail4;
}
#endif
#else
#endif
if (!droot)
{
LogFunc(("d_alloc_root failed\n"));
fInodePut = false;
#endif
goto fail5;
}
return 0;
if (fInodePut)
return err;
}
static struct super_block *
{
int err;
TRACE();
if (err)
return NULL;
return sb;
}
#endif
/* this is called when vfs is about to destroy the [inode]. all
resources associated with this [inode] must be cleared here */
{
struct sf_inode_info *sf_i;
TRACE();
if (!sf_i)
return;
}
#else
{
struct sf_inode_info *sf_i;
TRACE();
# else
# endif
if (!sf_i)
return;
}
#endif
/* this is called by vfs when it wants to populate [inode] with data.
the only thing that is known about inode at this point is its index
job to properly fill then [inode] */
{
}
#endif
/* vfs is done with [sb] (umount called) call [sf_glob_free] to unmap
the folder and free [sf_g] */
{
struct sf_glob_info *sf_g;
}
{
}
#else
{
}
#endif
{
struct sf_glob_info *sf_g;
struct sf_inode_info *sf_i;
int err;
{
struct vbsf_mount_info_new *info =
(struct vbsf_mount_info_new *)data;
{
}
}
if (!iroot)
return -ENOSYS;
/*unlock_new_inode(iroot);*/
return 0;
#else
return -ENOSYS;
#endif
}
static struct super_operations sf_super_ops =
{
#else
#endif
#endif
};
#else
static int
{
int err;
TRACE();
if (err)
return err;
}
{
TRACE();
}
{
TRACE();
}
# else
{
TRACE();
}
# endif
static struct file_system_type vboxsf_fs_type =
{
.owner = THIS_MODULE,
.name = "vboxsf",
# else
# endif
};
#endif
static int follow_symlinks = 0;
module_param(follow_symlinks, int, 0);
#endif
/* Module initialization/finalization handlers */
{
int rcVBox;
int rcRet = 0;
int err;
TRACE();
if (sizeof(struct vbsf_mount_info_new) > PAGE_SIZE)
{
"Mount information structure is too large %lu\n"
"Must be less than or equal to %lu\n",
(unsigned long)sizeof (struct vbsf_mount_info_new),
(unsigned long)PAGE_SIZE);
return -EINVAL;
}
if (err)
{
return err;
}
if (RT_FAILURE(rcVBox))
{
goto fail0;
}
if (RT_FAILURE(rcVBox))
{
goto fail1;
}
if (RT_FAILURE(rcVBox))
{
goto fail2;
}
if (!follow_symlinks)
{
if (RT_FAILURE(rcVBox))
{
"vboxsf: Host unable to show symlinks, rc=%d\n",
rcVBox);
}
}
#endif
"vboxsf: Successfully loaded version " VBOX_VERSION_STRING
return 0;
vboxUninit();
return rcRet;
}
{
TRACE();
vboxUninit();
}
/* C++ hack */
int __gxx_personality_v0 = 0xdeadbeef;