vmblock-only/ 0000755 0000000 0000000 00000000000 12025726673 012202 5 ustar root root vmblock-only/linux/ 0000755 0000000 0000000 00000000000 12025726674 013342 5 ustar root root vmblock-only/linux/control.c 0000444 0000000 0000000 00000021034 12025726674 015164 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* control.c --
*
* Control operations for the vmblock driver.
*
*/
#include "driver-config.h"
#include
#include
#include
#include "compat_uaccess.h"
#include "compat_fs.h"
#include "vmblockInt.h"
#include "block.h"
/* procfs initialization/cleanup functions */
static int SetupProcDevice(void);
static int CleanupProcDevice(void);
/* procfs entry file operations */
ssize_t ControlFileOpWrite(struct file *filp, const char __user *buf,
size_t cmd, loff_t *ppos);
static int ControlFileOpRelease(struct inode *inode, struct file *file);
static struct proc_dir_entry *controlProcDirEntry;
struct file_operations ControlFileOps = {
.owner = THIS_MODULE,
.write = ControlFileOpWrite,
.release = ControlFileOpRelease,
};
/* Public initialization/cleanup routines */
/*
*----------------------------------------------------------------------------
*
* VMBlockInitControlOps --
*
* Sets up state for control operations.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
VMBlockInitControlOps(void)
{
int ret;
ret = BlockInit();
if (ret < 0) {
Warning("VMBlockInitControlOps: could not initialize blocking ops.\n");
return ret;
}
ret = SetupProcDevice();
if (ret < 0) {
Warning("VMBlockInitControlOps: could not setup proc device.\n");
BlockCleanup();
return ret;
}
return 0;
}
/*
*----------------------------------------------------------------------------
*
* VMBlockCleanupControlOps --
*
* Cleans up state for control operations.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
VMBlockCleanupControlOps(void)
{
int ret;
ret = CleanupProcDevice();
if (ret < 0) {
Warning("VMBlockCleanupControlOps: could not cleanup proc device.\n");
return ret;
}
BlockCleanup();
return 0;
}
/* Private initialization/cleanup routines */
/*
*----------------------------------------------------------------------------
*
* SetupProcDevice --
*
* Adds entries to /proc used to control file blocks.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static int
SetupProcDevice(void)
{
struct proc_dir_entry *controlProcEntry;
struct proc_dir_entry *controlProcMountpoint;
/* Create /proc/fs/vmblock */
controlProcDirEntry = proc_mkdir(VMBLOCK_CONTROL_PROC_DIRNAME, NULL);
if (!controlProcDirEntry) {
Warning("SetupProcDevice: could not create /proc/"
VMBLOCK_CONTROL_PROC_DIRNAME "\n");
return -EINVAL;
}
controlProcDirEntry->owner = THIS_MODULE;
/* Create /proc/fs/vmblock/mountPoint */
controlProcMountpoint = proc_mkdir(VMBLOCK_CONTROL_MOUNTPOINT,
controlProcDirEntry);
if (!controlProcMountpoint) {
Warning("SetupProcDevice: could not create "
VMBLOCK_MOUNT_POINT "\n");
remove_proc_entry(VMBLOCK_CONTROL_PROC_DIRNAME, NULL);
return -EINVAL;
}
controlProcMountpoint->owner = THIS_MODULE;
/* Create /proc/fs/vmblock/dev */
controlProcEntry = create_proc_entry(VMBLOCK_CONTROL_DEVNAME,
VMBLOCK_CONTROL_MODE,
controlProcDirEntry);
if (!controlProcEntry) {
Warning("SetupProcDevice: could not create " VMBLOCK_DEVICE "\n");
remove_proc_entry(VMBLOCK_CONTROL_MOUNTPOINT, controlProcDirEntry);
remove_proc_entry(VMBLOCK_CONTROL_PROC_DIRNAME, NULL);
return -EINVAL;
}
controlProcEntry->proc_fops = &ControlFileOps;
return 0;
}
/*
*----------------------------------------------------------------------------
*
* CleanupProcDevice --
*
* Removes /proc entries for controlling file blocks.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static int
CleanupProcDevice(void)
{
if (controlProcDirEntry) {
remove_proc_entry(VMBLOCK_CONTROL_MOUNTPOINT, controlProcDirEntry);
remove_proc_entry(VMBLOCK_CONTROL_DEVNAME, controlProcDirEntry);
remove_proc_entry(VMBLOCK_CONTROL_PROC_DIRNAME, NULL);
}
return 0;
}
/* procfs file operations */
/*
*----------------------------------------------------------------------------
*
* ControlFileOpWrite --
*
* write implementation for our control file. This accepts either add or
* delete commands and the buffer contains the file to block.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
ssize_t
ControlFileOpWrite(struct file *file, // IN: Opened file, used for ID
const char __user *buf, // IN: NUL-terminated filename
size_t cmd, // IN: VMBlock command (usually count)
loff_t *ppos) // IN/OUT: File offset (unused)
{
int ret;
ssize_t i;
char *filename;
#ifdef VMX86_DEVEL
if (cmd == VMBLOCK_LIST_FILEBLOCKS) {
BlockListFileBlocks();
return 0;
}
#endif
/*
* XXX: Can we GPL our modules already? This is gross. On kernels 2.6.6
* through 2.6.12 when CONFIG_AUDITSYSCALL is defined, putname() turns into
* a macro that calls audit_putname(), which happens to only be exported to
* GPL modules (until 2.6.9). Here we work around this by calling
* __getname() and __putname() to get our path buffer directly,
* side-stepping the syscall auditing and doing the copy from user space
* ourself. Change this back once we GPL the module.
*/
filename = compat___getname();
if (!filename) {
Warning("ControlFileOpWrite: Could not obtain memory for filename.\n");
return -ENOMEM;
}
/*
* XXX: compat___getname() returns a pointer to a PATH_MAX-sized buffer.
* Hard-coding this size is also gross, but it's our only option here and
* InodeOpLookup() already set a bad example by doing this.
*/
ret = strncpy_from_user(filename, buf, PATH_MAX);
if (ret < 0 || ret >= PATH_MAX) {
Warning("ControlFileOpWrite: Could not access provided user buffer.\n");
ret = ret < 0 ? ret : -ENAMETOOLONG;
goto exit;
}
/* Remove all trailing path separators. */
for (i = ret - 1; i >= 0 && filename[i] == '/'; i--) {
filename[i] = '\0';
}
if (i < 0) {
ret = -EINVAL;
goto exit;
}
switch (cmd) {
case VMBLOCK_ADD_FILEBLOCK:
ret = BlockAddFileBlock(filename, file);
break;
case VMBLOCK_DEL_FILEBLOCK:
ret = BlockRemoveFileBlock(filename, file);
break;
default:
Warning("ControlFileOpWrite: unrecognized command (%u) recieved\n",
(unsigned)cmd);
ret = -EINVAL;
break;
}
exit:
compat___putname(filename);
return ret;
}
/*
*----------------------------------------------------------------------------
*
* ControlFileOpRelease --
*
* Called when the file is closed.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static int
ControlFileOpRelease(struct inode *inode, // IN
struct file *file) // IN
{
BlockRemoveAllBlocks(file);
return 0;
}
vmblock-only/linux/dentry.c 0000444 0000000 0000000 00000007611 12025726674 015016 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* dentry.c --
*
* Dentry operations for the file system of the vmblock driver.
*
*/
#include "driver-config.h"
#include "compat_fs.h"
#include "compat_namei.h"
#include "vmblockInt.h"
#include "filesystem.h"
#include "block.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 75)
static int DentryOpRevalidate(struct dentry *dentry, struct nameidata *nd);
#else
static int DentryOpRevalidate(struct dentry *dentry, int flags);
#endif
struct dentry_operations LinkDentryOps = {
.d_revalidate = DentryOpRevalidate,
};
/*
*----------------------------------------------------------------------------
*
* DentryOpRevalidate --
*
* This function is invoked every time the dentry is accessed from the cache
* to ensure it is still valid. We use it to block since any threads
* looking up this dentry after the initial lookup should still block if the
* block has not been cleared.
*
* Results:
* 1 if the dentry is valid, 0 if it is not.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 75)
static int
DentryOpRevalidate(struct dentry *dentry, // IN: dentry revalidating
struct nameidata *nd) // IN: lookup flags & intent
#else
static int
DentryOpRevalidate(struct dentry *dentry, // IN: dentry revalidating
int flags) // IN: lookup flags (e.g., LOOKUP_CONTINUE)
#endif
{
VMBlockInodeInfo *iinfo;
struct nameidata actualNd;
struct dentry *actualDentry;
int ret;
if (!dentry) {
Warning("DentryOpRevalidate: invalid args from kernel\n");
return 0;
}
/*
* If a dentry does not have an inode associated with it then
* we are dealing with a negative dentry. Always invalidate a negative
* dentry which will cause a fresh lookup.
*/
if (!dentry->d_inode) {
return 0;
}
iinfo = INODE_TO_IINFO(dentry->d_inode);
if (!iinfo) {
Warning("DentryOpRevalidate: dentry has no fs-specific data\n");
return 0;
}
/* Block if there is a pending block on this file */
BlockWaitOnFile(iinfo->name, NULL);
/*
* If the actual dentry has a revalidate function, we'll let it figure out
* whether the dentry is still valid. If not, do a path lookup to ensure
* that the file still exists.
*/
actualDentry = iinfo->actualDentry;
if (actualDentry &&
actualDentry->d_op &&
actualDentry->d_op->d_revalidate) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 75)
return actualDentry->d_op->d_revalidate(actualDentry, nd);
#else
return actualDentry->d_op->d_revalidate(actualDentry, flags);
#endif
}
if (compat_path_lookup(iinfo->name, 0, &actualNd)) {
LOG(4, "DentryOpRevalidate: [%s] no longer exists\n", iinfo->name);
return 0;
}
ret = compat_vmw_nd_to_dentry(actualNd) &&
compat_vmw_nd_to_dentry(actualNd)->d_inode;
compat_path_release(&actualNd);
LOG(8, "DentryOpRevalidate: [%s] %s revalidated\n",
iinfo->name, ret ? "" : "not");
return ret;
}
vmblock-only/linux/file.c 0000444 0000000 0000000 00000017631 12025726674 014433 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* file.c --
*
* File operations for the file system of the vmblock driver.
*
*/
#include "driver-config.h"
#include
#include "compat_fs.h"
#include "compat_sched.h"
#include "vmblockInt.h"
#include "filesystem.h"
/* Specifically for our filldir_t callback */
typedef struct FilldirInfo {
filldir_t filldir;
void *dirent;
} FilldirInfo;
/* File operations */
static int FileOpOpen(struct inode *inode, struct file *file);
static int FileOpReaddir(struct file *file, void *dirent, filldir_t filldir);
static int FileOpRelease(struct inode *inode, struct file *file);
/* Local functions */
#if defined(VMW_FILLDIR_2618)
static int Filldir(void *buf, const char *name, int namelen,
loff_t offset, u64 ino, unsigned int d_type);
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 9)
static int Filldir(void *buf, const char *name, int namelen,
loff_t offset, ino_t ino, unsigned int d_type);
#else
static int Filldir(void *buf, const char *name, int namelen,
off_t offset, ino_t ino, unsigned int d_type);
#endif
struct file_operations RootFileOps = {
.readdir = FileOpReaddir,
.open = FileOpOpen,
.release = FileOpRelease,
};
/* File operations */
/*
*----------------------------------------------------------------------------
*
* FileOpOpen --
*
* Invoked when open(2) has been called on our root inode. We get an open
* file instance of the actual file that we are providing indirect access
* to.
*
* Results:
* 0 on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static int
FileOpOpen(struct inode *inode, // IN
struct file *file) // IN
{
VMBlockInodeInfo *iinfo;
struct file *actualFile;
if (!inode || !file || !INODE_TO_IINFO(inode)) {
Warning("FileOpOpen: invalid args from kernel\n");
return -EINVAL;
}
iinfo = INODE_TO_IINFO(inode);
/*
* Get an open file for the directory we are redirecting to. This ensure we
* can gracefully handle cases where that directory is removed after we are
* mounted.
*/
actualFile = filp_open(iinfo->name, file->f_flags, file->f_flags);
if (IS_ERR(actualFile)) {
Warning("FileOpOpen: could not open file [%s]\n", iinfo->name);
file->private_data = NULL;
return PTR_ERR(actualFile);
}
/*
* If the file opened is the same as the one retrieved for the file then we
* shouldn't allow the open to happen. This can only occur if the
* redirected root directory specified at mount time is the same as where
* the mount is placed. Later in FileOpReaddir() we'd call vfs_readdir()
* and that would try to acquire the inode's semaphore; if the two inodes
* are the same we'll deadlock.
*/
if (actualFile->f_dentry && inode == actualFile->f_dentry->d_inode) {
Warning("FileOpOpen: identical inode encountered, open cannot succeed.\n");
if (filp_close(actualFile, current->files) < 0) {
Warning("FileOpOpen: unable to close opened file.\n");
}
return -EINVAL;
}
file->private_data = actualFile;
return 0;
}
/*
*----------------------------------------------------------------------------
*
* FileOpReaddir --
*
* Invoked when a user invokes getdents(2) or readdir(2) on the root of our
* file system. We perform a readdir on the actual underlying file but
* interpose the callback by providing our own Filldir() function. This
* enables us to change dentry types to symlinks.
*
* Results:
* 0 on success, negative error code on error.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static int
FileOpReaddir(struct file *file, // IN
void *dirent, // IN
filldir_t filldir) // IN
{
int ret;
FilldirInfo info;
struct file *actualFile;
if (!file) {
Warning("FileOpReaddir: invalid args from kernel\n");
return -EINVAL;
}
actualFile = file->private_data;
if (!actualFile) {
Warning("FileOpReaddir: no actual file found\n");
return -EINVAL;
}
info.filldir = filldir;
info.dirent = dirent;
actualFile->f_pos = file->f_pos;
ret = vfs_readdir(actualFile, Filldir, &info);
file->f_pos = actualFile->f_pos;
return ret;
}
/*
*----------------------------------------------------------------------------
*
* FileOpRelease --
*
* Invoked when a user close(2)s the root of our file system. Here we just
* close the actual file we opened in FileOpOpen().
*
* Results:
* 0 on success, negative value on error.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static int
FileOpRelease(struct inode *inode, // IN
struct file *file) // IN
{
int ret;
struct file *actualFile;
if (!inode || !file) {
Warning("FileOpRelease: invalid args from kerel\n");
return -EINVAL;
}
actualFile = file->private_data;
if (!actualFile) {
Warning("FileOpRelease: no actual file found\n");
return -EINVAL;
}
ret = filp_close(actualFile, current->files);
return ret;
}
/* Local functions */
/*
*----------------------------------------------------------------------------
*
* Filldir --
*
* Callback function for readdir that we use in place of the one provided.
* This allows us to specify that each dentry is a symlink, but pass through
* everything else to the original filldir function.
*
* Results:
* Original filldir's return value.
*
* Side effects:
* Directory information gets copied to user's buffer.
*
*----------------------------------------------------------------------------
*/
#if defined(VMW_FILLDIR_2618)
static int
Filldir(void *buf, // IN: Dirent buffer passed from FileOpReaddir
const char *name, // IN: Dirent name
int namelen, // IN: len of dirent's name
loff_t offset, // IN: Offset
u64 ino, // IN: Inode number of dirent
unsigned int d_type) // IN: Type of file
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 9)
static int
Filldir(void *buf, // IN: Dirent buffer passed from FileOpReaddir
const char *name, // IN: Dirent name
int namelen, // IN: len of dirent's name
loff_t offset, // IN: Offset
ino_t ino, // IN: Inode number of dirent
unsigned int d_type) // IN: Type of file
#else
static int
Filldir(void *buf, // IN: Dirent buffer passed from FileOpReaddir
const char *name, // IN: Dirent name
int namelen, // IN: len of dirent's name
off_t offset, // IN: Offset
ino_t ino, // IN: Inode number of dirent
unsigned int d_type) // IN: Type of file
#endif
{
FilldirInfo *info = (FilldirInfo *)buf;
/* Specify DT_LNK regardless */
return info->filldir(info->dirent, name, namelen, offset, ino, DT_LNK);
}
vmblock-only/linux/filesystem.c 0000444 0000000 0000000 00000046416 12025726674 015703 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* filesystem.c --
*
* File system for the vmblock driver.
*
*/
#include "driver-config.h"
#include "compat_kernel.h"
#include
#include
#include
#include "compat_fs.h"
#include "compat_spinlock.h"
#include "compat_namei.h"
#include "compat_slab.h"
#include "os.h"
#include "vmblockInt.h"
#include "filesystem.h"
#define VMBLOCK_ROOT_INO 1
#define GetRootInode(sb) Iget(sb, NULL, NULL, VMBLOCK_ROOT_INO)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 25)
# define KERNEL_25_FS 0
#else
# define KERNEL_25_FS 1
#endif
static struct inode *GetInode(struct super_block *sb, ino_t ino);
/* File system operations */
#if KERNEL_25_FS /* { */
# if defined(VMW_GETSB_2618)
static int FsOpGetSb(struct file_system_type *fsType, int flags,
const char *devName, void *rawData, struct vfsmount *mnt);
# elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 70)
static struct super_block *FsOpGetSb(struct file_system_type *fsType, int flags,
const char *devName, void *rawData);
# else
static struct super_block *FsOpGetSb(struct file_system_type *fsType, int flags,
char *devName, void *rawData);
# endif
#else /* } { */
static struct super_block *FsOpReadSuper24(struct super_block *sb, void *rawData,
int flags);
#endif /* } */
static int FsOpReadSuper(struct super_block *sb, void *rawData, int flags);
/* Utility */
static compat_kmem_cache_ctor InodeCacheCtor;
/* Variables */
compat_kmem_cache *VMBlockInodeCache;
/* Local variables */
static char const *fsRoot;
static size_t fsRootLen;
static struct file_system_type fsType = {
.owner = THIS_MODULE,
.name = VMBLOCK_FS_NAME,
#if KERNEL_25_FS
.get_sb = FsOpGetSb,
.kill_sb = kill_anon_super,
#else
.read_super = FsOpReadSuper24,
#endif
};
/*
* Public functions (with respect to the module)
*/
/*
*----------------------------------------------------------------------------
*
* VMBlockInitFileSystem --
*
* Initializes the file system and registers it with the kernel.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
VMBlockInitFileSystem(char const *root) // IN: directory redirecting to
{
int ret;
if (!root) {
Warning("VMBlockInitFileSystem: root not provided "
"(missing module parameter?)\n");
return -EINVAL;
}
/*
* Here we assume that the provided root is valid so the module will load.
* The mount operation will fail if that is not the case.
*/
fsRoot = root;
fsRootLen = strlen(fsRoot);
if (fsRootLen >= PATH_MAX) {
return -ENAMETOOLONG;
}
/* Initialize our inode slab allocator */
VMBlockInodeCache = os_kmem_cache_create("VMBlockInodeCache",
sizeof (VMBlockInodeInfo),
0,
InodeCacheCtor);
if (!VMBlockInodeCache) {
Warning("VMBlockInitFileSystem: could not initialize inode cache\n");
return -ENOMEM;
}
/* Tell the kernel about our file system */
ret = register_filesystem(&fsType);
if (ret < 0) {
Warning("VMBlockInitFileSystem: could not initialize file system\n");
kmem_cache_destroy(VMBlockInodeCache);
return ret;
}
LOG(4, "file system registered with root of [%s]\n", fsRoot);
return 0;
}
/*
*----------------------------------------------------------------------------
*
* VMBlockCleanupFileSystem --
*
* Cleans up file system and unregisters it with the kernel.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
VMBlockCleanupFileSystem(void)
{
int ret;
kmem_cache_destroy(VMBlockInodeCache);
ret = unregister_filesystem(&fsType);
if (ret < 0) {
Warning("VMBlockCleanupFileSystem: could not unregister file system\n");
return ret;
}
return 0;
}
/*
*----------------------------------------------------------------------------
*
* VMBlockReadInode --
*
* A filesystem wide function that is called to initialize a new inode.
* This is called from two different places depending on the kernel version.
* In older kernels that provide the iget() interface, this function is
* called by the kernel as part of inode initialization (from
* SuperOpReadInode). In newer kernels that call iget_locked(), this
* function is called by filesystem code to initialize the new inode.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
void
VMBlockReadInode(struct inode *inode) // IN: Inode to initialize
{
VMBlockInodeInfo *iinfo = INODE_TO_IINFO(inode);
iinfo->name[0] = '\0';
iinfo->nameLen = 0;
iinfo->actualDentry = NULL;
}
/*
*----------------------------------------------------------------------------
*
* GetNextIno --
*
* Gets the next available inode number.
*
* Results:
* The next available inode number.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
ino_t
GetNextIno(void)
{
static spinlock_t inoLock = SPIN_LOCK_UNLOCKED;
static ino_t nextIno = VMBLOCK_ROOT_INO + 1;
ino_t ret;
/* Too bad atomic_t's don't provide an atomic increment and read ... */
spin_lock(&inoLock);
ret = nextIno++;
spin_unlock(&inoLock);
return ret;
}
/*
*----------------------------------------------------------------------------
*
* GetInode --
*
* This function replaces iget() and should be called instead of it. In newer
* kernels that have removed the iget() interface, GetInode() obtains an inode
* and if it is a new one, then initializes the inode by calling
* VMBlockReadInode(). In older kernels that support the iget() interface,
* VMBlockReadInode() is called by iget() internally by the superblock function
* SuperOpReadInode.
*
* Results:
* A new inode object on success, NULL on error.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static struct inode *
GetInode(struct super_block *sb, // IN: file system superblock object
ino_t ino) // IN: inode number to assign to new inode
{
#ifdef VMW_USE_IGET_LOCKED
struct inode *inode;
inode = iget_locked(sb, ino);
if (!inode) {
return NULL;
} else if (inode->i_state & I_NEW) {
VMBlockReadInode(inode);
unlock_new_inode(inode);
}
return inode;
#else
return iget(sb, ino);
#endif
}
/*
*----------------------------------------------------------------------------
*
* Iget --
*
* Lookup or create a new inode.
*
* Inode creation in detail:
* Throughout the file system, we call the VFS iget() function to get a new
* inode. This in turn invokes our file system's SuperOpAllocInode()
* function, which allocates an inode info structure (VMBlockInodeInfo)
* using the kernel's slab allocator. When a new slab is created, each
* object is initialized with the constructor (InodeCacheCtor()), but that
* occurs only once per struct (e.g., when a struct from a slab is freed and
* reused, the constructor is not invoked again). SuperOpAllocInode() then
* returns the address of the inode struct that is embedded within the inode
* info we have allocated. iget() also invokes our SuperOpReadInode()
* function to do any further file system wide initialization to the inode,
* then returns the inode to us (this function).
*
* Note that in older kernels that don't have the alloc_inode operation
* (where VMW_EMBED_INODE is undefined), the allocation is delayed until
* this function and is contained within the INODE_TO_IINFO macro. That
* allocation is freed in the SuperOpClearInode() function.
*
* This function then constructs the full path of the actual file name and
* does a path_lookup() to see if it exists. If it does, we save a pointer
* to the actual dentry within our inode info for future use. If it
* doesn't, we still provide an inode but indicate that it doesn't exist by
* setting the actual dentry to NULL. Callers that need to handle this case
* differently check for the existence of the actual dentry (and actual
* inode) to ensure the actual file exists.
*
* Results:
* A new inode object on success, NULL on error.
*
* Side effects:
* A path lookup is done for the actual file.
*
*----------------------------------------------------------------------------
*/
struct inode *
Iget(struct super_block *sb, // IN: file system superblock object
struct inode *dir, // IN: containing directory
struct dentry *dentry, // IN: dentry within directory
ino_t ino) // IN: inode number to assign to new inode
{
VMBlockInodeInfo *iinfo;
struct inode *inode;
struct nameidata actualNd;
ASSERT(sb);
inode = GetInode(sb, ino);
if (!inode) {
return NULL;
}
iinfo = INODE_TO_IINFO(inode);
if (!iinfo) {
Warning("Iget: invalid inode provided, or unable to allocate inode info\n");
goto error_inode;
}
/* Populate iinfo->name with the full path of the target file */
if (MakeFullName(dir, dentry, iinfo->name, sizeof iinfo->name) < 0) {
Warning("Iget: could not make full name\n");
goto error_inode;
}
if (compat_path_lookup(iinfo->name, 0, &actualNd)) {
/*
* This file does not exist, so we create an inode that doesn't know
* about its underlying file. Operations that create files and
* directories need an inode to operate on even if there is no actual
* file yet.
*/
iinfo->actualDentry = NULL;
return inode;
}
iinfo->actualDentry = compat_vmw_nd_to_dentry(actualNd);
compat_path_release(&actualNd);
return inode;
error_inode:
iput(inode);
return NULL;
}
/*
*----------------------------------------------------------------------------
*
* InodeCacheCtor --
*
* The constructor for inode info structs that occurs once at slab
* allocation. That is, this is called once for each piece of memory that
* is used to satisfy inode info allocations; it should only be used to
* initialized items that will naturally return to their initialized state
* before deallocation (such as locks, list_heads).
*
* We only invoke the inode's initialization routine since all of the inode
* info members need to be initialized on each allocation (in
* SuperOpReadInode()).
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static void
InodeCacheCtor(COMPAT_KMEM_CACHE_CTOR_ARGS(slabElem)) // IN: allocated slab item to initialize
{
#ifdef VMW_EMBED_INODE
VMBlockInodeInfo *iinfo = slabElem;
inode_init_once(&iinfo->inode);
#endif
}
/*
*----------------------------------------------------------------------------
*
* MakeFullName --
*
* Constructs the full filename from the provided directory and a dentry
* contained within it.
*
* Results:
* Zero on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
MakeFullName(struct inode *dir, // IN : directory
struct dentry *dentry, // IN : dentry in that directory
char *bufOut, // OUT: output buffer
size_t bufOutSize) // IN : size of output buffer
{
ASSERT(bufOut);
/*
* If dir is supplied, contruct the full path of the actual file, otherwise
* it's the root directory.
*/
if (dir == NULL) {
if (fsRootLen >= bufOutSize) {
Warning("MakeFullName: root path was too long.\n");
return -ENAMETOOLONG;
}
memcpy(bufOut, fsRoot, fsRootLen);
bufOut[fsRootLen] = '\0';
} else {
VMBlockInodeInfo *dirIinfo;
ASSERT(dir);
ASSERT(dentry);
if (!dentry->d_name.name) {
Warning("MakeFullName: dentry name is empty\n");
return -EINVAL;
}
dirIinfo = INODE_TO_IINFO(dir);
/*
* If dirIinfo->name[1] is '\0', then it is "/" and we don't need
* another '/' between it and the additional name.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 10)
{
int ret;
ret = snprintf(bufOut, bufOutSize,
dirIinfo->name[1] == '\0' ? "%s%s" : "%s/%s",
dirIinfo->name, dentry->d_name.name);
if (ret >= bufOutSize) {
Warning("MakeFullName: path was too long.\n");
return -ENAMETOOLONG;
}
}
#else
{
/* snprintf was not exported prior to 2.4.10 */
size_t dirLen;
size_t pathSepLen;
size_t dentryLen;
size_t pathLen;
dirLen = strlen(dirIinfo->name);
pathSepLen = dirLen == 1 ? 0 : 1;
dentryLen = strlen(dentry->d_name.name);
pathLen = dirLen + dentryLen + pathSepLen;
if (pathLen >= bufOutSize) {
Warning("MakeFullName: path was too long.\n");
return -ENAMETOOLONG;
}
memcpy(bufOut, dirIinfo->name, dirLen);
if (pathSepLen == 1) {
ASSERT(dirLen == 1);
bufOut[dirLen] = '/';
}
memcpy(bufOut + dirLen + pathSepLen, dentry->d_name.name, dentryLen);
bufOut[pathLen] = '\0';
}
#endif
}
return 0;
}
/* File system operations */
/*
*-----------------------------------------------------------------------------
*
* FsOpReadSuper --
*
* The main entry point of the filesystem side of the driver. Called when
* a userland process does a mount(2) of an hgfs filesystem. This makes the
* whole driver transition from its initial state to state 1. Fill the
* content of the uninitialized superblock provided by the kernel.
*
* 'rawData' is a pointer (that can be NULL) to a kernel buffer (whose
* size is <= PAGE_SIZE) that corresponds to the filesystem-specific 'data'
* argument passed to mount(2).
*
* Results:
* zero and initialized superblock on success
* negative value on failure
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static int
FsOpReadSuper(struct super_block *sb, // OUT: Superblock object
void *rawData, // IN: Fs-specific mount data
int flags) // IN: Mount flags
{
struct inode *rootInode;
struct dentry *rootDentry;
if (!sb) {
Warning("FsOpReadSuper: invalid arg from kernel\n");
return -EINVAL;
}
sb->s_magic = VMBLOCK_SUPER_MAGIC;
sb->s_blocksize = 1024;
sb->s_op = &VMBlockSuperOps;
/*
* Make root inode and dentry. Ensure that the directory we are redirecting
* to has an actual dentry and inode, and that it is in fact a directory.
*/
rootInode = GetRootInode(sb);
if (!rootInode) {
return -EINVAL;
}
if (!INODE_TO_IINFO(rootInode) ||
!INODE_TO_ACTUALDENTRY(rootInode) ||
!INODE_TO_ACTUALINODE(rootInode) ||
!S_ISDIR(INODE_TO_ACTUALINODE(rootInode)->i_mode)) {
iput(rootInode);
return -EINVAL;
}
rootDentry = d_alloc_root(rootInode);
if (!rootDentry) {
iput(rootInode);
return -ENOMEM;
}
sb->s_root = rootDentry;
rootInode->i_op = &RootInodeOps;
rootInode->i_fop = &RootFileOps;
rootInode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
LOG(4, "%s file system mounted\n", VMBLOCK_FS_NAME);
return 0;
}
#if KERNEL_25_FS /* { */
#if defined(VMW_GETSB_2618)
/*
*-----------------------------------------------------------------------------
*
* FsOpGetSb --
*
* Invokes generic kernel code to prepare superblock for
* deviceless filesystem.
*
* Results:
* 0 on success
* negative error code on failure
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static int
FsOpGetSb(struct file_system_type *fs_type, // IN: file system type of mount
int flags, // IN: mount flags
const char *dev_name, // IN: device mounting on
void *rawData, // IN: mount arguments
struct vfsmount *mnt) // IN: vfs mount
{
return get_sb_nodev(fs_type, flags, rawData, FsOpReadSuper, mnt);
}
#else
/*
*-----------------------------------------------------------------------------
*
* FsOpGetSb --
*
* Invokes generic kernel code to prepare superblock for
* deviceless filesystem.
*
* Results:
* The initialized superblock on success
* NULL on failure
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 70)
static struct super_block *
FsOpGetSb(struct file_system_type *fs_type, // IN: file system type of mount
int flags, // IN: mount flags
const char *dev_name, // IN: device mounting on
void *rawData) // IN: mount arguments
#else
static struct super_block *
FsOpGetSb(struct file_system_type *fs_type, // IN: file system type of mount
int flags, // IN: mount flags
char *dev_name, // IN: device mounting on
void *rawData) // IN: mount arguments
#endif
{
return get_sb_nodev(fs_type, flags, rawData, FsOpReadSuper);
}
#endif
#else /* } { */
/*
*-----------------------------------------------------------------------------
*
* FsOpReadSuper24 --
*
* Compatibility wrapper for 2.4.x kernels read_super.
* Converts success to sb, and failure to NULL.
*
* Results:
* The initialized superblock on success
* NULL on failure
*
* Side effects:
* None
*
*-----------------------------------------------------------------------------
*/
static struct super_block *
FsOpReadSuper24(struct super_block *sb, // OUT: Superblock object
void *rawData, // IN : mount arguments
int flags) // IN : mount flags
{
return FsOpReadSuper(sb, rawData, flags) ? NULL : sb;
}
#endif /* } */
vmblock-only/linux/filesystem.h 0000444 0000000 0000000 00000011370 12025726674 015677 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* filesystem.h --
*
* Definitions and prototypes for file system portion of vmblock driver.
*
* There are currently two classes of files in the blocking file system: the
* root directory and symlinks to actual files on the file system. The root
* directory provides a way to lookup directory entries in the directory we
* are redirecting to; each of these directory entries is presented as
* a symlink. These symlinks within the root directory contain the path of
* the actual file and will block any time the inode is accessed or dentry is
* revalidated (if there is a pending block). This blocking ensures that any
* access to the file through the symlink will not proceed until the block is
* lifted.
*
* Operation tables for the root directory and symlinks are are named Root*Ops
* and Link*Ops respectively. All operations are preceded by their operation
* type (e.g., the file_operation table's open is named FileOpOpen and the
* inode_operation table's lookup is named InodeOpLookup).
*
* The use of symlinks greatly simplifies the driver's implementation but also
* limits blocking to a depth of one level within the redirected directory
* (since after the symlink is followed all operations are passed on to the
* actual file system and are out of our control). This limitation is fine
* under the current use of this driver.
*/
#ifndef __FILESYSTEM_H__
#define __FILESYSTEM_H__
#include "compat_slab.h"
#include "compat_fs.h"
#include "vm_basic_types.h"
#ifndef container_of
#define container_of(ptr, type, memb) ((type *)((char *)(ptr) - offsetof(type, memb)))
#endif
#ifdef VMW_EMBED_INODE
# define INODE_SET_IINFO(inode, iinfo)
# define INODE_TO_IINFO(_inode) container_of(_inode, VMBlockInodeInfo, inode)
#else
# define INODE_SET_IINFO(inode, iinfo) (inode)->u.generic_ip = iinfo
# define INODE_TO_IINFO(_inode) \
({ \
/* Allocate an inode info for new inodes */ \
if ((_inode)->u.generic_ip == NULL) { \
VMBlockInodeInfo *_iinfo; \
ASSERT(VMBlockInodeCache); \
_iinfo = kmem_cache_alloc(VMBlockInodeCache, SLAB_KERNEL); \
/* We must set the inode info for new inodes */ \
INODE_SET_IINFO(_inode, _iinfo); \
} \
((VMBlockInodeInfo *)((_inode)->u.generic_ip)); \
})
#endif
#define INODE_TO_ACTUALDENTRY(inode) INODE_TO_IINFO(inode)->actualDentry
#define INODE_TO_ACTUALINODE(inode) INODE_TO_IINFO(inode)->actualDentry->d_inode
#define VMBLOCK_SUPER_MAGIC 0xabababab
typedef struct VMBlockInodeInfo {
char name[PATH_MAX];
size_t nameLen;
struct dentry *actualDentry;
#ifdef VMW_EMBED_INODE
/* Embedded inode */
struct inode inode;
#endif
} VMBlockInodeInfo;
ino_t GetNextIno(void);
struct inode *Iget(struct super_block *sb, struct inode *dir,
struct dentry *dentry, ino_t ino);
int MakeFullName(struct inode *dir, struct dentry *dentry,
char *bufOut, size_t bufOutSize);
void VMBlockReadInode(struct inode *inode);
/* Variables */
extern compat_kmem_cache *VMBlockInodeCache;
/* File system wide superblock operations */
extern struct super_operations VMBlockSuperOps;
/* File operations on fs's root inode to read directory entries. */
extern struct file_operations RootFileOps;
/* Inode operations to lookup inodes of directory entries in fs's root inode. */
extern struct inode_operations RootInodeOps;
/* Dentry operations for our symlinks to actual files (to enable blocking). */
extern struct dentry_operations LinkDentryOps;
#endif /* __FILESYSTEM_H__ */
vmblock-only/linux/inode.c 0000444 0000000 0000000 00000015212 12025726674 014603 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* inode.c --
*
* Inode operations for the file system of the vmblock driver.
*
*/
#include "driver-config.h"
#include
#include "compat_fs.h"
#include
#include "compat_namei.h"
#include "compat_uaccess.h"
#include "compat_sched.h"
#include "vmblockInt.h"
#include "filesystem.h"
#include "block.h"
/* Inode operations */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 75)
static struct dentry *InodeOpLookup(struct inode *dir,
struct dentry *dentry, struct nameidata *nd);
#else
static struct dentry *InodeOpLookup(struct inode *dir, struct dentry *dentry);
#endif
static int InodeOpReadlink(struct dentry *dentry, char __user *buffer, int buflen);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
static void *InodeOpFollowlink(struct dentry *dentry, struct nameidata *nd);
#else
static int InodeOpFollowlink(struct dentry *dentry, struct nameidata *nd);
#endif
struct inode_operations RootInodeOps = {
.lookup = InodeOpLookup,
};
static struct inode_operations LinkInodeOps = {
.readlink = InodeOpReadlink,
.follow_link = InodeOpFollowlink,
};
/*
*----------------------------------------------------------------------------
*
* InodeOpLookup --
*
* Looks up a name (dentry) in provided directory. Invoked every time
* a directory entry is traversed in path lookups.
*
* Results:
* NULL on success, negative error code on error.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 75)
static struct dentry *
InodeOpLookup(struct inode *dir, // IN: parent directory's inode
struct dentry *dentry, // IN: dentry to lookup
struct nameidata *nd) // IN: lookup intent and information
#else
static struct dentry *
InodeOpLookup(struct inode *dir, // IN: parent directory's inode
struct dentry *dentry) // IN: dentry to lookup
#endif
{
char *filename;
struct inode *inode;
int ret;
if (!dir || !dentry) {
Warning("InodeOpLookup: invalid args from kernel\n");
return ERR_PTR(-EINVAL);
}
/* The kernel should only pass us our own inodes, but check just to be safe. */
if (!INODE_TO_IINFO(dir)) {
Warning("InodeOpLookup: invalid inode provided\n");
return ERR_PTR(-EINVAL);
}
/* Get a slab from the kernel's names_cache of PATH_MAX-sized buffers. */
filename = compat___getname();
if (!filename) {
Warning("InodeOpLookup: unable to obtain memory for filename.\n");
return ERR_PTR(-ENOMEM);
}
ret = MakeFullName(dir, dentry, filename, PATH_MAX);
if (ret < 0) {
Warning("InodeOpLookup: could not construct full name\n");
compat___putname(filename);
return ERR_PTR(ret);
}
/* Block if there is a pending block on this file */
BlockWaitOnFile(filename, NULL);
compat___putname(filename);
inode = Iget(dir->i_sb, dir, dentry, GetNextIno());
if (!inode) {
Warning("InodeOpLookup: failed to get inode\n");
return ERR_PTR(-ENOMEM);
}
dentry->d_op = &LinkDentryOps;
dentry->d_time = jiffies;
/*
* If the actual file's dentry doesn't have an inode, it means the file we
* are redirecting to doesn't exist. Give back the inode that was created
* for this and add a NULL dentry->inode entry in the dcache. (The NULL
* entry is added so ops to create files/directories are invoked by VFS.)
*/
if (!INODE_TO_ACTUALDENTRY(inode) || !INODE_TO_ACTUALINODE(inode)) {
iput(inode);
d_add(dentry, NULL);
return NULL;
}
inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_size = INODE_TO_IINFO(inode)->nameLen;
inode->i_version = 1;
inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_uid = inode->i_gid = 0;
inode->i_op = &LinkInodeOps;
d_add(dentry, inode);
return NULL;
}
/*
*----------------------------------------------------------------------------
*
* InodeOpReadlink --
*
* Provides the symbolic link's contents to the user. Invoked when
* readlink(2) is invoked on our symlinks.
*
* Results:
* 0 on success, negative error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static int
InodeOpReadlink(struct dentry *dentry, // IN : dentry of symlink
char __user *buffer, // OUT: output buffer (user space)
int buflen) // IN : length of output buffer
{
VMBlockInodeInfo *iinfo;
if (!dentry || !buffer) {
Warning("InodeOpReadlink: invalid args from kernel\n");
return -EINVAL;
}
iinfo = INODE_TO_IINFO(dentry->d_inode);
if (!iinfo) {
return -EINVAL;
}
return vfs_readlink(dentry, buffer, buflen, iinfo->name);
}
/*
*----------------------------------------------------------------------------
*
* InodeOpFollowlink --
*
* Provides the inode corresponding to this symlink through the nameidata
* structure.
*
* Results:
* 0 on success, negative error on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
static void *
#else
static int
#endif
InodeOpFollowlink(struct dentry *dentry, // IN : dentry of symlink
struct nameidata *nd) // OUT: stores result
{
int ret;
VMBlockInodeInfo *iinfo;
if (!dentry) {
Warning("InodeOpReadlink: invalid args from kernel\n");
ret = -EINVAL;
goto out;
}
iinfo = INODE_TO_IINFO(dentry->d_inode);
if (!iinfo) {
ret = -EINVAL;
goto out;
}
ret = vfs_follow_link(nd, iinfo->name);
out:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
return ERR_PTR(ret);
#else
return ret;
#endif
}
vmblock-only/linux/module.c 0000444 0000000 0000000 00000011021 12025726674 014764 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* module.c --
*
* Module loading/unloading functions.
*
*/
#include "driver-config.h"
#include "compat_init.h"
#include "compat_kernel.h"
#include "compat_module.h"
#include
#include
#include "compat_string.h"
#include "vmblockInt.h"
#include "vmblock_version.h"
/* Module parameters */
#ifdef VMX86_DEVEL /* { */
int LOGLEVEL_THRESHOLD = 4;
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
module_param(LOGLEVEL_THRESHOLD, int, 0600);
# else
MODULE_PARM(LOGLEVEL_THRESHOLD, "i");
# endif
MODULE_PARM_DESC(LOGLEVEL_THRESHOLD, "Logging level (0 means no log, "
"10 means very verbose, 4 is default)");
#endif /* } */
static char *root = "/tmp/VMwareDnD";
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
module_param(root, charp, 0600);
#else
MODULE_PARM(root, "s");
#endif
MODULE_PARM_DESC(root, "The directory the file system redirects to.");
/* Module information */
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Blocking File System");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(VMBLOCK_DRIVER_VERSION_STRING);
/*
* Starting with SLE10sp2, Novell requires that IHVs sign a support agreement
* with them and mark their kernel modules as externally supported via a
* change to the module header. If this isn't done, the module will not load
* by default (i.e., neither mkinitrd nor modprobe will accept it).
*/
MODULE_INFO(supported, "external");
/* Functions */
static int VMBlockInit(void);
static void VMBlockExit(void);
/* Define init/exit routines */
module_init(VMBlockInit);
module_exit(VMBlockExit);
/*
*----------------------------------------------------------------------------
*
* VMBlockInit --
*
* Module entry point and initialization.
*
* Results:
* Zero on success, negative value on failure.
*
* Side effects:
* /proc entries are available and file system is registered with kernel and
* ready to be mounted.
*
*----------------------------------------------------------------------------
*/
static int
VMBlockInit(void)
{
int ret;
ret = VMBlockInitControlOps();
if (ret < 0) {
goto error;
}
ret = VMBlockInitFileSystem(root);
if (ret < 0) {
VMBlockCleanupControlOps();
goto error;
}
LOG(4, "module loaded\n");
return 0;
error:
Warning("VMBlock: could not initialize module\n");
return ret;
}
/*
*----------------------------------------------------------------------------
*
* VMBlockExit --
*
* Unloads module from kernel and removes associated state.
*
* Results:
* None.
*
* Side effects:
* Opposite of VMBlockInit(): /proc entries go away and file system is
* unregistered.
*
*----------------------------------------------------------------------------
*/
static void
VMBlockExit(void)
{
VMBlockCleanupControlOps();
VMBlockCleanupFileSystem();
LOG(4, "module unloaded\n");
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 70)
/*
*----------------------------------------------------------------------------
*
* strlcpy --
*
* 2.4 doesn't have strlcpy().
*
* Copies at most count - 1 bytes from src to dest, and ensures dest is NUL
* terminated.
*
* Results:
* Length of src. If src >= count, src was truncated in copy.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
size_t
strlcpy(char *dest, // OUT: destination to copy string to
const char *src, // IN : source to copy string from
size_t count) // IN : size of destination buffer
{
size_t ret;
size_t len;
ret = strlen(src);
len = ret >= count ? count - 1 : ret;
memcpy(dest, src, len);
dest[len] = '\0';
return ret;
}
#endif
vmblock-only/linux/super.c 0000444 0000000 0000000 00000011642 12025726674 014646 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* super.c --
*
* Super operations for the file system portion of the vmblock driver.
*
*/
#include "driver-config.h"
#include "compat_fs.h"
#include "compat_statfs.h"
#include "vmblockInt.h"
#include "filesystem.h"
/* Super block operations */
#ifdef VMW_EMBED_INODE
static struct inode *SuperOpAllocInode(struct super_block *sb);
static void SuperOpDestroyInode(struct inode *inode);
#else
static void SuperOpClearInode(struct inode *inode);
#endif
#ifndef VMW_USE_IGET_LOCKED
static void SuperOpReadInode(struct inode *inode);
#endif
#ifdef VMW_STATFS_2618
static int SuperOpStatfs(struct dentry *dentry, struct compat_kstatfs *stat);
#else
static int SuperOpStatfs(struct super_block *sb, struct compat_kstatfs *stat);
#endif
struct super_operations VMBlockSuperOps = {
#ifdef VMW_EMBED_INODE
.alloc_inode = SuperOpAllocInode,
.destroy_inode = SuperOpDestroyInode,
#else
.clear_inode = SuperOpClearInode,
#endif
#ifndef VMW_USE_IGET_LOCKED
.read_inode = SuperOpReadInode,
#endif
.statfs = SuperOpStatfs,
};
#ifdef VMW_EMBED_INODE
/*
*----------------------------------------------------------------------------
*
* SuperOpAllocInode --
*
* Allocates an inode info from the cache. See function comment for Iget()
* for a complete explanation of how inode allocation works.
*
* Results:
* A pointer to the embedded inode on success, NULL on failure.
*
* Side effects:
* iinfo is initialized by InodeCacheCtor().
*
*----------------------------------------------------------------------------
*/
static struct inode *
SuperOpAllocInode(struct super_block *sb) // IN: superblock of file system
{
VMBlockInodeInfo *iinfo;
iinfo = kmem_cache_alloc(VMBlockInodeCache, GFP_KERNEL);
if (!iinfo) {
Warning("SuperOpAllocInode: could not allocate iinfo\n");
return NULL;
}
/* The inode we give back to VFS is embedded within our inode info struct. */
return &iinfo->inode;
}
#endif
/*
*----------------------------------------------------------------------------
*
* SuperOpDestroyInode --
* SuperOpClearInode --
*
* Destroys the provided inode by freeing the inode info. In the embedded
* inode case, this includes the actual inode itself; in the non-embedded
* inode case, the inode is freed by the kernel.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static void
#ifdef VMW_EMBED_INODE
SuperOpDestroyInode(struct inode *inode) // IN: Inode to free
#else
SuperOpClearInode(struct inode *inode) // IN: Inode to free
#endif
{
kmem_cache_free(VMBlockInodeCache, INODE_TO_IINFO(inode));
}
#ifndef VMW_USE_IGET_LOCKED
/*
*----------------------------------------------------------------------------
*
* SuperOpReadInode --
*
* Performs any filesystem wide inode initialization. This is only called by
* iget() in older kernels that do not support iget_locked(). Newer kernels
* that use the iget_locked() interface are required to initialize the inode
* after it has been returned to the filesystem.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static void
SuperOpReadInode(struct inode *inode) // IN: Inode to initialize
{
VMBlockReadInode(inode);
}
#endif
/*
*----------------------------------------------------------------------------
*
* SuperOpStatfs --
*
* Implements a null statfs.
*
* Results:
* Zero on success, negative error on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
#ifdef VMW_STATFS_2618
static int
SuperOpStatfs(struct dentry *dentry,
struct compat_kstatfs *stat)
#else
static int
SuperOpStatfs(struct super_block *sb,
struct compat_kstatfs *stat)
#endif
{
if (!stat) {
return -EINVAL;
}
stat->f_type = VMBLOCK_SUPER_MAGIC;
stat->f_bsize = 0;
stat->f_namelen = NAME_MAX;
stat->f_blocks = 0;
stat->f_bfree = 0;
stat->f_bavail = 0;
return 0;
}
vmblock-only/linux/vmblockInt.h 0000444 0000000 0000000 00000006427 12025726674 015632 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* vmblockInt.h --
*
* Definitions and prototypes for entire module.
*
* The module is split into two halves, a control half and a file system
* half, and the halves communicate through the blocking functionality in
* block.c. The control half creates a device node for a user space program
* (running as root) to add and delete blocks on files in the file system's
* namespace. The file system provides links to the contents of the
* directory it is redirecting to and blocks according to the file blocks set
* through the control half.
*/
#ifndef __VMBLOCKINT_H__
#define __VMBLOCKINT_H__
#include "compat_version.h"
#include "compat_mm.h"
#include "vmblock.h"
#include "vm_basic_types.h"
#include "vm_assert.h"
#ifdef __KERNEL__
#ifdef VMX86_DEVEL
extern int LOGLEVEL_THRESHOLD;
# define LOG(level, fmt, args...) \
((void) (LOGLEVEL_THRESHOLD >= (level) ? \
printk(KERN_DEBUG "VMBlock: " fmt, ## args) : \
0) \
)
#else
# define LOG(level, fmt, args...)
#endif
#define Warning(fmt, args...) \
printk(KERN_WARNING "VMBlock warning: " fmt, ## args)
/*
* Some kernel versions, bld-2.4.21-32.EL_x86_64-ia32e-RHEL3 and perhaps more,
* don't define __user in uaccess.h, so let's do it here so we don't have to
* ifdef all the __user annotations.
*/
#ifndef __user
#define __user
#endif
#endif /* __KERNEL__ */
#define VMBLOCK_CONTROL_MODE S_IRUSR | S_IFREG
/*
* Our modules may be compatible with kernels built for different processors.
* This can cause problems, so we add a reference to the __alloc_pages symbol
* below since it is versioned per-processor and will cause modules to only
* load on kernels built for the same processor as our module.
*
* XXX This should go in driver-config.h, but vmmon's hostKernel.h is retarded.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 29)
static const void *forceProcessorCheck __attribute__((unused)) = __alloc_pages;
#endif
/*
* Initialization and cleanup routines for control and file system halves of
* vmblock driver
*/
int VMBlockInitControlOps(void);
int VMBlockCleanupControlOps(void);
int VMBlockInitFileSystem(char const *root);
int VMBlockCleanupFileSystem(void);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 70)
size_t strlcpy(char *dest, const char *src, size_t count);
#endif
#endif /* __VMBLOCK_H__ */
vmblock-only/linux/vmblock_version.h 0000444 0000000 0000000 00000002230 12025726674 016710 0 ustar root root /*********************************************************
* Copyright (C) 2007 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* vmblock_version.h --
*
* Version definitions for the Linux vmblock driver.
*/
#ifndef _VMBLOCK_VERSION_H_
#define _VMBLOCK_VERSION_H_
#define VMBLOCK_DRIVER_VERSION 1.1.2.0
#define VMBLOCK_DRIVER_VERSION_COMMAS 1,1,2,0
#define VMBLOCK_DRIVER_VERSION_STRING "1.1.2.0"
#endif /* _VMBLOCK_VERSION_H_ */
vmblock-only/linux/os.h 0000444 0000000 0000000 00000010304 12025726674 014130 0 ustar root root /*********************************************************
* Copyright (C) 2007 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* os.h --
*
* OS-specific definitions.
*/
#ifndef __OS_H__
#define __OS_H__
#include "driver-config.h"
#include "compat_list.h"
#include "compat_completion.h"
#include
#include "compat_slab.h"
#include "compat_wait.h"
#include
#include
#include "compat_sched.h"
#include
#include "compat_kernel.h"
#include "compat_spinlock.h"
typedef rwlock_t os_rwlock_t;
typedef compat_kmem_cache os_kmem_cache_t;
typedef compat_completion os_completion_t;
typedef atomic_t os_atomic_t;
typedef struct file * os_blocker_id_t;
#define OS_UNKNOWN_BLOCKER NULL
#define OS_ENOMEM -ENOMEM
#define OS_ENOENT -ENOENT
#define OS_EEXIST -EEXIST
#define OS_PATH_MAX PATH_MAX
#define OS_FMTTID "d"
#define os_threadid current->pid
/*
* XXX vprintk() wasn't exported until 2.6.9; we should do something more
* intelligent here eventually.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
# define os_panic(fmt, args) \
({ \
vprintk(fmt, args); \
BUG(); \
})
#else
# define os_panic(fmt, args) \
({ \
BUG(); \
})
#endif
#define os_rwlock_init(lock) rwlock_init(lock)
#define os_rwlock_destroy(lock)
/*
* XXX We'd like to check for kernel version 2.5.34 as the patches indicate,
* but SLES10's 2.6.16.21-0.8-i586default doesn't seem to have this defined.
*/
#if defined(rwlock_is_locked)
# define os_rwlock_held(lock) rwlock_is_locked(lock)
#else
/* XXX Is there something we can come up with for this? */
# define os_rwlock_held(lock) TRUE
#endif
#define os_read_lock(lock) read_lock(lock)
#define os_write_lock(lock) write_lock(lock)
#define os_read_unlock(lock) read_unlock(lock)
#define os_write_unlock(lock) write_unlock(lock)
#define os_kmem_cache_create(name, size, align, ctor) \
compat_kmem_cache_create(name, size, align, SLAB_HWCACHE_ALIGN, ctor)
#define os_kmem_cache_destroy(cache) kmem_cache_destroy(cache)
#define os_kmem_cache_alloc(cache) kmem_cache_alloc(cache, GFP_KERNEL)
#define os_kmem_cache_free(cache, elem) kmem_cache_free(cache, elem)
#define os_completion_init(comp) compat_init_completion(comp)
#define os_completion_destroy(comp)
/*
* XXX This should be made interruptible using
* wait_for_completion_interruptible(), and return a proper value. Callers
* would need to handle interruption, of course.
*/
#define os_wait_for_completion(comp) \
({ \
compat_wait_for_completion(comp); \
0; \
})
#define os_complete_all(comp) compat_complete_all(comp)
#define os_atomic_dec_and_test(atomic) atomic_dec_and_test(atomic)
#define os_atomic_dec(atomic) atomic_dec(atomic)
#define os_atomic_set(atomic, val) atomic_set(atomic, val)
#define os_atomic_inc(atomic) atomic_inc(atomic)
#define os_atomic_read(atomic) atomic_read(atomic)
#endif /* __OS_H__ */
vmblock-only/linux/block.c 0000444 0000000 0000000 00000040064 12025726674 014602 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* block.c --
*
* Blocking operation implementions for the vmblock driver.
*/
/* os.h includes necessary OS-specific headers. */
#include "os.h"
#ifdef linux
# include "vmblockInt.h"
#elif defined(sun)
# include "module.h"
#elif defined(__FreeBSD__)
# include "vmblock_k.h"
#endif
#include "block.h"
#include "stubs.h"
#include "dbllnklst.h"
typedef struct BlockInfo {
DblLnkLst_Links links;
os_atomic_t refcount;
os_blocker_id_t blocker;
os_completion_t completion;
char filename[OS_PATH_MAX];
} BlockInfo;
/* XXX: Is it worth turning this into a hash table? */
static DblLnkLst_Links blockedFiles;
static os_rwlock_t blockedFilesLock;
static os_kmem_cache_t *blockInfoCache = NULL;
/* Utility functions */
static Bool BlockExists(const char *filename);
static BlockInfo *GetBlock(const char *filename, const os_blocker_id_t blocker);
static BlockInfo *AllocBlock(os_kmem_cache_t *cache,
const char *filename, const os_blocker_id_t blocker);
static void FreeBlock(os_kmem_cache_t *cache, BlockInfo *block);
/*
*----------------------------------------------------------------------------
*
* BlockInit --
*
* Initializes blocking portion of module.
*
* Results:
* Zero on success, error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
BlockInit(void)
{
ASSERT(!blockInfoCache);
blockInfoCache = os_kmem_cache_create("blockInfoCache",
sizeof (BlockInfo),
0,
NULL);
if (!blockInfoCache) {
return OS_ENOMEM;
}
DblLnkLst_Init(&blockedFiles);
os_rwlock_init(&blockedFilesLock);
return 0;
}
/*
*----------------------------------------------------------------------------
*
* BlockCleanup --
*
* Cleans up the blocking portion of the module.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
void
BlockCleanup(void)
{
ASSERT(blockInfoCache);
ASSERT(!DblLnkLst_IsLinked(&blockedFiles));
os_rwlock_destroy(&blockedFilesLock);
os_kmem_cache_destroy(blockInfoCache);
}
/*
*----------------------------------------------------------------------------
*
* BlockAddFileBlock --
*
* Adds a block for the provided filename. filename should be the name of
* the actual file being blocked, not the name within our namespace. The
* provided blocker ID should uniquely identify this blocker.
*
* All calls to BlockWaitOnFile() with the same filename will not return
* until BlockRemoveFileBlock() is called.
*
* Note that this function assumes a block on filename does not already
* exist.
*
* Results:
* Zero on success, error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
BlockAddFileBlock(const char *filename, // IN: name of file to block
const os_blocker_id_t blocker) // IN: blocker adding the block
{
BlockInfo *block;
ASSERT(filename);
/* Create a new block. */
block = AllocBlock(blockInfoCache, filename, blocker);
if (!block) {
Warning("BlockAddFileBlock: out of memory\n");
return OS_ENOMEM;
}
os_write_lock(&blockedFilesLock);
/*
* Prevent duplicate blocks of any filename. Done under same lock as list
* addition to ensure check for and adding of file are atomic.
*/
if (BlockExists(filename)) {
Warning("BlockAddFileBlock: block already exists for [%s]\n", filename);
os_write_unlock(&blockedFilesLock);
FreeBlock(blockInfoCache, block);
return OS_EEXIST;
}
DblLnkLst_LinkLast(&blockedFiles, &block->links);
os_write_unlock(&blockedFilesLock);
LOG(4, "added block for [%s]\n", filename);
return 0;
}
/*
*----------------------------------------------------------------------------
*
* BlockRemoveFileBlock --
*
* Removes the provided file block and wakes up any threads waiting within
* BlockWaitOnFile(). Note that only the blocker that added a block can
* remove it.
*
* Results:
* Zero on success, error code on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
BlockRemoveFileBlock(const char *filename, // IN: block to remove
const os_blocker_id_t blocker) // IN: blocker removing this block
{
BlockInfo *block;
ASSERT(filename);
os_write_lock(&blockedFilesLock);
block = GetBlock(filename, blocker);
if (!block) {
os_write_unlock(&blockedFilesLock);
return OS_ENOENT;
}
DblLnkLst_Unlink1(&block->links);
os_write_unlock(&blockedFilesLock);
/* Undo GetBlock's refcount increment first. */
os_atomic_dec(&block->refcount);
/*
* Now remove /our/ reference. (As opposed to references by waiting
* threads.)
*/
if (os_atomic_dec_and_test(&block->refcount)) {
/* No threads are waiting, so clean up ourself. */
LOG(4, "Freeing block with no waiters on [%s]\n", filename);
FreeBlock(blockInfoCache, block);
} else {
/* Wake up waiters; the last one will free the BlockInfo */
LOG(4, "Completing block on [%s]\n", filename);
os_complete_all(&block->completion);
}
return 0;
}
/*
*----------------------------------------------------------------------------
*
* BlockRemoveAllBlocks --
*
* Removes all blocks added by the provided blocker.
*
* Results:
* Returns the number of entries removed from the blocklist.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
unsigned int
BlockRemoveAllBlocks(const os_blocker_id_t blocker) // IN: blocker to remove blocks for
{
struct DblLnkLst_Links *curr;
struct DblLnkLst_Links *tmp;
unsigned int removed = 0;
os_write_lock(&blockedFilesLock);
DblLnkLst_ForEachSafe(curr, tmp, &blockedFiles) {
BlockInfo *currBlock = DblLnkLst_Container(curr, BlockInfo, links);
if (currBlock->blocker == blocker || blocker == OS_UNKNOWN_BLOCKER) {
DblLnkLst_Unlink1(&currBlock->links);
/*
* We count only entries removed from the -list-, regardless of whether
* or not other waiters exist.
*/
++removed;
/*
* BlockInfos, as the result of placing a block on a file or directory,
* reference themselves. When the block is lifted, we need to remove
* this self-reference and handle the result appropriately.
*/
if (os_atomic_dec_and_test(&currBlock->refcount)) {
/* Free blocks without any waiters ... */
LOG(4, "Freeing block with no waiters for blocker [%p] (%s)\n",
blocker, currBlock->filename);
FreeBlock(blockInfoCache, currBlock);
} else {
/* ... or wakeup the waiting threads */
LOG(4, "Completing block for blocker [%p] (%s)\n",
blocker, currBlock->filename);
os_complete_all(&currBlock->completion);
}
}
}
os_write_unlock(&blockedFilesLock);
return removed;
}
/*
*----------------------------------------------------------------------------
*
* BlockWaitOnFile --
*
* Searches for a block on the provided filename. If one exists, this
* function does not return until that block has been lifted; otherwise, it
* returns right away.
*
* Results:
* Zero on success, otherwise an appropriate system error if our sleep/
* block is interrupted.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
int
BlockWaitOnFile(const char *filename, // IN: file to block on
BlockHandle cookie) // IN: previously found block
{
BlockInfo *block = NULL;
int error = 0;
ASSERT(filename);
/*
* Caller may have used BlockLookup to conditionally search for a
* block before actually going to sleep. (This allows the caller to
* do a little housekeeping, such as releasing vnode locks, before
* blocking here.)
*/
if (cookie == NULL) {
os_read_lock(&blockedFilesLock);
block = GetBlock(filename, NULL);
os_read_unlock(&blockedFilesLock);
if (!block) {
/* This file is not blocked, just return */
return 0;
}
} else {
/*
* Note that the "cookie's" reference count was incremented when it
* was fetched via BlockLookup, so this is completely safe. (We'll
* decrement it below.)
*/
block = cookie;
}
LOG(4, "(%"OS_FMTTID") Waiting for completion on [%s]\n", os_threadid, filename);
error = os_wait_for_completion(&block->completion);
LOG(4, "(%"OS_FMTTID") Wokeup from block on [%s]\n", os_threadid, filename);
/*
* The assumptions here are as follows:
* 1. The BlockInfo holds a reference to itself. (BlockInfo's refcount
* is initialized to 1.)
* 2. BlockInfo's self reference is deleted only when BlockInfo is
* /also/ removed removed from the block list.
*
* Therefore, if the reference count hits zero, it's because the block is
* no longer in the list, and there is no chance of another thread finding
* and referencing this block between our dec_and_test and freeing it.
*/
if (os_atomic_dec_and_test(&block->refcount)) {
/* We were the last thread, so clean up */
LOG(4, "(%"OS_FMTTID") I am the last to wakeup, freeing the block on [%s]\n",
os_threadid, filename);
FreeBlock(blockInfoCache, block);
}
return error;
}
/*
*-----------------------------------------------------------------------------
*
* BlockLookup --
*
* VFS-exported function for searching for blocks.
*
* Results:
* Opaque pointer to a blockInfo if a block is found, NULL otherwise.
*
* Side effects:
* Located blockInfo, if any, has an incremented reference count.
*
*-----------------------------------------------------------------------------
*/
BlockHandle
BlockLookup(const char *filename, // IN: pathname to test for
// blocking
const os_blocker_id_t blocker) // IN: specific blocker to
// search for
{
BlockInfo *block;
os_read_lock(&blockedFilesLock);
block = GetBlock(filename, blocker);
os_read_unlock(&blockedFilesLock);
return block;
}
#ifdef VMX86_DEVEL
/*
*----------------------------------------------------------------------------
*
* BlockListFileBlocks --
*
* Lists all the current file blocks.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
void
BlockListFileBlocks(void)
{
DblLnkLst_Links *curr;
int count = 0;
os_read_lock(&blockedFilesLock);
DblLnkLst_ForEach(curr, &blockedFiles) {
BlockInfo *currBlock = DblLnkLst_Container(curr, BlockInfo, links);
LOG(1, "BlockListFileBlocks: (%d) Filename: [%s], Blocker: [%p]\n",
count++, currBlock->filename, currBlock->blocker);
}
os_read_unlock(&blockedFilesLock);
if (!count) {
LOG(1, "BlockListFileBlocks: No blocks currently exist.\n");
}
}
#endif
/* Utility functions */
/*
*----------------------------------------------------------------------------
*
* BlockExists --
*
* Checks if a block already exists for the provided filename.
*
* Note that this assumes the proper locking has been done on the data
* structure holding the blocked files (including ensuring the atomic_dec()
* without a kmem_cache_free() is safe).
*
* Results:
* TRUE if a block exists, FALSE otherwise.
*
* Side effects:
* If a block exists, its refcount is incremented and decremented.
*
*----------------------------------------------------------------------------
*/
static Bool
BlockExists(const char *filename)
{
BlockInfo *block = GetBlock(filename, OS_UNKNOWN_BLOCKER);
if (block) {
os_atomic_dec(&block->refcount);
return TRUE;
}
return FALSE;
}
/*
*----------------------------------------------------------------------------
*
* GetBlock --
*
* Searches for a block on the provided filename by the provided blocker.
* If blocker is NULL, it is ignored and any matching filename is returned.
* If a block is found, the refcount is incremented.
*
* Note that this assumes the proper locking has been done on the data
* structure holding the blocked files.
*
* Results:
* A pointer to the corresponding BlockInfo if found, NULL otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static BlockInfo *
GetBlock(const char *filename, // IN: file to find block for
const os_blocker_id_t blocker) // IN: blocker associated with this block
{
struct DblLnkLst_Links *curr;
/* XXX The following is only temporary. */
#ifdef __FreeBSD__
os_assert_rwlock_held(&blockedFilesLock);
#else
ASSERT(os_rwlock_held(&blockedFilesLock));
#endif
DblLnkLst_ForEach(curr, &blockedFiles) {
BlockInfo *currBlock = DblLnkLst_Container(curr, BlockInfo, links);
if ((blocker == OS_UNKNOWN_BLOCKER || currBlock->blocker == blocker) &&
strcmp(currBlock->filename, filename) == 0) {
os_atomic_inc(&currBlock->refcount);
return currBlock;
}
}
return NULL;
}
/*
*----------------------------------------------------------------------------
*
* AllocBlock --
*
* Allocates and initializes a new block structure.
*
* Results:
* Pointer to the struct on success, NULL on failure.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
BlockInfo *
AllocBlock(os_kmem_cache_t *cache, // IN: cache to allocate from
const char *filename, // IN: filname of block
const os_blocker_id_t blocker) // IN: blocker id
{
BlockInfo *block;
size_t ret;
/* Initialize this file's block structure. */
block = os_kmem_cache_alloc(blockInfoCache);
if (!block) {
return NULL;
}
ret = strlcpy(block->filename, filename, sizeof block->filename);
if (ret >= sizeof block->filename) {
Warning("BlockAddFileBlock: filename is too large\n");
os_kmem_cache_free(blockInfoCache, block);
return NULL;
}
DblLnkLst_Init(&block->links);
os_atomic_set(&block->refcount, 1);
os_completion_init(&block->completion);
block->blocker = blocker;
return block;
}
/*
*----------------------------------------------------------------------------
*
* FreeBlock --
*
* Frees the provided block structure.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
static void
FreeBlock(os_kmem_cache_t *cache, // IN: cache block was allocated from
BlockInfo *block) // IN: block to free
{
ASSERT(cache);
ASSERT(block);
os_completion_destroy(&block->completion);
os_kmem_cache_free(cache, block);
}
vmblock-only/linux/block.h 0000444 0000000 0000000 00000003010 12025726674 014575 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* block.h --
*
* Blocking operations for the vmblock driver.
*/
#ifndef __BLOCK_H__
#define __BLOCK_H__
#include "os.h"
typedef struct BlockInfo * BlockHandle;
/*
* Global functions
*/
int BlockInit(void);
void BlockCleanup(void);
int BlockAddFileBlock(const char *filename, const os_blocker_id_t blocker);
int BlockRemoveFileBlock(const char *filename, const os_blocker_id_t blocker);
unsigned int BlockRemoveAllBlocks(const os_blocker_id_t blocker);
int BlockWaitOnFile(const char *filename, BlockHandle cookie);
BlockHandle BlockLookup(const char *filename, const os_blocker_id_t blocker);
#ifdef VMX86_DEVEL
void BlockListFileBlocks(void);
#endif
#endif /* __BLOCK_H__ */
vmblock-only/linux/stubs.c 0000444 0000000 0000000 00000002436 12025726674 014651 0 ustar root root /*********************************************************
* Copyright (C) 2007 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* stubs.c --
*
* Common stubs.
*/
#include "os.h"
/*
*----------------------------------------------------------------------------
*
* Panic --
*
* Panic implementation.
*
* Results:
* None.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
void
Panic(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
os_panic(fmt, args);
va_end(args);
}
vmblock-only/linux/stubs.h 0000444 0000000 0000000 00000002041 12025726674 014646 0 ustar root root /*********************************************************
* Copyright (C) 2007 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* stubs.h --
*
*/
#ifndef __STUBS_H__
#define __STUBS_H__
#ifdef linux
# include "driver-config.h"
# include "compat_version.h"
#endif
void Panic(const char *fmt, ...);
#endif /* __STUBS_H__ */
vmblock-only/linux/dbllnklst.c 0000444 0000000 0000000 00000020031 12025726674 015471 0 ustar root root /*********************************************************
* Copyright (C) 1998 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include "vmware.h"
#include "dbllnklst.h"
/*
* dbllnklst.c --
*
* Light (but nonetheless powerful) implementation of doubly linked lists
*/
/*
*----------------------------------------------------------------------
*
* DblLnkLst_Init --
*
* Initialize a member of a doubly linked list
*
* Result
* None
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
void
DblLnkLst_Init(DblLnkLst_Links *l) // IN
{
ASSERT(l);
l->prev = l->next = l;
}
/*
*----------------------------------------------------------------------
*
* DblLnkLst_Link --
*
* Merge two doubly linked lists into one
*
* The operation is commutative
* The operation is inversible (its inverse is DblLnkLst_Unlink)
*
* Result
* None
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
void
DblLnkLst_Link(DblLnkLst_Links *l1, // IN
DblLnkLst_Links *l2) // IN
{
DblLnkLst_Links *tmp;
ASSERT(l1);
ASSERT(l2);
(tmp = l1->prev)->next = l2;
(l1->prev = l2->prev)->next = l1;
l2->prev = tmp ;
}
/*
*----------------------------------------------------------------------
*
* DblLnkLst_Unlink --
*
* Split one doubly linked list into two
*
* No check is performed: the caller must ensure that both members
* belong to the same doubly linked list
*
* The operation is commutative
* The operation is inversible (its inverse is DblLnkLst_Link)
*
* Result
* None
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
void
DblLnkLst_Unlink(DblLnkLst_Links *l1, // IN
DblLnkLst_Links *l2) // IN
{
DblLnkLst_Links *tmp;
ASSERT(l1);
ASSERT(l2);
tmp = l1->prev ;
(l1->prev = l2->prev)->next = l1;
(l2->prev = tmp )->next = l2;
}
/*
*----------------------------------------------------------------------
*
* DblLnkLst_Unlink1 --
*
* Unlink an element from its list.
*
* Result
* None
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
void
DblLnkLst_Unlink1(DblLnkLst_Links *l) // IN
{
ASSERT(l);
DblLnkLst_Unlink(l, l->next);
}
/*
*----------------------------------------------------------------------------
*
* DblLnkLst_IsLinked --
*
* Determines whether an element is linked with any other elements.
*
* Results:
* TRUE if link is linked, FALSE otherwise.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------------
*/
Bool
DblLnkLst_IsLinked(DblLnkLst_Links *l) // IN
{
ASSERT(l);
ASSERT((l->prev == l && l->next == l) ||
(l->prev != l && l->next != l));
/*
* A DblLnkLst_Links is either linked to itself (not linked) or linked to
* other elements in a list (linked).
*/
return l->prev != l;
}
/*
*----------------------------------------------------------------------
*
* DblLnkLst_LinkFirst --
*
* Insert 'l' at the beginning of the list anchored at 'head'
*
* Result
* None
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
void
DblLnkLst_LinkFirst(DblLnkLst_Links *head, // IN
DblLnkLst_Links *l) // IN
{
ASSERT(head);
ASSERT(l);
DblLnkLst_Link(head->next, l);
}
/*
*----------------------------------------------------------------------
*
* DblLnkLst_LinkLast --
*
* Insert 'l' at the end of the list anchored at 'head'
*
* Result
* None
*
* Side effects:
* None
*
*----------------------------------------------------------------------
*/
void
DblLnkLst_LinkLast(DblLnkLst_Links *head, // IN
DblLnkLst_Links *l) // IN
{
ASSERT(head);
ASSERT(l);
DblLnkLst_Link(head, l);
}
#if 0
/*
* Test code (which also demonstrates how to use this library)
*/
/*
* Add the double linked list capability to any of your data structure just by
* adding a DblLnkLst_Links field inside it. It is not required that the field
* comes first, but if it does, the execution will be slighly faster.
*
* Here we create a doubly linked list of integers
*/
#include
#include
typedef struct member {
int i;
DblLnkLst_Links l;
} member;
/* Member constructor */
member *
make_member(int i)
{
member *m;
m = malloc(sizeof(*m));
DblLnkLst_Init(&m->l);
m->i = i;
return m;
}
/* Dump a circular list */
void
dump_circular(const member *c) // IN
{
const member *current;
printf("forward: ");
current = c;
do {
printf("%d ", current->i);
current = DblLnkLst_Container(current->l.next, member, l);
} while (current != c);
printf("backward: ");
do {
printf("%d ", current->i);
current = DblLnkLst_Container(current->l.prev, member, l);
} while (current != c);
printf("\n");
}
/* Dump an anchored list */
void
dump_anchored(const DblLnkLst_Links *h) // IN
{
DblLnkLst_Links *cur_l;
printf("forward: ");
for (cur_l = h->next; cur_l != h; cur_l = cur_l->next) {
member *current;
current = DblLnkLst_Container(cur_l, member, l);
printf("%d ", current->i);
}
printf("backward: ");
for (cur_l = h->prev; cur_l != h; cur_l = cur_l->prev) {
member *current;
current = DblLnkLst_Container(cur_l, member, l);
printf("%d ", current->i);
}
printf("\n");
}
/* Test code entry point */
int
main(int argc, // IN
char **argv) // IN
{
member *c1;
member *c2;
member *c3;
member *c4;
DblLnkLst_Links h;
member *a1;
member *a2;
member *a3;
printf("Circular list: there is no origin\n");
/* Create the 1st member */
c1 = make_member(1);
/* Special case: there is no list to merge with, initially */
/* Add the 2nd member _after_ the 1st one */
c2 = make_member(2);
DblLnkLst_Link(&c1->l, &c2->l);
/* Add the 3rd member _after_ the 2nd one */
c3 = make_member(3);
DblLnkLst_Link(&c1->l, &c3->l);
/* Add the 4th member _before_ the 3rd one */
c4 = make_member(4);
DblLnkLst_Link(&c3->l, &c4->l);
printf("See it from this member...\n");
dump_circular(c1);
printf("...Or from this one\n");
dump_circular(c4);
printf("\n");
printf("Anchored (linear) list: it has a beginning and an end\n");
/* Create the 'head' of the list */
DblLnkLst_Init(&h);
/* Add the 1st member at the _end_ */
a1 = make_member(5);
DblLnkLst_LinkLast(&h, &a1->l);
/* Add the 2nd member at the _beginning_ */
a2 = make_member(6);
DblLnkLst_LinkFirst(&h, &a2->l);
/* Add the 3rd member _before_ the 1st one */
a3 = make_member(7);
DblLnkLst_Link(&a1->l, &a3->l);
dump_anchored(&h);
printf("\n");
printf("Merge both lists: the result is an anchored list\n");
DblLnkLst_Link(&h, &c4->l);
dump_anchored(&h);
printf("\n");
printf("Remove a member\n");
DblLnkLst_Unlink1(&c3->l);
dump_anchored(&h);
printf("\n");
printf("Split the result in two lists: an anchored one and a circular "
"one\n");
DblLnkLst_Unlink(&h, &a1->l);
dump_anchored(&h);
dump_circular(a1);
return 0;
}
#endif
vmblock-only/linux/dbllnklst.h 0000444 0000000 0000000 00000004456 12025726674 015513 0 ustar root root /*********************************************************
* Copyright (C) 1998 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* dbllnklst.h --
*
* Double linked lists
*/
#ifndef _DBLLNKLST_H_
#define _DBLLNKLST_H_
#include "vm_basic_types.h"
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_USERLEVEL
#include "includeCheck.h"
#define DblLnkLst_OffsetOf(type, field) ((intptr_t)&((type *)0)->field)
#define DblLnkLst_Container(addr, type, field) \
((type *)((char *)addr - DblLnkLst_OffsetOf(type, field)))
#define DblLnkLst_ForEach(curr, head) \
for (curr = (head)->next; curr != (head); curr = (curr)->next)
/* Safe from list element removal within loop body. */
#define DblLnkLst_ForEachSafe(curr, nextElem, head) \
for (curr = (head)->next, nextElem = (curr)->next; \
curr != (head); \
curr = nextElem, nextElem = (curr)->next)
typedef struct DblLnkLst_Links {
struct DblLnkLst_Links *prev;
struct DblLnkLst_Links *next;
} DblLnkLst_Links;
/* Functions for both circular and anchored lists. --hpreg */
void DblLnkLst_Init(DblLnkLst_Links *l);
void DblLnkLst_Link(DblLnkLst_Links *l1, DblLnkLst_Links *l2);
void DblLnkLst_Unlink(DblLnkLst_Links *l1, DblLnkLst_Links *l2);
void DblLnkLst_Unlink1(DblLnkLst_Links *l);
Bool DblLnkLst_IsLinked(DblLnkLst_Links *l);
/* Functions specific to anchored lists. --hpreg */
void DblLnkLst_LinkFirst(DblLnkLst_Links *head, DblLnkLst_Links *l);
void DblLnkLst_LinkLast(DblLnkLst_Links *head, DblLnkLst_Links *l);
#endif /* _DBLLNKLST_H_ */
vmblock-only/include/ 0000755 0000000 0000000 00000000000 12025726673 013625 5 ustar root root vmblock-only/include/vmware.h 0000444 0000000 0000000 00000003541 12025726674 015301 0 ustar root root /*********************************************************
* Copyright (C) 2003 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* vmware.h --
*
* Standard include file for VMware source code.
*/
#ifndef _VMWARE_H_
#define _VMWARE_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMNIXMOD
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#include "includeCheck.h"
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
#include "vm_assert.h"
/*
* Global error codes. Currently used internally, but may be exported
* to customers one day, like VM_E_XXX in vmcontrol_constants.h
*/
typedef enum VMwareStatus {
VMWARE_STATUS_SUCCESS, /* success */
VMWARE_STATUS_ERROR, /* generic error */
VMWARE_STATUS_NOMEM, /* generic memory allocation error */
VMWARE_STATUS_INSUFFICIENT_RESOURCES, /* internal or system resource limit exceeded */
VMWARE_STATUS_INVALID_ARGS /* invalid arguments */
} VMwareStatus;
#define VMWARE_SUCCESS(s) ((s) == VMWARE_STATUS_SUCCESS)
#endif // ifndef _VMWARE_H_
vmblock-only/include/vm_assert.h 0000444 0000000 0000000 00000024220 12025726674 016000 0 ustar root root /*********************************************************
* Copyright (C) 1998-2004 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* vm_assert.h --
*
* The basic assertion facility for all VMware code.
*
* For proper use, see
* http://vmweb.vmware.com/~mts/WebSite/guide/programming/asserts.html
*/
#ifndef _VM_ASSERT_H_
#define _VM_ASSERT_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMEXT
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMNIXMOD
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMIROM
#include "includeCheck.h"
// XXX not necessary except some places include vm_assert.h improperly
#include "vm_basic_types.h"
#include "vm_basic_defs.h"
/*
* XXX old file code
*/
#ifdef FILECODEINT
#error "Don't define FILECODEINT. It is obsolete."
#endif
#ifdef FILECODE
#error "Don't define FILECODE. It is obsolete."
#endif
/*
* Panic and log functions
*/
EXTERN void Log(const char *fmt, ...) PRINTF_DECL(1, 2);
EXTERN void Warning(const char *fmt, ...) PRINTF_DECL(1, 2);
EXTERN NORETURN void Panic(const char *fmt, ...) PRINTF_DECL(1, 2);
EXTERN void LogThrottled(uint32 *count, const char *fmt, ...)
PRINTF_DECL(2, 3);
EXTERN void WarningThrottled(uint32 *count, const char *fmt, ...)
PRINTF_DECL(2, 3);
/* DB family: messages which are parsed by logfile database system */
#define WarningDB Warning
#define LogDB Log
#define WarningThrottledDB WarningThrottled
#define LogThrottledDB LogThrottled
/*
* Stress testing: redefine ASSERT_IFNOT() to taste
*/
#ifndef ASSERT_IFNOT
#ifdef __cplusplus
#define ASSERT_IFNOT(cond, panic) (UNLIKELY(!(cond)) ? (panic) : (void)0)
#else
#define ASSERT_IFNOT(cond, panic) (UNLIKELY(!(cond)) ? (panic) : 0)
#endif
#endif
/*
* Assert, panic, and log macros
*
* Some of these are redefined below undef !VMX86_DEBUG.
* ASSERT() is special cased because of interaction with Windows DDK.
*/
#if defined VMX86_DEBUG || defined ASSERT_ALWAYS_AVAILABLE
#undef ASSERT
#define ASSERT(cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertAssert))
#endif
#define ASSERT_BUG(bug, cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC_BUG(bug, AssertAssert))
#define ASSERT_BUG_DEBUGONLY(bug, cond) ASSERT_BUG(bug, cond)
#define PANIC() _ASSERT_PANIC(AssertPanic)
#define PANIC_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertPanic)
#define ASSERT_NOT_IMPLEMENTED(cond) \
ASSERT_IFNOT(cond, NOT_IMPLEMENTED())
#define ASSERT_NOT_IMPLEMENTED_BUG(bug, cond) \
ASSERT_IFNOT(cond, NOT_IMPLEMENTED_BUG(bug))
#define NOT_IMPLEMENTED() _ASSERT_PANIC(AssertNotImplemented)
#define NOT_IMPLEMENTED_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertNotImplemented)
#define NOT_REACHED() _ASSERT_PANIC(AssertNotReached)
#define NOT_REACHED_BUG(bug) _ASSERT_PANIC_BUG(bug, AssertNotReached)
#define ASSERT_MEM_ALLOC(cond) \
ASSERT_IFNOT(cond, _ASSERT_PANIC(AssertMemAlloc))
#ifdef VMX86_DEVEL
#define ASSERT_LENGTH(real, expected) \
ASSERT_IFNOT((real) == (expected), \
Panic(AssertLengthFmt, __FILE__, __LINE__, real, expected))
#else
#define ASSERT_LENGTH(real, expected) ASSERT((real) == (expected))
#endif
#ifdef VMX86_DEVEL
#define ASSERT_DEVEL(cond) ASSERT(cond)
#else
#define ASSERT_DEVEL(cond) ((void) 0)
#endif
#define ASSERT_NO_INTERRUPTS() ASSERT(!INTERRUPTS_ENABLED())
#define ASSERT_HAS_INTERRUPTS() ASSERT(INTERRUPTS_ENABLED())
#define ASSERT_LOG_UNEXPECTED(bug, cond) \
(UNLIKELY(!(cond)) ? LOG_UNEXPECTED(bug) : 0)
#ifdef VMX86_DEVEL
#define LOG_UNEXPECTED(bug) \
Warning(AssertUnexpectedFmt, __FILE__, __LINE__, bug)
#else
#define LOG_UNEXPECTED(bug) \
Log(AssertUnexpectedFmt, __FILE__, __LINE__, bug)
#endif
#define ASSERT_NOT_TESTED(cond) (UNLIKELY(!(cond)) ? NOT_TESTED() : 0)
#ifdef VMX86_DEVEL
#define NOT_TESTED() Warning(AssertNotTestedFmt, __FILE__, __LINE__)
#else
#define NOT_TESTED() Log(AssertNotTestedFmt, __FILE__, __LINE__)
#endif
#define NOT_TESTED_ONCE() \
do { \
static Bool alreadyPrinted = FALSE; \
if (UNLIKELY(!alreadyPrinted)) { \
alreadyPrinted = TRUE; \
NOT_TESTED(); \
} \
} while (0)
#define NOT_TESTED_1024() \
do { \
static uint16 count = 0; \
if (UNLIKELY(count == 0)) { NOT_TESTED(); } \
count = (count + 1) & 1023; \
} while (0)
#define LOG_ONCE(_s) \
do { \
static Bool logged = FALSE; \
if (!logged) { \
Log _s; \
logged = TRUE; \
} \
} while (0)
/*
* Redefine macros that are only in debug versions
*/
#if !defined VMX86_DEBUG && !defined ASSERT_ALWAYS_AVAILABLE // {
#undef ASSERT
#define ASSERT(cond) ((void) 0)
#undef ASSERT_BUG_DEBUGONLY
#define ASSERT_BUG_DEBUGONLY(bug, cond) ((void) 0)
#undef ASSERT_LENGTH
#define ASSERT_LENGTH(real, expected) ((void) 0)
/*
* Expand NOT_REACHED() as appropriate for each situation.
*
* Mainly, we want the compiler to infer the same control-flow
* information as it would from Panic(). Otherwise, different
* compilation options will lead to different control-flow-derived
* errors, causing some make targets to fail while others succeed.
*
* VC++ has the __assume() built-in function which we don't trust
* (see bug 43485); gcc has no such construct; we just panic in
* userlevel code. The monitor doesn't want to pay the size penalty
* (measured at 212 bytes for the release vmm for a minimal infinite
* loop; panic would cost even more) so it does without and lives
* with the inconsistency.
*/
#ifdef VMM
#undef NOT_REACHED
#define NOT_REACHED() ((void) 0)
#else
// keep debug definition
#endif
#undef ASSERT_LOG_UNEXPECTED
#define ASSERT_LOG_UNEXPECTED(bug, cond) ((void) 0)
#undef LOG_UNEXPECTED
#define LOG_UNEXPECTED(bug) ((void) 0)
#undef ASSERT_NOT_TESTED
#define ASSERT_NOT_TESTED(cond) ((void) 0)
#undef NOT_TESTED
#define NOT_TESTED() ((void) 0)
#undef NOT_TESTED_ONCE
#define NOT_TESTED_ONCE() ((void) 0)
#undef NOT_TESTED_1024
#define NOT_TESTED_1024() ((void) 0)
#endif // !VMX86_DEBUG }
/*
* Compile-time assertions.
*
* ASSERT_ON_COMPILE does not use the common
* switch (0) { case 0: case (e): ; } trick because some compilers (e.g. MSVC)
* generate code for it.
*
* The implementation uses both enum and typedef because the typedef alone is
* insufficient; gcc allows arrays to be declared with non-constant expressions
* (even in typedefs, where it makes no sense).
*/
#define ASSERT_ON_COMPILE(e) \
do { \
enum { AssertOnCompileMisused = ((e) ? 1 : -1) }; \
typedef char AssertOnCompileFailed[AssertOnCompileMisused]; \
} while (0)
/*
* To put an ASSERT_ON_COMPILE() outside a function, wrap it
* in MY_ASSERTS(). The first parameter must be unique in
* each .c file where it appears. For example,
*
* MY_ASSERTS(FS3_INT,
* ASSERT_ON_COMPILE(sizeof(FS3_DiskLock) == 128);
* ASSERT_ON_COMPILE(sizeof(FS3_DiskLockReserved) == DISK_BLOCK_SIZE);
* ASSERT_ON_COMPILE(sizeof(FS3_DiskBlock) == DISK_BLOCK_SIZE);
* ASSERT_ON_COMPILE(sizeof(Hardware_DMIUUID) == 16);
* )
*
* Caution: ASSERT() within MY_ASSERTS() is silently ignored.
* The same goes for anything else not evaluated at compile time.
*/
#define MY_ASSERTS(name, assertions) \
static INLINE void name(void) { \
assertions \
}
/*
* Internal macros, functions, and strings
*
* The monitor wants to save space at call sites, so it has specialized
* functions for each situation. User level wants to save on implementation
* so it uses generic functions.
*/
#if !defined VMM || defined MONITOR_APP // {
#define _ASSERT_PANIC(name) \
Panic(_##name##Fmt "\n", __FILE__, __LINE__)
#define _ASSERT_PANIC_BUG(bug, name) \
Panic(_##name##Fmt " bugNr=%d\n", __FILE__, __LINE__, bug)
#define AssertLengthFmt _AssertLengthFmt
#define AssertUnexpectedFmt _AssertUnexpectedFmt
#define AssertNotTestedFmt _AssertNotTestedFmt
#endif // }
// these don't have newline so a bug can be tacked on
#define _AssertPanicFmt "PANIC %s:%d"
#define _AssertAssertFmt "ASSERT %s:%d"
#define _AssertNotImplementedFmt "NOT_IMPLEMENTED %s:%d"
#define _AssertNotReachedFmt "NOT_REACHED %s:%d"
#define _AssertMemAllocFmt "MEM_ALLOC %s:%d"
// these are complete formats with newline
#define _AssertLengthFmt "LENGTH %s:%d r=%#x e=%#x\n"
#define _AssertUnexpectedFmt "UNEXPECTED %s:%d bugNr=%d\n"
#define _AssertNotTestedFmt "NOT_TESTED %s:%d\n"
#endif /* ifndef _VM_ASSERT_H_ */
vmblock-only/include/vm_basic_defs.h 0000444 0000000 0000000 00000031565 12025726674 016573 0 ustar root root /*********************************************************
* Copyright (C) 2003 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* vm_basic_defs.h --
*
* Standard macros for VMware source code.
*/
#ifndef _VM_BASIC_DEFS_H_
#define _VM_BASIC_DEFS_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMEXT
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMNIXMOD
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMIROM
#include "includeCheck.h"
#include "vm_basic_types.h" // For INLINE.
#if defined _WIN32 && defined USERLEVEL
#include /*
* We re-define offsetof macro from stddef, make
* sure that its already defined before we do it
*/
#include // for Sleep() and LOWORD() etc.
#endif
/*
* Simple macros
*/
#if defined __APPLE__ && !defined KERNEL
# include
#else
// XXX the __cplusplus one matches that of VC++, to prevent redefinition warning
// XXX the other one matches that of gcc3.3.3/glibc2.2.4 to prevent redefinition warnings
#ifndef offsetof
#ifdef __cplusplus
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#else
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#endif
#endif // __APPLE__
#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof (a) / sizeof *(a))
#endif
#ifndef MIN
#define MIN(_a, _b) (((_a) < (_b)) ? (_a) : (_b))
#endif
/* The Solaris 9 cross-compiler complains about these not being used */
#ifndef sun
static INLINE int
Min(int a, int b)
{
return a < b ? a : b;
}
#endif
#ifndef MAX
#define MAX(_a, _b) (((_a) > (_b)) ? (_a) : (_b))
#endif
#ifndef sun
static INLINE int
Max(int a, int b)
{
return a > b ? a : b;
}
#endif
#define ROUNDUP(x,y) (((x) + (y) - 1) / (y) * (y))
#define ROUNDDOWN(x,y) ((x) / (y) * (y))
#define ROUNDUPBITS(x, bits) (((uintptr_t) (x) + MASK(bits)) & ~MASK(bits))
#define ROUNDDOWNBITS(x, bits) ((uintptr_t) (x) & ~MASK(bits))
#define CEILING(x, y) (((x) + (y) - 1) / (y))
#if defined __APPLE__
#include
#undef MASK
#endif
#define MASK(n) ((1 << (n)) - 1) /* make an n-bit mask */
#define DWORD_ALIGN(x) ((((x)+3) >> 2) << 2)
#define QWORD_ALIGN(x) ((((x)+4) >> 3) << 3)
#define IMPLIES(a,b) (!(a) || (b))
/*
* Not everybody (e.g., the monitor) has NULL
*/
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
/*
* Token concatenation
*
* The C preprocessor doesn't prescan arguments when they are
* concatenated or stringified. So we need extra levels of
* indirection to convince the preprocessor to expand its
* arguments.
*/
#define CONC(x, y) x##y
#define XCONC(x, y) CONC(x, y)
#define XXCONC(x, y) XCONC(x, y)
#define MAKESTR(x) #x
#define XSTR(x) MAKESTR(x)
/*
* Page operations
*
* It has been suggested that these definitions belong elsewhere
* (like x86types.h). However, I deem them common enough
* (since even regular user-level programs may want to do
* page-based memory manipulation) to be here.
* -- edward
*/
#ifndef PAGE_SHIFT // {
#if defined VM_I386
#define PAGE_SHIFT 12
#elif defined __APPLE__
#define PAGE_SHIFT 12
#else
#error
#endif
#endif // }
#ifndef PAGE_SIZE
#define PAGE_SIZE (1<> PAGE_SHIFT)
#endif
#ifndef BYTES_2_PAGES
#define BYTES_2_PAGES(_nbytes) ((_nbytes) >> PAGE_SHIFT)
#endif
#ifndef PAGES_2_BYTES
#define PAGES_2_BYTES(_npages) (((uint64)(_npages)) << PAGE_SHIFT)
#endif
#ifndef MBYTES_2_PAGES
#define MBYTES_2_PAGES(_nbytes) ((_nbytes) << (20 - PAGE_SHIFT))
#endif
#ifndef PAGES_2_MBYTES
#define PAGES_2_MBYTES(_npages) ((_npages) >> (20 - PAGE_SHIFT))
#endif
#ifndef VM_PAE_LARGE_PAGE_SHIFT
#define VM_PAE_LARGE_PAGE_SHIFT 21
#endif
#ifndef VM_PAE_LARGE_PAGE_SIZE
#define VM_PAE_LARGE_PAGE_SIZE (1 << VM_PAE_LARGE_PAGE_SHIFT)
#endif
#ifndef VM_PAE_LARGE_PAGE_MASK
#define VM_PAE_LARGE_PAGE_MASK (VM_PAE_LARGE_PAGE_SIZE - 1)
#endif
#ifndef VM_PAE_LARGE_2_SMALL_PAGES
#define VM_PAE_LARGE_2_SMALL_PAGES (BYTES_2_PAGES(VM_PAE_LARGE_PAGE_SIZE))
#endif
/*
* Word operations
*/
#ifndef LOWORD
#define LOWORD(_dw) ((_dw) & 0xffff)
#endif
#ifndef HIWORD
#define HIWORD(_dw) (((_dw) >> 16) & 0xffff)
#endif
#ifndef LOBYTE
#define LOBYTE(_w) ((_w) & 0xff)
#endif
#ifndef HIBYTE
#define HIBYTE(_w) (((_w) >> 8) & 0xff)
#endif
#define HIDWORD(_qw) ((uint32)((_qw) >> 32))
#define LODWORD(_qw) ((uint32)(_qw))
#define QWORD(_hi, _lo) ((((uint64)(_hi)) << 32) | ((uint32)(_lo)))
/*
* Deposit a field _src at _pos bits from the right,
* with a length of _len, into the integer _target.
*/
#define DEPOSIT_BITS(_src,_pos,_len,_target) { \
unsigned mask = ((1 << _len) - 1); \
unsigned shiftedmask = ((1 << _len) - 1) << _pos; \
_target = (_target & ~shiftedmask) | ((_src & mask) << _pos); \
}
/*
* Get return address.
*/
#ifdef _MSC_VER
#ifdef __cplusplus
extern "C"
#endif
void *_ReturnAddress(void);
#pragma intrinsic(_ReturnAddress)
#define GetReturnAddress() _ReturnAddress()
#elif __GNUC__
#define GetReturnAddress() __builtin_return_address(0)
#endif
#ifdef __GNUC__
#ifndef sun
/*
* Get the frame pointer. We use this assembly hack instead of
* __builtin_frame_address() due to a bug introduced in gcc 4.1.1
*/
static INLINE_SINGLE_CALLER uintptr_t
GetFrameAddr(void)
{
uintptr_t bp;
#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0))
bp = (uintptr_t)__builtin_frame_address(0);
#elif (__GNUC__ == 4 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ <= 3)
# if defined(VMM64) || defined(VM_X86_64)
__asm__ __volatile__("movq %%rbp, %0\n" : "=g" (bp));
# else
__asm__ __volatile__("movl %%ebp, %0\n" : "=g" (bp));
# endif
#else
__asm__ __volatile__(
#ifdef __linux__
".print \"This newer version of GCC may or may not have the "
"__builtin_frame_address bug. Need to update this. "
"See bug 147638.\"\n"
".abort"
#else /* MacOS */
".abort \"This newer version of GCC may or may not have the "
"__builtin_frame_address bug. Need to update this. "
"See bug 147638.\"\n"
#endif
: "=g" (bp)
);
#endif
return bp;
}
/*
* Returns the frame pointer of the calling function.
* Equivalent to __builtin_frame_address(1).
*/
static INLINE_SINGLE_CALLER uintptr_t
GetCallerFrameAddr(void)
{
return *(uintptr_t*)GetFrameAddr();
}
#endif // sun
#endif // __GNUC__
/*
* Data prefetch was added in gcc 3.1.1
* http://www.gnu.org/software/gcc/gcc-3.1/changes.html
*/
#ifdef __GNUC__
# if ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 1) || \
(__GNUC__ == 3 && __GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ >= 1))
# define PREFETCH_R(var) __builtin_prefetch((var), 0 /* read */, \
3 /* high temporal locality */)
# define PREFETCH_W(var) __builtin_prefetch((var), 1 /* write */, \
3 /* high temporal locality */)
# else
# define PREFETCH_R(var) ((void)(var))
# define PREFETCH_W(var) ((void)(var))
# endif
#endif /* __GNUC__ */
#ifdef USERLEVEL // {
/*
* Note this might be a problem on NT b/c while sched_yield guarantees it
* moves you to the end of your priority list, Sleep(0) offers no such
* guarantee. Bummer. --Jeremy.
*/
#if defined(N_PLAT_NLM) || defined(__FreeBSD__)
/* We do not have YIELD() as we do not need it yet... */
#elif defined(_WIN32)
# define YIELD() Sleep(0)
#else
# include // For sched_yield. Don't ask. --Jeremy.
# define YIELD() sched_yield()
#endif
/*
* Standardize some Posix names on Windows.
*/
#ifdef _WIN32 // {
#define snprintf _snprintf
#define vsnprintf _vsnprintf
#define strtok_r strtok_s
static INLINE void
sleep(unsigned int sec)
{
Sleep(sec * 1000);
}
static INLINE void
usleep(unsigned long usec)
{
Sleep(CEILING(usec, 1000));
}
typedef int pid_t;
#define F_OK 0
#define X_OK 1
#define W_OK 2
#define R_OK 4
#endif // }
/*
* Macro for username comparison.
*/
#ifdef _WIN32 // {
#define USERCMP(x,y) Str_Strcasecmp(x,y)
#else
#define USERCMP(x,y) strcmp(x,y)
#endif // }
#endif // }
#ifndef va_copy
#ifdef _WIN32
/*
* Windows needs va_copy. This works for both 32 and 64-bit Windows
* based on inspection of how varags.h from the Visual C CRTL is
* implemented. (Future versions of the RTL may break this).
*/
#define va_copy(dest, src) ((dest) = (src))
#elif defined(__APPLE__) && defined(KERNEL)
/*
* MacOS kernel-mode needs va_copy. Based on inspection of stdarg.h
* from the MacOSX10.4u.sdk kernel framework, this should work.
* (Future versions of the SDK may break this).
*/
#define va_copy(dest, src) ((dest) = (src))
#elif defined(__GNUC__) && (__GNUC__ < 3)
/*
* Old versions of gcc recognize __va_copy, but not va_copy.
*/
#define va_copy(dest, src) __va_copy(dest, src)
#endif // _WIN32
#endif // va_copy
/*
* This one is outside USERLEVEL because it's used by
* files compiled into the Windows hgfs driver or the display
* driver.
*/
#ifdef _WIN32
#define PATH_MAX 256
#ifndef strcasecmp
#define strcasecmp(_s1,_s2) _stricmp((_s1),(_s2))
#endif
#ifndef strncasecmp
#define strncasecmp(_s1,_s2,_n) _strnicmp((_s1),(_s2),(_n))
#endif
#endif
/*
* Convenience macro for COMMUNITY_SOURCE
*/
#undef EXCLUDE_COMMUNITY_SOURCE
#ifdef COMMUNITY_SOURCE
#define EXCLUDE_COMMUNITY_SOURCE(x)
#else
#define EXCLUDE_COMMUNITY_SOURCE(x) x
#endif
#undef COMMUNITY_SOURCE_INTEL_SECRET
#if !defined(COMMUNITY_SOURCE) || defined(INTEL_SOURCE)
/*
* It's ok to include INTEL_SECRET source code for non-commsrc,
* or for drops directed at Intel.
*/
#define COMMUNITY_SOURCE_INTEL_SECRET
#endif
/*
* Convenience macros and definitions. Can often be used instead of #ifdef.
*/
#undef DEBUG_ONLY
#undef SL_DEBUG_ONLY
#undef VMX86_SL_DEBUG
#ifdef VMX86_DEBUG
#define vmx86_debug 1
#define DEBUG_ONLY(x) x
/*
* Be very, very, very careful with SL_DEBUG. Pls ask ganesh or min before
* using it.
*/
#define VMX86_SL_DEBUG
#define vmx86_sl_debug 1
#define SL_DEBUG_ONLY(x) x
#else
#define vmx86_debug 0
#define DEBUG_ONLY(x)
#define vmx86_sl_debug 0
#define SL_DEBUG_ONLY(x)
#endif
#ifdef VMX86_STATS
#define vmx86_stats 1
#define STATS_ONLY(x) x
#else
#define vmx86_stats 0
#define STATS_ONLY(x)
#endif
#ifdef VMX86_DEVEL
#define vmx86_devel 1
#define DEVEL_ONLY(x) x
#else
#define vmx86_devel 0
#define DEVEL_ONLY(x)
#endif
#ifdef VMX86_LOG
#define vmx86_log 1
#define LOG_ONLY(x) x
#else
#define vmx86_log 0
#define LOG_ONLY(x)
#endif
#ifdef VMX86_VMM_SERIAL_LOGGING
#define vmx86_vmm_serial_log 1
#define VMM_SERIAL_LOG_ONLY(x) x
#else
#define vmx86_vmm_serial_log 0
#define VMM_SERIAL_LOG_ONLY(x)
#endif
#ifdef VMX86_SERVER
#define vmx86_server 1
#define SERVER_ONLY(x) x
#define HOSTED_ONLY(x)
#else
#define vmx86_server 0
#define SERVER_ONLY(x)
#define HOSTED_ONLY(x) x
#endif
#ifdef VMX86_WGS
#define vmx86_wgs 1
#define WGS_ONLY(x) x
#else
#define vmx86_wgs 0
#define WGS_ONLY(x)
#endif
#ifdef VMKERNEL
#define vmkernel 1
#define VMKERNEL_ONLY(x) x
#else
#define vmkernel 0
#define VMKERNEL_ONLY(x)
#endif
#ifdef _WIN32
#define WIN32_ONLY(x) x
#define POSIX_ONLY(x)
#else
#define WIN32_ONLY(x)
#define POSIX_ONLY(x) x
#endif
#ifdef VMM
#define VMM_ONLY(x) x
#define USER_ONLY(x)
#else
#define VMM_ONLY(x)
#define USER_ONLY(x) x
#endif
/* VMVISOR ifdef only allowed in the vmkernel */
#ifdef VMKERNEL
#ifdef VMVISOR
#define vmvisor 1
#define VMVISOR_ONLY(x) x
#else
#define vmvisor 0
#define VMVISOR_ONLY(x)
#endif
#endif
#ifdef _WIN32
#define VMW_INVALID_HANDLE INVALID_HANDLE_VALUE
#else
#define VMW_INVALID_HANDLE -1
#endif
#endif // ifndef _VM_BASIC_DEFS_H_
vmblock-only/include/vm_basic_types.h 0000444 0000000 0000000 00000056242 12025726674 017015 0 ustar root root /*********************************************************
* Copyright (C) 1998-2008 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
*
* vm_basic_types.h --
*
* basic data types.
*/
#ifndef _VM_BASIC_TYPES_H_
#define _VM_BASIC_TYPES_H_
#define INCLUDE_ALLOW_USERLEVEL
#define INCLUDE_ALLOW_VMMEXT
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_VMNIXMOD
#define INCLUDE_ALLOW_VMKERNEL
#define INCLUDE_ALLOW_VMKDRIVERS
#define INCLUDE_ALLOW_VMK_MODULE
#define INCLUDE_ALLOW_DISTRIBUTE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMIROM
#include "includeCheck.h"
/* STRICT ANSI means the Xserver build and X defines Bool differently. */
#if !defined(__STRICT_ANSI__) || defined(__FreeBSD__)
typedef char Bool;
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#define IsBool(x) (((x) & ~1) == 0)
#define IsBool2(x, y) ((((x) | (y)) & ~1) == 0)
/*
* Macros __i386__ and __ia64 are intrinsically defined by GCC
*/
#ifdef __i386__
#define VM_I386
#endif
#ifdef _WIN64
#define __x86_64__
#endif
#ifdef __x86_64__
#define VM_X86_64
#define VM_I386
#define vm_x86_64 (1)
#else
#define vm_x86_64 (0)
#endif
#ifdef _WIN32
/* safe assumption for a while */
#define VM_I386
#endif
#ifdef _MSC_VER
typedef unsigned __int64 uint64;
typedef signed __int64 int64;
#pragma warning (3 :4505) // unreferenced local function
#pragma warning (disable :4018) // signed/unsigned mismatch
#pragma warning (disable :4761) // integral size mismatch in argument; conversion supplied
#pragma warning (disable :4305) // truncation from 'const int' to 'short'
#pragma warning (disable :4244) // conversion from 'unsigned short' to 'unsigned char'
#pragma warning (disable :4267) // truncation of 'size_t'
#if !defined VMX86_DEVEL // XXX until we clean up all the code -- edward
#pragma warning (disable :4133) // incompatible types - from 'struct VM *' to 'int *'
#pragma warning (disable :4047) // differs in levels of indirection
#endif
#pragma warning (disable :4146) // unary minus operator applied to unsigned type, result still unsigned
#pragma warning (disable :4142) // benign redefinition of type
#elif __GNUC__
/* The Xserver source compiles with -ansi -pendantic */
#ifndef __STRICT_ANSI__
#if defined(VM_X86_64)
typedef unsigned long uint64;
typedef long int64;
#else
typedef unsigned long long uint64;
typedef long long int64;
#endif
#elif __FreeBSD__
typedef unsigned long long uint64;
typedef long long int64;
#endif
#else
#error - Need compiler define for int64/uint64
#endif
typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
typedef int int32;
typedef short int16;
typedef char int8;
/*
* FreeBSD (for the tools build) unconditionally defines these in
* sys/inttypes.h so don't redefine them if this file has already
* been included. [greg]
*
* This applies to Solaris as well.
*/
/*
* Before trying to do the includes based on OS defines, see if we can use
* feature-based defines to get as much functionality as possible
*/
#ifdef HAVE_INTTYPES_H
#include
#endif
#ifdef HAVE_SYS_TYPES_H
#include
#endif
#ifdef HAVE_SYS_INTTYPES_H
#include
#endif
#ifdef HAVE_STDINT_H
#include
#endif
#ifdef HAVE_STDLIB_H
#include
#endif
#if !defined(USING_AUTOCONF)
# if defined(__FreeBSD__) || defined(sun)
# ifdef KLD_MODULE
# include
# else
# if (BSD_VERSION >= 50)
# include
# include
# else
# include
# endif
# endif
# elif defined __APPLE__
# if KERNEL
# include
# include /* mostly for size_t */
# include
# else
# include
# include
# include
# include
# endif
# else
# if !defined(__intptr_t_defined) && !defined(intptr_t)
# define __intptr_t_defined
# define intptr_t intptr_t
# ifdef VM_I386
# ifdef VM_X86_64
typedef int64 intptr_t;
# else
typedef int32 intptr_t;
# endif
# endif
# endif
# ifndef _STDINT_H
# ifdef VM_I386
# ifdef VM_X86_64
typedef uint64 uintptr_t;
# else
typedef uint32 uintptr_t;
# endif
# endif
# endif
# endif
#endif
/*
* Time
* XXX These should be cleaned up. -- edward
*/
typedef int64 VmTimeType; /* Time in microseconds */
typedef int64 VmTimeRealClock; /* Real clock kept in microseconds */
typedef int64 VmTimeVirtualClock; /* Virtual Clock kept in CPU cycles */
/*
* Printf format specifiers for size_t and 64-bit number.
* Use them like this:
* printf("%"FMT64"d\n", big);
*
* FMTH is for handles/fds.
*/
#ifdef _MSC_VER
#define FMT64 "I64"
#ifdef VM_X86_64
#define FMTSZ "I64"
#define FMTPD "I64"
#define FMTH "I64"
#else
#define FMTSZ "I"
#define FMTPD "I"
#define FMTH "I"
#endif
#elif __GNUC__
#define FMTH ""
#if defined(N_PLAT_NLM) || defined(sun) || \
(defined(__FreeBSD__) && (__FreeBSD__ + 0) && ((__FreeBSD__ + 0) < 5))
/*
* Why (__FreeBSD__ + 0)? See bug 141008.
* Yes, we really need to test both (__FreeBSD__ + 0) and
* ((__FreeBSD__ + 0) < 5). No, we can't remove "+ 0" from
* ((__FreeBSD__ + 0) < 5).
*/
#ifdef VM_X86_64
#define FMTSZ "l"
#define FMTPD "l"
#else
#define FMTSZ ""
#define FMTPD ""
#endif
#elif defined(__linux__) \
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) \
|| (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \
|| (defined(_POSIX2_VERSION) && _POSIX2_VERSION >= 200112L)
/* BSD/Darwin, Linux */
#define FMTSZ "z"
#define FMTPD "t"
#else
/* Systems with a pre-C99 libc */
#define FMTSZ "Z"
#ifdef VM_X86_64
#define FMTPD "l"
#else
#define FMTPD ""
#endif
#endif
#ifdef VM_X86_64
#define FMT64 "l"
#elif defined(sun) || defined(__APPLE__) || defined(__FreeBSD__)
#define FMT64 "ll"
#else
#define FMT64 "L"
#endif
#else
#error - Need compiler define for FMT64 and FMTSZ
#endif
/*
* Suffix for 64-bit constants. Use it like this:
* CONST64(0x7fffffffffffffff) for signed or
* CONST64U(0x7fffffffffffffff) for unsigned.
*
* 2004.08.30(thutt):
* The vmcore/asm64/gen* programs are compiled as 32-bit
* applications, but must handle 64 bit constants. If the
* 64-bit-constant defining macros are already defined, the
* definition will not be overwritten.
*/
#if !defined(CONST64) || !defined(CONST64U)
#ifdef _MSC_VER
#define CONST64(c) c##I64
#define CONST64U(c) c##uI64
#elif __GNUC__
#ifdef VM_X86_64
#define CONST64(c) c##L
#define CONST64U(c) c##uL
#else
#define CONST64(c) c##LL
#define CONST64U(c) c##uLL
#endif
#else
#error - Need compiler define for CONST64
#endif
#endif
/*
* Use CONST3264/CONST3264U if you want a constant to be
* treated as a 32-bit number on 32-bit compiles and
* a 64-bit number on 64-bit compiles. Useful in the case
* of shifts, like (CONST3264U(1) << x), where x could be
* more than 31 on a 64-bit compile.
*/
#ifdef VM_X86_64
#define CONST3264(a) CONST64(a)
#define CONST3264U(a) CONST64U(a)
#else
#define CONST3264(a) (a)
#define CONST3264U(a) (a)
#endif
#define MIN_INT32 ((int32)0x80000000)
#define MAX_INT32 ((int32)0x7fffffff)
#define MIN_UINT32 ((uint32)0)
#define MAX_UINT32 ((uint32)0xffffffff)
#define MIN_INT64 (CONST64(0x8000000000000000))
#define MAX_INT64 (CONST64(0x7fffffffffffffff))
#define MIN_UINT64 (CONST64U(0))
#define MAX_UINT64 (CONST64U(0xffffffffffffffff))
typedef uint8 *TCA; /* Pointer into TC (usually). */
/*
* Type big enough to hold an integer between 0..100
*/
typedef uint8 Percent;
#define AsPercent(v) ((Percent)(v))
#define CHOOSE_PERCENT AsPercent(101)
typedef uintptr_t VA;
typedef uintptr_t VPN;
typedef uint64 PA;
typedef uint32 PPN;
typedef uint64 PhysMemOff;
typedef uint64 PhysMemSize;
/* The Xserver source compiles with -ansi -pendantic */
#ifndef __STRICT_ANSI__
typedef uint64 BA;
#endif
typedef uint32 BPN;
typedef uint32 PageNum;
typedef unsigned MemHandle;
typedef int32 World_ID;
#define INVALID_WORLD_ID ((World_ID)0)
typedef World_ID User_CartelID;
#define INVALID_CARTEL_ID INVALID_WORLD_ID
typedef User_CartelID User_SessionID;
#define INVALID_SESSION_ID INVALID_CARTEL_ID
typedef User_CartelID User_CartelGroupID;
#define INVALID_CARTELGROUP_ID INVALID_CARTEL_ID
typedef uint32 Worldlet_ID;
#define INVALID_WORLDLET_ID ((Worldlet_ID)0)
/* world page number */
typedef uint32 WPN;
/* The Xserver source compiles with -ansi -pendantic */
#ifndef __STRICT_ANSI__
typedef uint64 MA;
typedef uint32 MPN;
#endif
/*
* This type should be used for variables that contain sector
* position/quantity.
*/
typedef uint64 SectorType;
/*
* Linear address
*/
typedef uintptr_t LA;
typedef uintptr_t LPN;
#define LA_2_LPN(_la) ((_la) >> PAGE_SHIFT)
#define LPN_2_LA(_lpn) ((_lpn) << PAGE_SHIFT)
#define LAST_LPN ((((LA) 1) << (8 * sizeof(LA) - PAGE_SHIFT)) - 1)
#define LAST_LPN32 ((((LA32)1) << (8 * sizeof(LA32) - PAGE_SHIFT)) - 1)
#define LAST_LPN64 ((((LA64)1) << (8 * sizeof(LA64) - PAGE_SHIFT)) - 1)
/* Valid bits in a LPN. */
#define LPN_MASK LAST_LPN
#define LPN_MASK32 LAST_LPN32
#define LPN_MASK64 LAST_LPN64
/*
* On 64 bit platform, address and page number types default
* to 64 bit. When we need to represent a 32 bit address, we use
* types defined below.
*
* On 32 bit platform, the following types are the same as the
* default types.
*/
typedef uint32 VA32;
typedef uint32 VPN32;
typedef uint32 LA32;
typedef uint32 LPN32;
typedef uint32 PA32;
typedef uint32 PPN32;
typedef uint32 MA32;
typedef uint32 MPN32;
/*
* On 64 bit platform, the following types are the same as the
* default types.
*/
typedef uint64 VA64;
typedef uint64 VPN64;
typedef uint64 LA64;
typedef uint64 LPN64;
typedef uint64 PA64;
typedef uint64 PPN64;
typedef uint64 MA64;
typedef uint64 MPN64;
/*
* VA typedefs for user world apps.
*/
typedef VA32 UserVA32;
typedef VA64 UserVA64;
typedef UserVA32 UserVAConst; /* Userspace ptr to data that we may only read. */
typedef UserVA64 UserVA64Const; /* Used by 64-bit syscalls until conversion is finished. */
#ifdef VMKERNEL
typedef UserVA32 UserVA;
#else
typedef void * UserVA;
#endif
/*
* Maximal possible PPN value (errors too) that PhysMem can handle.
* Must be at least as large as MAX_PPN which is the maximum PPN
* for any region other than buserror.
*/
#define PHYSMEM_MAX_PPN ((PPN)0xffffffff)
#define MAX_PPN ((PPN)0x1fffffff) /* Maximal observable PPN value. */
#define INVALID_PPN ((PPN)0xffffffff)
#define INVALID_BPN ((BPN) 0x1fffffff)
#define INVALID_MPN ((MPN)-1)
#define MEMREF_MPN ((MPN)-2)
#define RESERVED_MPN ((MPN) 0)
/* Support 43 bits of address space. */
#define MAX_MPN ((MPN)0x7fffffff)
#define INVALID_LPN ((LPN)-1)
#define INVALID_VPN ((VPN)-1)
#define INVALID_LPN64 ((LPN64)-1)
#define INVALID_PAGENUM ((PageNum)-1)
#define INVALID_WPN ((WPN) -1)
/*
* Format modifier for printing VA, LA, and VPN.
* Use them like this: Log("%#"FMTLA"x\n", laddr)
*/
#if defined(VMM64) || defined(FROBOS64) || vm_x86_64 || defined __APPLE__
# define FMTLA "l"
# define FMTVA "l"
# define FMTVPN "l"
#else
# define FMTLA ""
# define FMTVA ""
# define FMTVPN ""
#endif
#define EXTERN extern
#define CONST const
#ifndef INLINE
# ifdef _MSC_VER
# define INLINE __inline
# else
# define INLINE inline
# endif
#endif
/*
* Annotation for data that may be exported into a DLL and used by other
* apps that load that DLL and import the data.
*/
#if defined(_WIN32) && defined(VMX86_IMPORT_DLLDATA)
# define VMX86_EXTERN_DATA extern __declspec(dllimport)
#else // !_WIN32
# define VMX86_EXTERN_DATA extern
#endif
#if defined(_WIN32) && !defined(VMX86_NO_THREADS)
#define THREADSPECIFIC __declspec(thread)
#else
#define THREADSPECIFIC
#endif
/*
* Due to the wonderful "registry redirection" feature introduced in
* 64-bit Windows, if you access any key under HKLM\Software in 64-bit
* code, you need to open/create/delete that key with
* VMKEY_WOW64_32KEY if you want a consistent view with 32-bit code.
*/
#ifdef _WIN32
#ifdef _WIN64
#define VMW_KEY_WOW64_32KEY KEY_WOW64_32KEY
#else
#define VMW_KEY_WOW64_32KEY 0x0
#endif
#endif
/*
* Consider the following reasons functions are inlined:
*
* 1) inlined for performance reasons
* 2) inlined because it's a single-use function
*
* Functions which meet only condition 2 should be marked with this
* inline macro; It is not critical to be inlined (but there is a
* code-space & runtime savings by doing so), so when other callers
* are added the inline-ness should be removed.
*/
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
/*
* Starting at version 3.3, gcc does not always inline functions marked
* 'inline' (it depends on their size). To force gcc to do so, one must use the
* extra __always_inline__ attribute.
*/
# define INLINE_SINGLE_CALLER INLINE __attribute__((__always_inline__))
# if defined(VMM) \
&& (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1))
# warning Verify INLINE_SINGLE_CALLER '__always_inline__' attribute (did \
monitor size change?)
# endif
#else
# define INLINE_SINGLE_CALLER INLINE
#endif
/*
* Used when a hard guaranteed of no inlining is needed. Very few
* instances need this since the absence of INLINE is a good hint
* that gcc will not do inlining.
*/
#if defined(__GNUC__) && defined(VMM)
#define ABSOLUTELY_NOINLINE __attribute__((__noinline__))
#endif
/*
* Attributes placed on function declarations to tell the compiler
* that the function never returns.
*/
#ifdef _MSC_VER
#define NORETURN __declspec(noreturn)
#elif __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 9)
#define NORETURN __attribute__((__noreturn__))
#else
#define NORETURN
#endif
/*
* GCC 3.2 inline asm needs the + constraint for input/ouput memory operands.
* Older GCCs don't know about it --hpreg
*/
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 2)
# define VM_ASM_PLUS 1
#else
# define VM_ASM_PLUS 0
#endif
/*
* Branch prediction hints:
* LIKELY(exp) - Expression exp is likely TRUE.
* UNLIKELY(exp) - Expression exp is likely FALSE.
* Usage example:
* if (LIKELY(excCode == EXC_NONE)) {
* or
* if (UNLIKELY(REAL_MODE(vc))) {
*
* We know how to predict branches on gcc3 and later (hopefully),
* all others we don't so we do nothing.
*/
#if (__GNUC__ >= 3)
/*
* gcc3 uses __builtin_expect() to inform the compiler of an expected value.
* We use this to inform the static branch predictor. The '!!' in LIKELY
* will convert any !=0 to a 1.
*/
#define LIKELY(_exp) __builtin_expect(!!(_exp), 1)
#define UNLIKELY(_exp) __builtin_expect((_exp), 0)
#else
#define LIKELY(_exp) (_exp)
#define UNLIKELY(_exp) (_exp)
#endif
/*
* GCC's argument checking for printf-like functions
* This is conditional until we have replaced all `"%x", void *'
* with `"0x%08x", (uint32) void *'. Note that %p prints different things
* on different platforms. Argument checking is enabled for the
* vmkernel, which has already been cleansed.
*
* fmtPos is the position of the format string argument, beginning at 1
* varPos is the position of the variable argument, beginning at 1
*/
#if defined(__GNUC__)
# define PRINTF_DECL(fmtPos, varPos) __attribute__((__format__(__printf__, fmtPos, varPos)))
#else
# define PRINTF_DECL(fmtPos, varPos)
#endif
#if defined(__GNUC__)
# define SCANF_DECL(fmtPos, varPos) __attribute__((__format__(__scanf__, fmtPos, varPos)))
#else
# define SCANF_DECL(fmtPos, varPos)
#endif
/*
* UNUSED_PARAM should surround the parameter name and type declaration,
* e.g. "int MyFunction(int var1, UNUSED_PARAM(int var2))"
*
*/
#ifndef UNUSED_PARAM
# if defined(__GNUC__)
# define UNUSED_PARAM(_parm) _parm __attribute__((__unused__))
# else
# define UNUSED_PARAM(_parm) _parm
# endif
#endif
/*
* REGPARM defaults to REGPARM3, i.e., a requent that gcc
* puts the first three arguments in registers. (It is fine
* if the function has fewer than three args.) Gcc only.
* Syntactically, put REGPARM where you'd put INLINE or NORETURN.
*/
#if defined(__GNUC__)
# define REGPARM0 __attribute__((regparm(0)))
# define REGPARM1 __attribute__((regparm(1)))
# define REGPARM2 __attribute__((regparm(2)))
# define REGPARM3 __attribute__((regparm(3)))
# define REGPARM REGPARM3
#else
# define REGPARM0
# define REGPARM1
# define REGPARM2
# define REGPARM3
# define REGPARM
#endif
/*
* ALIGNED specifies minimum alignment in "n" bytes.
*/
#ifdef __GNUC__
#define ALIGNED(n) __attribute__((__aligned__(n)))
#else
#define ALIGNED(n)
#endif
/*
***********************************************************************
* STRUCT_OFFSET_CHECK -- */ /**
*
* \brief Check if the actual offsef of a member in a structure
* is what is expected
*
*
* \param[in] STRUCT Structure the member is a part of.
* \param[in] MEMBER Member to check the offset of.
* \param[in] OFFSET Expected offset of MEMBER in STRUCTURE.
* \param[in] DEBUG_EXTRA Additional bytes to be added to OFFSET to
* compensate for extra info in debug builds.
*
***********************************************************************
*/
#ifdef VMX86_DEBUG
#define STRUCT_OFFSET_CHECK(STRUCT, MEMBER, OFFSET, DEBUG_EXTRA) \
ASSERT_ON_COMPILE(vmk_offsetof(STRUCT, MEMBER) == (OFFSET + DEBUG_EXTRA))
#else
#define STRUCT_OFFSET_CHECK(STRUCT, MEMBER, OFFSET, DEBUG_EXTRA) \
ASSERT_ON_COMPILE(vmk_offsetof(STRUCT, MEMBER) == OFFSET)
#endif
/*
***********************************************************************
* STRUCT_SIZE_CHECK -- */ /**
*
* \brief Check if the actual size of a structure is what is expected
*
*
* \param[in] STRUCT Structure whose size is to be checked.
* \param[in] SIZE Expected size of STRUCT.
* \param[in] DEBUG_EXTRA Additional bytes to be added to SIZE to
* compensate for extra info in debug builds.
*
***********************************************************************
*/
#ifdef VMX86_DEBUG
#define STRUCT_SIZE_CHECK(STRUCT, SIZE, DEBUG_EXTRA) \
ASSERT_ON_COMPILE(sizeof(STRUCT) == (SIZE + DEBUG_EXTRA))
#else
#define STRUCT_SIZE_CHECK(STRUCT, SIZE, DEBUG_EXTRA) \
ASSERT_ON_COMPILE(sizeof(STRUCT) == SIZE)
#endif
/*
* __func__ is a stringified function name that is part of the C99 standard. The block
* below defines __func__ on older systems where the compiler does not support that
* macro.
*/
#if defined(__GNUC__) \
&& ((__GNUC__ == 2 && __GNUC_MINOR < 96) \
|| (__GNUC__ < 2))
# define __func__ __FUNCTION__
#endif
/*
* Once upon a time, this was used to silence compiler warnings that
* get generated when the compiler thinks that a function returns
* when it is marked noreturn. Don't do it. Use NOT_REACHED().
*/
#define INFINITE_LOOP() do { } while (1)
/*
* On FreeBSD (for the tools build), size_t is typedef'd if _BSD_SIZE_T_
* is defined. Use the same logic here so we don't define it twice. [greg]
*/
#ifdef __FreeBSD__
# ifdef _BSD_SIZE_T_
# undef _BSD_SIZE_T_
# ifdef VM_I386
# ifdef VM_X86_64
typedef uint64 size_t;
# else
typedef uint32 size_t;
# endif
# endif /* VM_I386 */
# endif
# ifdef _BSD_SSIZE_T_
# undef _BSD_SSIZE_T_
# define _SSIZE_T
# define __ssize_t_defined
# define _SSIZE_T_DECLARED
# ifdef VM_I386
# ifdef VM_X86_64
typedef int64 ssize_t;
# else
typedef int32 ssize_t;
# endif
# endif /* VM_I386 */
# endif
#else
# ifndef _SIZE_T
# define _SIZE_T
# ifdef VM_I386
# ifdef VM_X86_64
typedef uint64 size_t;
# else
typedef uint32 size_t;
# endif
# endif /* VM_I386 */
# endif
# if !defined(FROBOS) && !defined(_SSIZE_T) && !defined(ssize_t) && \
!defined(__ssize_t_defined) && !defined(_SSIZE_T_DECLARED)
# define _SSIZE_T
# define __ssize_t_defined
# define _SSIZE_T_DECLARED
# ifdef VM_I386
# ifdef VM_X86_64
typedef int64 ssize_t;
# else
typedef int32 ssize_t;
# endif
# endif /* VM_I386 */
# endif
#endif
/*
* Format modifier for printing pid_t. On sun the pid_t is a ulong, but on
* Linux it's an int.
* Use this like this: printf("The pid is %"FMTPID".\n", pid);
*/
#ifdef sun
# ifdef VM_X86_64
# define FMTPID "d"
# else
# define FMTPID "lu"
# endif
#else
# define FMTPID "d"
#endif
/*
* Format modifier for printing uid_t. On sun the uid_t is a ulong, but on
* Linux it's an int.
* Use this like this: printf("The uid is %"FMTUID".\n", uid);
*/
#ifdef sun
# ifdef VM_X86_64
# define FMTUID "u"
# else
# define FMTUID "lu"
# endif
#else
# define FMTUID "u"
#endif
/*
* Format modifier for printing mode_t. On sun the mode_t is a ulong, but on
* Linux it's an int.
* Use this like this: printf("The mode is %"FMTMODE".\n", mode);
*/
#ifdef sun
# ifdef VM_X86_64
# define FMTMODE "o"
# else
# define FMTMODE "lo"
# endif
#else
# define FMTMODE "o"
#endif
/*
* Format modifier for printing time_t. Most platforms define a time_t to be
* a long int, but on FreeBSD (as of 5.0, it seems), the time_t is a signed
* size quantity. Refer to the definition of FMTSZ to see why we need silly
* preprocessor arithmetic.
* Use this like this: printf("The mode is %"FMTTIME".\n", time);
*/
#if defined(__FreeBSD__) && (__FreeBSD__ + 0) && ((__FreeBSD__ + 0) >= 5)
# define FMTTIME FMTSZ"d"
#else
# define FMTTIME "ld"
#endif
/*
* Define MXSemaHandle here so both vmmon and vmx see this definition.
*/
#ifdef _WIN32
typedef uintptr_t MXSemaHandle;
#else
typedef int MXSemaHandle;
#endif
/*
* Define type for poll device handles.
*/
#ifdef _WIN32
typedef uintptr_t PollDevHandle;
#else
typedef int PollDevHandle;
#endif
/*
* Define the utf16_t type.
*/
#if defined(_WIN32) && defined(_NATIVE_WCHAR_T_DEFINED)
typedef wchar_t utf16_t;
#else
typedef uint16 utf16_t;
#endif
#endif /* _VM_BASIC_TYPES_H_ */
vmblock-only/include/driver-config.h 0000444 0000000 0000000 00000004250 12025726674 016534 0 ustar root root /*********************************************************
* Copyright (C) 1998 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* Sets the proper defines from the Linux header files
*
* This file must be included before the inclusion of any kernel header file,
* with the exception of linux/autoconf.h and linux/version.h --hpreg
*/
#ifndef __VMX_CONFIG_H__
#define __VMX_CONFIG_H__
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMNIXMOD
#include "includeCheck.h"
#include
#include "compat_version.h"
/*
* We rely on Kernel Module support. Check here.
*/
#ifndef CONFIG_MODULES
# error "No Module support in this kernel. Please configure with CONFIG_MODULES"
#endif
/*
* 2.2 kernels still use __SMP__ (derived from CONFIG_SMP
* in the main Makefile), so we do it here.
*/
#ifdef CONFIG_SMP
# define __SMP__ 1
#endif
#if defined(CONFIG_MODVERSIONS) && defined(KERNEL_2_1)
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,60)
/*
* MODVERSIONS might be already defined when using kernel's Makefiles.
*/
# ifndef MODVERSIONS
# define MODVERSIONS
# endif
# include
# endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
/*
* Force the uintptr_t definition to come from linux/types.h instead of vm_basic_types.h.
*/
# include
# define _STDINT_H 1
#endif
#ifndef __KERNEL__
# define __KERNEL__
#endif
#endif
vmblock-only/include/compat_completion.h 0000444 0000000 0000000 00000013710 12025726674 017513 0 ustar root root /*********************************************************
* Copyright (C) 2004 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_COMPLETION_H__
# define __COMPAT_COMPLETION_H__
/*
* The kernel's completion objects were made available for module use in 2.4.9.
*
* Between 2.4.0 and 2.4.9, we implement completions on our own using
* waitqueues and counters. This was done so that we could safely support
* functions like complete_all(), which cannot be implemented using semaphores.
*
* Prior to that, the waitqueue API is substantially different, and since none
* of our modules that are built against older kernels need complete_all(),
* we fallback on a simple semaphore-based implementation.
*/
/*
* Native completions.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 9)
#include
#define compat_completion struct completion
#define compat_init_completion(comp) init_completion(comp)
#define COMPAT_DECLARE_COMPLETION DECLARE_COMPLETION
#define compat_wait_for_completion(comp) wait_for_completion(comp)
#define compat_complete(comp) complete(comp)
/* complete_all() was exported in 2.6.6. */
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 6)
# include "compat_wait.h"
# include "compat_list.h"
# include "compat_spinlock.h"
# include "compat_sched.h"
# define compat_complete_all(x) \
({ \
struct list_head *currLinks; \
spin_lock(&(x)->wait.lock); \
(x)->done += UINT_MAX/2; \
\
list_for_each(currLinks, &(x)->wait.task_list) { \
wait_queue_t *currQueue = list_entry(currLinks, wait_queue_t, task_list); \
wake_up_process(currQueue->task); \
} \
spin_unlock(&(x)->wait.lock); \
})
# else
# define compat_complete_all complete_all
# endif
/*
* Completions via waitqueues.
*/
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
/*
* Kernel completions in 2.4.9 and beyond use a counter and a waitqueue, and
* our implementation is quite similar. Because __wake_up_common() is not
* exported, our implementations of compat_complete() and compat_complete_all()
* are somewhat racy: the counter is incremented outside of the waitqueue's
* lock.
*
* As a result, our completion cannot guarantee in-order wake ups. For example,
* suppose thread A is entering compat_complete(), thread B is sleeping inside
* compat_wait_for_completion(), and thread C is just now entering
* compat_wait_for_completion(). If Thread A is scheduled first and increments
* the counter, then gets swapped out, thread C may get scheduled and will
* quickly go through compat_wait_for_completion() (since done != 0) while
* thread B continues to sleep, even though thread B should have been the one
* to wake up.
*/
#include
#include "compat_sched.h"
#include "compat_list.h"
#include // for lock_kernel()/unlock_kernel()
#include "compat_wait.h"
typedef struct compat_completion {
unsigned int done;
wait_queue_head_t wq;
} compat_completion;
#define compat_init_completion(comp) do { \
(comp)->done = 0; \
init_waitqueue_head(&(comp)->wq); \
} while (0)
#define COMPAT_DECLARE_COMPLETION(comp) \
compat_completion comp = { \
.done = 0, \
.wq = __WAIT_QUEUE_HEAD_INITIALIZER((comp).wq), \
}
/*
* Locking and unlocking the kernel lock here ensures that the thread
* is no longer running in module code: compat_complete_and_exit
* performs the sequence { lock_kernel(); up(comp); compat_exit(); }, with
* the final unlock_kernel performed implicitly by the resident kernel
* in do_exit.
*/
#define compat_wait_for_completion(comp) do { \
spin_lock_irq(&(comp)->wq.lock); \
if (!(comp)->done) { \
DECLARE_WAITQUEUE(wait, current); \
wait.flags |= WQ_FLAG_EXCLUSIVE; \
__add_wait_queue_tail(&(comp)->wq, &wait); \
do { \
__set_current_state(TASK_UNINTERRUPTIBLE); \
spin_unlock_irq(&(comp)->wq.lock); \
schedule(); \
spin_lock_irq(&(comp)->wq.lock); \
} while (!(comp)->done); \
__remove_wait_queue(&(comp)->wq, &wait); \
} \
(comp)->done--; \
spin_unlock_irq(&(comp)->wq.lock); \
lock_kernel(); \
unlock_kernel(); \
} while (0)
/* XXX: I don't think I need to touch the BKL. */
#define compat_complete(comp) do { \
unsigned long flags; \
spin_lock_irqsave(&(comp)->wq.lock, flags); \
(comp)->done++; \
spin_unlock_irqrestore(&(comp)->wq.lock, flags); \
wake_up(&(comp)->wq); \
} while (0)
#define compat_complete_all(comp) do { \
unsigned long flags; \
spin_lock_irqsave(&(comp)->wq.lock, flags); \
(comp)->done += UINT_MAX / 2; \
spin_unlock_irqrestore(&(comp)->wq.lock, flags); \
wake_up_all(&(comp)->wq); \
} while (0)
/*
* Completions via semaphores.
*/
#else
#include "compat_semaphore.h"
#define compat_completion struct semaphore
#define compat_init_completion(comp) init_MUTEX_LOCKED(comp)
#define COMPAT_DECLARE_COMPLETION(comp) DECLARE_MUTEX_LOCKED(comp)
#define compat_wait_for_completion(comp) do { \
down(comp); \
lock_kernel(); \
unlock_kernel(); \
} while (0)
#define compat_complete(comp) up(comp)
#endif
#endif /* __COMPAT_COMPLETION_H__ */
vmblock-only/include/compat_file.h 0000444 0000000 0000000 00000003523 12025726674 016262 0 ustar root root /*********************************************************
* Copyright (C) 2002 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_FILE_H__
# define __COMPAT_FILE_H__
/* The fput() API is modified in 2.2.0 --hpreg */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 0)
# define compat_fput(_file) fput(_file)
#else
# define compat_fput(_file) fput(_file, (_file)->f_inode)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
# define compat_get_file(_file) get_file(_file)
# define compat_file_count(_file) file_count(_file)
#else
# define compat_get_file(_file) (_file)->f_count++
# define compat_file_count(_file) (_file)->f_count
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 4)
# define compat_filp_close(_file, _files) filp_close(_file, _files)
#else
static inline void compat_filp_close(struct file* filp, fl_owner_t files) {
if (filp->f_op && filp->f_op->flush) {
filp->f_op->flush(filp);
}
/*
* Hopefully there are no locks to release on this filp.
* locks_remove_posix is not exported so we cannot use it...
*/
fput(filp);
}
#endif
#endif /* __COMPAT_FILE_H__ */
vmblock-only/include/compat_fs.h 0000444 0000000 0000000 00000023172 12025726674 015755 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_FS_H__
# define __COMPAT_FS_H__
#include
/*
* 2.6.5+ kernels define FS_BINARY_MOUNTDATA. Since it didn't exist and
* wasn't used prior, it's safe to define it to zero.
*/
#ifndef FS_BINARY_MOUNTDATA
#define FS_BINARY_MOUNTDATA 0
#endif
/*
* MAX_LFS_FILESIZE wasn't defined until 2.5.4.
*/
#ifndef MAX_LFS_FILESIZE
# include
# if BITS_PER_LONG == 32
# define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG - 1)) - 1)
# elif BITS_PER_LONG == 64
# define MAX_LFS_FILESIZE 0x7fffffffffffffffUL
# endif
#endif
/*
* sendfile as a VFS op was born in 2.5.30. Unfortunately, it also changed
* signatures, first in 2.5.47, then again in 2.5.70, then again in 2.6.8.
* Luckily, the 2.6.8+ signature is the same as the 2.5.47 signature. And
* as of 2.6.23-rc1 sendfile is gone, replaced by splice_read...
*
* Let's not support sendfile from 2.5.30 to 2.5.47, because the 2.5.30
* signature is much different and file_send_actor isn't externed.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
#define VMW_SENDFILE_NONE
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)
#define VMW_SENDFILE_NEW
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 70)
#define VMW_SENDFILE_OLD
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 47)
#define VMW_SENDFILE_NEW
#else
#define VMW_SENDFILE_NONE
#endif
/*
* splice_read is there since 2.6.17, but let's avoid 2.6.17-rcX kernels...
* After all nobody is using splice system call until 2.6.23 using it to
* implement sendfile.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)
#define VMW_SPLICE_READ 1
#endif
/*
* Filesystems wishing to use generic page cache read/write routines are
* supposed to implement aio_read and aio_write (calling into
* generic_file_aio_read() and generic_file_aio_write() if necessary).
*
* The VFS exports do_sync_read() and do_sync_write() as the "new"
* generic_file_read() and generic_file_write(), but filesystems need not
* actually implement read and write- the VFS will automatically call
* do_sync_write() and do_sync_read() when applications invoke the standard
* read() and write() system calls.
*
* In 2.6.19, generic_file_read() and generic_file_write() were removed,
* necessitating this change. AIO dates as far back as 2.5.42, but the API has
* changed over time, so for simplicity, we'll only enable it from 2.6.19 and
* on.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
# define VMW_USE_AIO
#endif
/*
* The alloc_inode and destroy_inode VFS ops didn't exist prior to 2.4.21.
* Without these functions, file systems can't embed inodes.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 21)
# define VMW_EMBED_INODE
#endif
/*
* iget() was removed from the VFS as of 2.6.25-rc1. The replacement for iget()
* is iget_locked() which was added in 2.5.17.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 17)
# define VMW_USE_IGET_LOCKED
#endif
/*
* parent_ino was born in 2.5.5. For older kernels, let's use 2.5.5
* implementation. It uses the dcache lock which is OK because per-dentry
* locking appeared after 2.5.5.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5)
#define compat_parent_ino(dentry) parent_ino(dentry)
#else
#define compat_parent_ino(dentry) \
({ \
ino_t res; \
spin_lock(&dcache_lock); \
res = dentry->d_parent->d_inode->i_ino; \
spin_unlock(&dcache_lock); \
res; \
})
#endif
/*
* putname changed to __putname in 2.6.6.
*/
#define compat___getname() __getname()
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 6)
#define compat___putname(name) putname(name)
#else
#define compat___putname(name) __putname(name)
#endif
/*
* inc_nlink, drop_nlink, and clear_nlink were added in 2.6.19.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
#define compat_inc_nlink(inode) ((inode)->i_nlink++)
#define compat_drop_nlink(inode) ((inode)->i_nlink--)
#define compat_clear_nlink(inode) ((inode)->i_nlink = 0)
#else
#define compat_inc_nlink(inode) inc_nlink(inode)
#define compat_drop_nlink(inode) drop_nlink(inode)
#define compat_clear_nlink(inode) clear_nlink(inode)
#endif
/*
* i_size_write and i_size_read were introduced in 2.6.0-test1
* (though we'll look for them as of 2.6.1). They employ slightly different
* locking in order to guarantee atomicity, depending on the length of a long,
* whether the kernel is SMP, or whether the kernel is preemptible. Prior to
* i_size_write and i_size_read, there was no such locking, so that's the
* behavior we'll emulate.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 1)
#define compat_i_size_read(inode) ((inode)->i_size)
#define compat_i_size_write(inode, size) ((inode)->i_size = size)
#else
#define compat_i_size_read(inode) i_size_read(inode)
#define compat_i_size_write(inode, size) i_size_write(inode, size)
#endif
/*
* filemap_fdatawrite was introduced in 2.5.12. Prior to that, modules used
* filemap_fdatasync instead. In 2.4.18, both filemap_fdatawrite and
* filemap_fdatawait began returning status codes. Prior to that, they were
* void functions, so we'll just have them return 0.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 18)
#define compat_filemap_fdatawrite(mapping) \
({ \
int result = 0; \
filemap_fdatasync(mapping); \
result; \
})
#define compat_filemap_fdatawait(mapping) \
({ \
int result = 0; \
filemap_fdatawait(mapping); \
result; \
})
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 12)
#define compat_filemap_fdatawrite(mapping) filemap_fdatasync(mapping)
#define compat_filemap_fdatawait(mapping) filemap_fdatawait(mapping)
#else
#define compat_filemap_fdatawrite(mapping) filemap_fdatawrite(mapping)
#define compat_filemap_fdatawait(mapping) filemap_fdatawait(mapping)
#endif
/*
* filemap_write_and_wait was introduced in 2.6.6 and exported for module use
* in 2.6.16. It's really just a simple wrapper around filemap_fdatawrite and
* and filemap_fdatawait, which initiates a flush of all dirty pages, then
* waits for the pages to flush. The implementation here is a simplified form
* of the one found in 2.6.20-rc3.
*
* Unfortunately, it just isn't possible to implement this prior to 2.4.5, when
* neither filemap_fdatawait nor filemap_fdatasync were exported for module
* use. So we'll define it out and hope for the best.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 5)
#define compat_filemap_write_and_wait(mapping)
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
#define compat_filemap_write_and_wait(mapping) \
({ \
int result = 0; \
if (mapping->nrpages) { \
result = compat_filemap_fdatawrite(mapping); \
if (result != -EIO) { \
int result2 = compat_filemap_fdatawait(mapping); \
if (!result) { \
result = result2; \
} \
} \
} \
result; \
})
#else
#define compat_filemap_write_and_wait(mapping) filemap_write_and_wait(mapping)
#endif
/*
* invalidate_remote_inode was introduced in 2.6.0-test5. Prior to that,
* filesystems wishing to invalidate pages belonging to an inode called
* invalidate_inode_pages.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
#define compat_invalidate_remote_inode(inode) invalidate_inode_pages(inode)
#else
#define compat_invalidate_remote_inode(inode) invalidate_remote_inode(inode)
#endif
#endif /* __COMPAT_FS_H__ */
vmblock-only/include/compat_init.h 0000444 0000000 0000000 00000002355 12025726674 016310 0 ustar root root /*********************************************************
* Copyright (C) 1999 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* compat_init.h: Initialization compatibility wrappers.
*/
#ifndef __COMPAT_INIT_H__
#define __COMPAT_INIT_H__
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 0)
#include
#endif
#ifndef module_init
#define module_init(x) int init_module(void) { return x(); }
#endif
#ifndef module_exit
#define module_exit(x) void cleanup_module(void) { x(); }
#endif
#endif /* __COMPAT_INIT_H__ */
vmblock-only/include/compat_list.h 0000444 0000000 0000000 00000003575 12025726674 016325 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_LIST_H__
# define __COMPAT_LIST_H__
#include
/*
* list_add_tail is with us since 2.4.0, or something like that.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
#define list_add_tail(newe, head) do { \
struct list_head *__h = (head); \
__list_add((newe), __h->prev, __h); \
} while (0)
#endif
/*
* list_for_each_safe() showed up in 2.4.10, but it may be backported so we
* just check for its existence.
*/
#ifndef list_for_each_safe
# define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
#endif
/*
* list_for_each_entry() showed up in 2.4.20, but it may be backported so we
* just check for its existence.
*/
#ifndef list_for_each_entry
# define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))
#endif
#endif /* __COMPAT_LIST_H__ */
vmblock-only/include/compat_kernel.h 0000444 0000000 0000000 00000005143 12025726674 016623 0 ustar root root /*********************************************************
* Copyright (C) 2004 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_KERNEL_H__
# define __COMPAT_KERNEL_H__
#include
#include
/*
* container_of was introduced in 2.5.28 but it's easier to check like this.
*/
#ifndef container_of
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
/*
* wait_for_completion and friends did not exist before 2.4.9.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 9)
#define compat_complete_and_exit(comp, status) complete_and_exit(comp, status)
#else
#include "compat_completion.h"
/*
* Used by _syscallX macros. Note that this is global variable, so
* do not rely on its contents too much. As exit() is only function
* we use, and we never check return value from exit(), we have
* no problem...
*/
extern int errno;
/*
* compat_exit() provides an access to the exit() function. It must
* be named compat_exit(), as exit() (with different signature) is
* provided by x86-64, arm and other (but not by i386).
*/
#define __NR_compat_exit __NR_exit
static inline _syscall1(int, compat_exit, int, exit_code);
/*
* See compat_wait_for_completion in compat_completion.h.
* compat_exit implicitly performs an unlock_kernel, in resident code,
* ensuring that the thread is no longer running in module code when the
* module is unloaded.
*/
#define compat_complete_and_exit(comp, status) do { \
lock_kernel(); \
compat_complete(comp); \
compat_exit(status); \
} while (0)
#endif
/*
* vsnprintf became available in 2.4.10. For older kernels, just fall back on
* vsprintf.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 10)
#define vsnprintf(str, size, fmt, args) vsprintf(str, fmt, args)
#endif
#endif /* __COMPAT_KERNEL_H__ */
vmblock-only/include/compat_mm.h 0000444 0000000 0000000 00000010207 12025726674 015751 0 ustar root root /*********************************************************
* Copyright (C) 2002 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_MM_H__
# define __COMPAT_MM_H__
#include
/* The get_page() API appeared in 2.3.7 --hpreg */
/* Sometime during development it became function instead of macro --petr */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) && !defined(get_page)
# define get_page(_page) atomic_inc(&(_page)->count)
/* The __free_page() API is exported in 2.1.67 --hpreg */
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 67)
# define put_page __free_page
# else
# include "compat_page.h"
# define page_to_phys(_page) (page_to_pfn(_page) << PAGE_SHIFT)
# define put_page(_page) free_page(page_to_phys(_page))
# endif
#endif
/* page_count() is 2.4.0 invention. Unfortunately unavailable in some RedHat
* kernels (for example 2.4.21-4-RHEL3). */
/* It is function since 2.6.0, and hopefully RedHat will not play silly games
* with mm_inline.h again... */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && !defined(page_count)
# define page_count(page) atomic_read(&(page)->count)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
# define compat_vm_pgoff(vma) ((vma)->vm_offset >> PAGE_SHIFT)
static inline unsigned long compat_do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long len, unsigned long prot,
unsigned long flag, unsigned long pgoff)
{
unsigned long ret = -EINVAL;
if (pgoff < 1 << (32 - PAGE_SHIFT)) {
ret = do_mmap(file, addr, len, prot, flag, pgoff << PAGE_SHIFT);
}
return ret;
}
#else
# define compat_vm_pgoff(vma) (vma)->vm_pgoff
# ifdef VMW_SKAS_MMAP
# define compat_do_mmap_pgoff(f, a, l, p, g, o) \
do_mmap_pgoff(current->mm, f, a, l, p, g, o)
# else
# define compat_do_mmap_pgoff(f, a, l, p, g, o) \
do_mmap_pgoff(f, a, l, p, g, o)
# endif
#endif
/* 2.2.x uses 0 instead of some define */
#ifndef NOPAGE_SIGBUS
#define NOPAGE_SIGBUS (0)
#endif
/* 2.2.x does not have HIGHMEM support */
#ifndef GFP_HIGHUSER
#define GFP_HIGHUSER (GFP_USER)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
#include "compat_page.h"
static inline struct page * alloc_pages(unsigned int gfp_mask, unsigned int order)
{
unsigned long addr;
addr = __get_free_pages(gfp_mask, order);
if (!addr) {
return NULL;
}
return virt_to_page(addr);
}
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0)
#endif
/*
* In 2.4.14, the logic behind the UnlockPage macro was moved to the
* unlock_page() function. Later (in 2.5.12), the UnlockPage macro was removed
* altogether, and nowadays everyone uses unlock_page().
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 14)
#define compat_unlock_page(page) UnlockPage(page)
#else
#define compat_unlock_page(page) unlock_page(page)
#endif
/*
* In 2.4.10, vmtruncate was changed from returning void to returning int.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 10)
#define compat_vmtruncate(inode, size) \
({ \
int result = 0; \
vmtruncate(inode, size); \
result; \
})
#else
#define compat_vmtruncate(inode, size) vmtruncate(inode, size)
#endif
#endif /* __COMPAT_MM_H__ */
vmblock-only/include/compat_module.h 0000444 0000000 0000000 00000004372 12025726674 016633 0 ustar root root /*********************************************************
* Copyright (C) 2007 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* compat_module.h --
*/
#ifndef __COMPAT_MODULE_H__
# define __COMPAT_MODULE_H__
#include
/*
* Modules wishing to use the GPL license are required to include a
* MODULE_LICENSE definition in their module source as of 2.4.10.
*/
#ifndef MODULE_LICENSE
#define MODULE_LICENSE(license)
#endif
/*
* To make use of our own home-brewed MODULE_INFO, we need macros to
* concatenate two expressions to "__mod_", and and to convert an
* expression into a string. I'm sure we've got these in our codebase,
* but I'd rather not introduce such a dependency in a compat header.
*/
#ifndef __module_cat
#define __module_cat_1(a, b) __mod_ ## a ## b
#define __module_cat(a, b) __module_cat_1(a, b)
#endif
#ifndef __stringify
#define __stringify_1(x) #x
#define __stringify(x) __stringify_1(x)
#endif
/*
* MODULE_INFO was born in 2.5.69.
*/
#ifndef MODULE_INFO
#define MODULE_INFO(tag, info) \
static const char __module_cat(tag, __LINE__)[] \
__attribute__((section(".modinfo"), unused)) = __stringify(tag) "=" info
#endif
/*
* MODULE_VERSION was born in 2.6.4. The earlier form appends a long "\0xxx"
* string to the module's version, but that was removed in 2.6.10, so we'll
* ignore it in our wrapper.
*/
#ifndef MODULE_VERSION
#define MODULE_VERSION(_version) MODULE_INFO(version, _version)
#endif
#endif /* __COMPAT_MODULE_H__ */
vmblock-only/include/compat_namei.h 0000444 0000000 0000000 00000004106 12025726674 016432 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_NAMEI_H__
# define __COMPAT_NAMEI_H__
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 18)
#include
#endif
/*
* In 2.6.25-rc2, dentry and mount objects were removed from the nameidata
* struct. They were both replaced with a struct path.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
#define compat_vmw_nd_to_dentry(nd) (nd).path.dentry
#else
#define compat_vmw_nd_to_dentry(nd) (nd).dentry
#endif
/* In 2.6.25-rc2, path_release(&nd) was replaced with path_put(&nd.path). */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
#define compat_path_release(nd) path_put(&(nd)->path)
#else
#define compat_path_release(nd) path_release(nd)
#endif
/* path_lookup was exported in 2.4.25 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25)
#define compat_path_lookup(path, flags, nd) path_lookup(path, flags, nd)
#else
#define compat_path_lookup(path, flags, nd) \
({ \
int ret = 0; \
if (path_init(path, flags, nd)) { \
ret = path_walk(path, nd); \
} \
ret; \
})
#endif
#endif /* __COMPAT_NAMEI_H__ */
vmblock-only/include/compat_page.h 0000444 0000000 0000000 00000004663 12025726674 016265 0 ustar root root /*********************************************************
* Copyright (C) 2002 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_PAGE_H__
# define __COMPAT_PAGE_H__
#include
#include
/* The pfn_to_page() API appeared in 2.5.14 and changed to function during 2.6.x */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) && !defined(pfn_to_page)
# define pfn_to_page(_pfn) (mem_map + (_pfn))
# define page_to_pfn(_page) ((_page) - mem_map)
#endif
/* The virt_to_page() API appeared in 2.4.0 --hpreg */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0) && !defined(virt_to_page)
# define virt_to_page(_kvAddr) pfn_to_page(MAP_NR(_kvAddr))
#endif
/*
* The get_order() API appeared at some point in 2.3.x, and was then backported
* in 2.2.17-21mdk and in the stock 2.2.18. Because we can only detect its
* definition through makefile tricks, we provide our own for now --hpreg
*/
static inline int
compat_get_order(unsigned long size) // IN
{
int order;
size = (size - 1) >> (PAGE_SHIFT - 1);
order = -1;
do {
size >>= 1;
order++;
} while (size);
return order;
}
/*
* BUG() was added to in 2.2.18, and was moved to
* in 2.5.58.
*
* XXX: Technically, this belongs in some sort of "compat_asm_page.h" file, but
* since our compatibility wrappers don't distinguish between and
* , putting it here is reasonable.
*/
#ifndef BUG
#define BUG() do { \
printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
__asm__ __volatile__(".byte 0x0f,0x0b"); \
} while (0)
#endif
#endif /* __COMPAT_PAGE_H__ */
vmblock-only/include/compat_sched.h 0000444 0000000 0000000 00000024252 12025726674 016433 0 ustar root root /*********************************************************
* Copyright (C) 2002 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_SCHED_H__
# define __COMPAT_SCHED_H__
#include
/* CLONE_KERNEL available in 2.5.35 and higher. */
#ifndef CLONE_KERNEL
#define CLONE_KERNEL CLONE_FILES | CLONE_FS | CLONE_SIGHAND
#endif
/* TASK_COMM_LEN become available in 2.6.11. */
#ifndef TASK_COMM_LEN
#define TASK_COMM_LEN 16
#endif
/* The capable() API appeared in 2.1.92 --hpreg */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 1, 92)
# define capable(_capability) suser()
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 0)
# define need_resched() need_resched
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 3)
# define need_resched() (current->need_resched)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 3)
# define cond_resched() (need_resched() ? schedule() : (void) 0)
#endif
/* Oh well. We need yield... Happy us! */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 20)
# ifdef __x86_64__
# define compat_yield() there_is_nothing_like_yield()
# else
# include
# include
/*
* Used by _syscallX macros. Note that this is global variable, so
* do not rely on its contents too much. As exit() is only function
* we use, and we never check return value from exit(), we have
* no problem...
*/
extern int errno;
/*
* compat_exit() provides an access to the exit() function. It must
* be named compat_exit(), as exit() (with different signature) is
* provided by x86-64, arm and other (but not by i386).
*/
# define __NR_compat_yield __NR_sched_yield
static inline _syscall0(int, compat_yield);
# endif
#else
# define compat_yield() yield()
#endif
/*
* Since 2.5.34 there are two methods to enumerate tasks:
* for_each_process(p) { ... } which enumerates only tasks and
* do_each_thread(g,t) { ... } while_each_thread(g,t) which enumerates
* also threads even if they share same pid.
*/
#ifndef for_each_process
# define for_each_process(p) for_each_task(p)
#endif
#ifndef do_each_thread
# define do_each_thread(g, t) for_each_task(g) { t = g; do
# define while_each_thread(g, t) while (0) }
#endif
/*
* Lock for signal mask is moving target...
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 40) && defined(CLONE_PID)
/* 2.4.x without NPTL patches or early 2.5.x */
#define compat_sigmask_lock sigmask_lock
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(¤t->blocked, (siginfo_ptr))
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 60) && !defined(INIT_SIGHAND)
/* RedHat's 2.4.x with first version of NPTL support, or 2.5.40 to 2.5.59 */
#define compat_sigmask_lock sig->siglock
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(¤t->blocked, (siginfo_ptr))
#else
/* RedHat's 2.4.x with second version of NPTL support, or 2.5.60+. */
#define compat_sigmask_lock sighand->siglock
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(¤t->blocked, (siginfo_ptr))
#else
#define compat_dequeue_signal_current(siginfo_ptr) \
dequeue_signal(current, ¤t->blocked, (siginfo_ptr))
#endif
#endif
/*
* recalc_sigpending() had task argument in the past
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 29) && defined(CLONE_PID)
/* 2.4.x without NPTL patches or early 2.5.x */
#define compat_recalc_sigpending() recalc_sigpending(current)
#else
/* RedHat's 2.4.x with NPTL support, or 2.5.29+ */
#define compat_recalc_sigpending() recalc_sigpending()
#endif
/*
* reparent_to_init() was introduced in 2.4.8. In 2.5.38 (or possibly
* earlier, but later than 2.5.31) a call to it was added into
* daemonize(), so compat_daemonize no longer needs to call it.
*
* In 2.4.x kernels reparent_to_init() forgets to do correct refcounting
* on current->user. It is better to count one too many than one too few...
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 38)
#define compat_reparent_to_init() do { \
reparent_to_init(); \
atomic_inc(¤t->user->__count); \
} while (0)
#else
#define compat_reparent_to_init() do {} while (0)
#endif
/*
* daemonize appeared in 2.2.18. Except 2.2.17-4-RH7.0, which has it too.
* Fortunately 2.2.17-4-RH7.0 uses versioned symbols, so we can check
* its existence with defined().
*/
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) && !defined(daemonize)
static inline void daemonize(void) {
struct fs_struct *fs;
exit_mm(current);
current->session = 1;
current->pgrp = 1;
exit_fs(current);
fs = init_task.fs;
current->fs = fs;
atomic_inc(&fs->count);
}
#endif
/*
* flush_signals acquires sighand->siglock since 2.5.61... Verify RH's kernels!
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 61)
#define compat_flush_signals(task) do { \
spin_lock_irq(&task->compat_sigmask_lock); \
flush_signals(task); \
spin_unlock_irq(&task->compat_sigmask_lock); \
} while (0)
#else
#define compat_flush_signals(task) flush_signals(task)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 61)
#define compat_allow_signal(signr) do { \
spin_lock_irq(¤t->compat_sigmask_lock); \
sigdelset(¤t->blocked, signr); \
compat_recalc_sigpending(); \
spin_unlock_irq(¤t->compat_sigmask_lock); \
} while (0)
#else
#define compat_allow_signal(signr) allow_signal(signr)
#endif
/*
* daemonize can set process name since 2.5.61. Prior to 2.5.61, daemonize
* didn't block signals on our behalf.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 61)
#define compat_daemonize(x...) \
({ \
/* Beware! No snprintf here, so verify arguments! */ \
sprintf(current->comm, x); \
\
/* Block all signals. */ \
spin_lock_irq(¤t->compat_sigmask_lock); \
sigfillset(¤t->blocked); \
compat_recalc_sigpending(); \
spin_unlock_irq(¤t->compat_sigmask_lock); \
compat_flush_signals(current); \
\
daemonize(); \
compat_reparent_to_init(); \
})
#else
#define compat_daemonize(x...) daemonize(x)
#endif
/*
* set priority for specified thread. Exists on 2.6.x kernels and some
* 2.4.x vendor's kernels.
*/
#if defined(VMW_HAVE_SET_USER_NICE)
#define compat_set_user_nice(task, n) set_user_nice((task), (n))
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)
#define compat_set_user_nice(task, n) do { (task)->priority = 20 - (n); } while (0)
#elif !defined(VMW_HAVE_SET_USER_NICE)
#define compat_set_user_nice(task, n) do { (task)->nice = (n); } while (0)
#endif
/*
* try to freeze a process. For kernels 2.6.11 or newer, we know how to choose
* the interface. The problem is that the oldest interface, introduced in
* 2.5.18, was backported to 2.4.x kernels. So if we're older than 2.6.11,
* we'll decide what to do based on whether or not swsusp was configured
* for the kernel. For kernels 2.6.20 and newer, we'll also need to include
* freezer.h since the try_to_freeze definition was pulled out of sched.h.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
#include
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13) || defined(VMW_TL10S64_WORKAROUND)
#define compat_try_to_freeze() try_to_freeze()
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
#define compat_try_to_freeze() try_to_freeze(PF_FREEZE)
#elif defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_SOFTWARE_SUSPEND2)
#include "compat_mm.h"
#include
#include
static inline int compat_try_to_freeze(void) {
if (current->flags & PF_FREEZE) {
refrigerator(PF_FREEZE);
return 1;
} else {
return 0;
}
}
#else
static inline int compat_try_to_freeze(void) { return 0; }
#endif
/*
* As of 2.6.23-rc1, kernel threads are no longer freezable by
* default. Instead, kernel threads that need to be frozen must opt-in
* by calling set_freezable() as soon as the thread is created.
*/
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 22)
#define compat_set_freezable() do { set_freezable(); } while (0)
#else
#define compat_set_freezable() do {} while (0)
#endif
/*
* Since 2.6.27-rc2 kill_proc() is gone... Replacement (GPL-only!)
* API is available since 2.6.19. Use them from 2.6.27-rc1 up.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
typedef int compat_pid;
#define compat_find_get_pid(pid) (pid)
#define compat_put_pid(pid) do { } while (0)
#define compat_kill_pid(pid, sig, flag) kill_proc(pid, sig, flag)
#else
typedef struct pid * compat_pid;
#define compat_find_get_pid(pid) find_get_pid(pid)
#define compat_put_pid(pid) put_pid(pid)
#define compat_kill_pid(pid, sig, flag) kill_pid(pid, sig, flag)
#endif
#endif /* __COMPAT_SCHED_H__ */
vmblock-only/include/compat_semaphore.h 0000444 0000000 0000000 00000003142 12025726674 017323 0 ustar root root /*********************************************************
* Copyright (C) 2002 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_SEMAPHORE_H__
# define __COMPAT_SEMAPHORE_H__
/* <= 2.6.25 have asm only, 2.6.26 has both, and 2.6.27-rc2+ has linux only. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
# include
#else
# include
#endif
/*
* The init_MUTEX_LOCKED() API appeared in 2.2.18, and is also in
* 2.2.17-21mdk --hpreg
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)
#ifndef init_MUTEX_LOCKED
#define init_MUTEX_LOCKED(_sem) *(_sem) = MUTEX_LOCKED
#endif
#ifndef DECLARE_MUTEX
#define DECLARE_MUTEX(name) struct semaphore name = MUTEX
#endif
#ifndef DECLARE_MUTEX_LOCKED
#define DECLARE_MUTEX_LOCKED(name) struct semaphore name = MUTEX_LOCKED
#endif
#endif
#endif /* __COMPAT_SEMAPHORE_H__ */
vmblock-only/include/compat_slab.h 0000444 0000000 0000000 00000006653 12025726674 016273 0 ustar root root /*********************************************************
* Copyright (C) 2005 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_SLAB_H__
# define __COMPAT_SLAB_H__
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 0)
# include
#else
# include
#endif
/*
* Before 2.6.20, kmem_cache_t was the accepted way to refer to a kmem_cache
* structure. Prior to 2.6.15, this structure was called kmem_cache_s, and
* afterwards it was renamed to kmem_cache. Here we keep things simple and use
* the accepted typedef until it became deprecated, at which point we switch
* over to the kmem_cache name.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
# define compat_kmem_cache struct kmem_cache
#else
# define compat_kmem_cache kmem_cache_t
#endif
/*
* Up to 2.6.22 kmem_cache_create has 6 arguments - name, size, alignment, flags,
* constructor, and destructor. Then for some time kernel was asserting that
* destructor is NULL, and since 2.6.23-pre1 kmem_cache_create takes only 5
* arguments - destructor is gone.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) || defined(VMW_KMEMCR_HAS_DTOR)
#define compat_kmem_cache_create(name, size, align, flags, ctor) \
kmem_cache_create(name, size, align, flags, ctor, NULL)
#else
#define compat_kmem_cache_create(name, size, align, flags, ctor) \
kmem_cache_create(name, size, align, flags, ctor)
#endif
/*
* Up to 2.6.23 kmem_cache constructor has three arguments - pointer to block to
* prepare (aka "this"), from which cache it came, and some unused flags. After
* 2.6.23 flags were removed, and order of "this" and cache parameters was swapped...
* Since 2.6.27-rc2 everything is different again, and ctor has only one argument.
*
* HAS_3_ARGS has precedence over HAS_2_ARGS if both are defined.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) && !defined(VMW_KMEMCR_CTOR_HAS_3_ARGS)
# define VMW_KMEMCR_CTOR_HAS_3_ARGS
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) && !defined(VMW_KMEMCR_CTOR_HAS_2_ARGS)
# define VMW_KMEMCR_CTOR_HAS_2_ARGS
#endif
#if defined(VMW_KMEMCR_CTOR_HAS_3_ARGS)
typedef void compat_kmem_cache_ctor(void *, compat_kmem_cache *, unsigned long);
#define COMPAT_KMEM_CACHE_CTOR_ARGS(arg) void *arg, \
compat_kmem_cache *cache, \
unsigned long flags
#elif defined(VMW_KMEMCR_CTOR_HAS_2_ARGS)
typedef void compat_kmem_cache_ctor(compat_kmem_cache *, void *);
#define COMPAT_KMEM_CACHE_CTOR_ARGS(arg) compat_kmem_cache *cache, \
void *arg
#else
typedef void compat_kmem_cache_ctor(void *);
#define COMPAT_KMEM_CACHE_CTOR_ARGS(arg) void *arg
#endif
#endif /* __COMPAT_SLAB_H__ */
vmblock-only/include/compat_spinlock.h 0000444 0000000 0000000 00000004606 12025726674 017170 0 ustar root root /*********************************************************
* Copyright (C) 2005 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_SPINLOCK_H__
# define __COMPAT_SPINLOCK_H__
/*
* The spin_lock() API appeared in 2.1.25 in asm/smp_lock.h
* It moved in 2.1.30 to asm/spinlock.h
* It moved again in 2.3.18 to linux/spinlock.h
*
* --hpreg
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 18)
# include
#else
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 30)
# include
# else
typedef struct {} spinlock_t;
# define spin_lock_init(lock)
# define spin_lock(lock)
# define spin_unlock(lock)
# define spin_lock_irqsave(lock, flags) do { \
save_flags(flags); \
cli(); \
spin_lock(lock); \
} while (0)
# define spin_unlock_irqrestore(lock, flags) do { \
spin_unlock(lock); \
restore_flags(flags); \
} while (0)
# endif
#endif
/*
* Preempt support was added during 2.5.x development cycle, and later
* it was backported to 2.4.x. In 2.4.x backport these definitions
* live in linux/spinlock.h, that's why we put them here (in 2.6.x they
* are defined in linux/preempt.h which is included by linux/spinlock.h).
*/
#ifdef CONFIG_PREEMPT
#define compat_preempt_disable() preempt_disable()
#define compat_preempt_enable() preempt_enable()
#else
#define compat_preempt_disable() do { } while (0)
#define compat_preempt_enable() do { } while (0)
#endif
#endif /* __COMPAT_SPINLOCK_H__ */
vmblock-only/include/compat_statfs.h 0000444 0000000 0000000 00000002306 12025726674 016645 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_STATFS_H__
# define __COMPAT_STATFS_H__
/* vfs.h simply include statfs.h, but it knows what directory statfs.h is in. */
#include
/* 2.5.74 renamed struct statfs to kstatfs. */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 74)
#define compat_kstatfs kstatfs
#else
#define compat_kstatfs statfs
#endif
#endif /* __COMPAT_STATFS_H__ */
vmblock-only/include/compat_string.h 0000444 0000000 0000000 00000003563 12025726674 016655 0 ustar root root /*********************************************************
* Copyright (C) 2007 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_STRING_H__
# define __COMPAT_STRING_H__
#include
/*
* kstrdup was born in 2.6.13. This implementation is almost identical to the
* one found there.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 13)
#define compat_kstrdup(s, gfp) kstrdup(s, gfp)
#else
#define compat_kstrdup(s, gfp) \
({ \
size_t len; \
char *buf; \
len = strlen(s) + 1; \
buf = kmalloc(len, gfp); \
memcpy(buf, s, len); \
buf; \
})
#endif
#endif /* __COMPAT_STRING_H__ */
vmblock-only/include/compat_uaccess.h 0000444 0000000 0000000 00000006062 12025726674 016772 0 ustar root root /*********************************************************
* Copyright (C) 2002 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_UACCESS_H__
# define __COMPAT_UACCESS_H__
/* User space access functions moved in 2.1.7 to asm/uaccess.h --hpreg */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 7)
# include
#else
# include
#endif
/* get_user() API modified in 2.1.4 to take 2 arguments --hpreg */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 4)
# define compat_get_user get_user
#else
/*
* We assign 0 to the variable in case of failure to prevent "`_var' might be
* used uninitialized in this function" compiler warnings. I think it is OK,
* because the hardware-based version in newer kernels probably has the same
* semantics and does not guarantee that the value of _var will not be
* modified, should the access fail --hpreg
*/
# define compat_get_user(_var, _uvAddr) ({ \
int _status; \
\
_status = verify_area(VERIFY_READ, _uvAddr, sizeof(*(_uvAddr))); \
if (_status == 0) { \
(_var) = get_user(_uvAddr); \
} else { \
(_var) = 0; \
} \
_status; \
})
#endif
/*
* The copy_from_user() API appeared in 2.1.4
*
* The emulation is not perfect here, but it is conservative: on failure, we
* always return the total size, instead of the potentially smaller faulty
* size --hpreg
*
* Since 2.5.55 copy_from_user() is no longer macro.
*/
#if !defined(copy_from_user) && LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 0)
# define copy_from_user(_to, _from, _size) ( \
verify_area(VERIFY_READ, _from, _size) \
? (_size) \
: (memcpy_fromfs(_to, _from, _size), 0) \
)
# define copy_to_user(_to, _from, _size) ( \
verify_area(VERIFY_WRITE, _to, _size) \
? (_size) \
: (memcpy_tofs(_to, _from, _size), 0) \
)
#endif
#endif /* __COMPAT_UACCESS_H__ */
vmblock-only/include/compat_version.h 0000444 0000000 0000000 00000006165 12025726674 017035 0 ustar root root /*********************************************************
* Copyright (C) 1998 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_VERSION_H__
# define __COMPAT_VERSION_H__
#define INCLUDE_ALLOW_VMMON
#define INCLUDE_ALLOW_MODULE
#define INCLUDE_ALLOW_VMCORE
#define INCLUDE_ALLOW_VMNIXMOD
#define INCLUDE_ALLOW_DISTRIBUTE
#include "includeCheck.h"
#ifndef __linux__
# error "linux-version.h"
#endif
#include
/* Appeared in 2.1.90 --hpreg */
#ifndef KERNEL_VERSION
# define KERNEL_VERSION(a, b, c) (((a) << 16) + ((b) << 8) + (c))
#endif
/*
* Distinguish relevant classes of Linux kernels.
*
* The convention is that version X defines all
* the KERNEL_Y symbols where Y <= X.
*
* XXX Do not add more definitions here. This way of doing things does not
* scale, and we are going to phase it out soon --hpreg
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 1, 0)
# define KERNEL_2_1
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 2, 0)
# define KERNEL_2_2
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 1)
# define KERNEL_2_3_1
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 15)
/* new networking */
# define KERNEL_2_3_15
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 25)
/* new procfs */
# define KERNEL_2_3_25
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 29)
/* even newer procfs */
# define KERNEL_2_3_29
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 43)
/* softnet changes */
# define KERNEL_2_3_43
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 47)
/* more softnet changes */
# define KERNEL_2_3_47
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 99)
/* name in netdevice struct is array and not pointer */
# define KERNEL_2_3_99
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0)
/* New 'owner' member at the beginning of struct file_operations */
# define KERNEL_2_4_0
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 8)
/* New netif_rx_ni() --hpreg */
# define KERNEL_2_4_8
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 22)
/* New vmap() */
# define KERNEL_2_4_22
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 2)
/* New kdev_t, major()/minor() API --hpreg */
# define KERNEL_2_5_2
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5)
/* New sk_alloc(), pte_offset_map()/pte_unmap() --hpreg */
# define KERNEL_2_5_5
#endif
#endif /* __COMPAT_VERSION_H__ */
vmblock-only/include/compat_wait.h 0000444 0000000 0000000 00000015642 12025726674 016314 0 ustar root root /*********************************************************
* Copyright (C) 2002 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#ifndef __COMPAT_WAIT_H__
# define __COMPAT_WAIT_H__
#include
#include
#include
#include "compat_file.h"
/*
* The DECLARE_WAITQUEUE() API appeared in 2.3.1
* It was back ported in 2.2.18
*
* --hpreg
*/
#ifndef DECLARE_WAITQUEUE
typedef struct wait_queue *wait_queue_head_t;
# define init_waitqueue_head(_headPtr) *(_headPtr) = NULL
# define DECLARE_WAITQUEUE(_var, _task) \
struct wait_queue _var = {_task, NULL, }
typedef struct wait_queue wait_queue_t;
# define init_waitqueue_entry(_wait, _task) ((_wait)->task = (_task))
#endif
/*
* The 'struct poll_wqueues' appeared in 2.5.48, when global
* /dev/epoll interface was added. It was backported to the
* 2.4.20-wolk4.0s.
*/
#ifdef VMW_HAVE_EPOLL // {
#define compat_poll_wqueues struct poll_wqueues
#else // } {
#define compat_poll_wqueues poll_table
#endif // }
#ifdef VMW_HAVE_EPOLL // {
/* If prototype does not match, build will abort here */
extern void poll_initwait(compat_poll_wqueues *);
#define compat_poll_initwait(wait, table) ( \
poll_initwait((table)), \
(wait) = &(table)->pt \
)
#define compat_poll_freewait(wait, table) ( \
poll_freewait((table)) \
)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) // {
/* If prototype does not match, build will abort here */
extern void poll_initwait(compat_poll_wqueues *);
#define compat_poll_initwait(wait, table) ( \
(wait) = (table), \
poll_initwait(wait) \
)
#define compat_poll_freewait(wait, table) ( \
poll_freewait((table)) \
)
#else // } {
#define compat_poll_initwait(wait, table) ( \
(wait) = (table), /* confuse compiler */ \
(wait) = (poll_table *) __get_free_page(GFP_KERNEL), \
(wait)->nr = 0, \
(wait)->entry = (struct poll_table_entry *)((wait) + 1), \
(wait)->next = NULL \
)
static inline void
poll_freewait(poll_table *wait)
{
while (wait) {
struct poll_table_entry * entry;
poll_table *old;
entry = wait->entry + wait->nr;
while (wait->nr > 0) {
wait->nr--;
entry--;
remove_wait_queue(entry->wait_address, &entry->wait);
compat_fput(entry->filp);
}
old = wait;
wait = wait->next;
free_page((unsigned long) old);
}
}
#define compat_poll_freewait(wait, table) ( \
poll_freewait((wait)) \
)
#endif // }
/*
* The wait_event_interruptible_timeout() interface is not
* defined in pre-2.6 kernels.
*/
#ifndef wait_event_interruptible_timeout
#define __wait_event_interruptible_timeout(wq, condition, ret) \
do { \
wait_queue_t __wait; \
init_waitqueue_entry(&__wait, current); \
\
add_wait_queue(&wq, &__wait); \
for (;;) { \
set_current_state(TASK_INTERRUPTIBLE); \
if (condition) \
break; \
if (!signal_pending(current)) { \
ret = schedule_timeout(ret); \
if (!ret) \
break; \
continue; \
} \
ret = -ERESTARTSYS; \
break; \
} \
set_current_state(TASK_RUNNING); \
remove_wait_queue(&wq, &__wait); \
} while (0)
#define wait_event_interruptible_timeout(wq, condition, timeout) \
({ \
long __ret = timeout; \
if (!(condition)) \
__wait_event_interruptible_timeout(wq, condition, __ret); \
__ret; \
})
#endif
/*
* The wait_event_timeout() interface is not
* defined in pre-2.6 kernels.
*/
#ifndef wait_event_timeout
#define __wait_event_timeout(wq, condition, ret) \
do { \
wait_queue_t __wait; \
init_waitqueue_entry(&__wait, current); \
\
add_wait_queue(&wq, &__wait); \
for (;;) { \
set_current_state(TASK_UNINTERRUPTIBLE); \
if (condition) \
break; \
ret = schedule_timeout(ret); \
if (!ret) \
break; \
} \
set_current_state(TASK_RUNNING); \
remove_wait_queue(&wq, &__wait); \
} while (0)
#define wait_event_timeout(wq, condition, timeout) \
({ \
long __ret = timeout; \
if (!(condition)) \
__wait_event_timeout(wq, condition, __ret); \
__ret; \
})
#endif
/*
* DEFINE_WAIT() and friends were added in 2.5.39 and backported to 2.4.28.
*
* Unfortunately it is not true. While some distros may have done it the
* change has never made it into vanilla 2.4 kernel. Instead of testing
* particular kernel versions let's just test for presence of DEFINE_WAIT
* when figuring out whether we need to provide replacement implementation
* or simply alias existing one.
*/
#ifndef DEFINE_WAIT
# define COMPAT_DEFINE_WAIT(_wait) \
DECLARE_WAITQUEUE(_wait, current)
# define compat_init_prepare_to_wait(_sleep, _wait, _state) \
do { \
__set_current_state(_state); \
add_wait_queue(_sleep, _wait); \
} while (0)
# define compat_cont_prepare_to_wait(_sleep, _wait, _state) \
set_current_state(_state)
# define compat_finish_wait(_sleep, _wait, _state) \
do { \
__set_current_state(_state); \
remove_wait_queue(_sleep, _wait); \
} while (0)
#else
# define COMPAT_DEFINE_WAIT(_wait) \
DEFINE_WAIT(_wait)
# define compat_init_prepare_to_wait(_sleep, _wait, _state) \
prepare_to_wait(_sleep, _wait, _state)
# define compat_cont_prepare_to_wait(_sleep, _wait, _state) \
prepare_to_wait(_sleep, _wait, _state)
# define compat_finish_wait(_sleep, _wait, _state) \
finish_wait(_sleep, _wait)
#endif /* #ifndef DEFINE_WAIT */
#endif /* __COMPAT_WAIT_H__ */
vmblock-only/include/vmblock.h 0000444 0000000 0000000 00000010354 12025726674 015435 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* vmblock.h --
*
* User-level interface to the vmblock device.
*/
#ifndef _VMBLOCK_H_
#define _VMBLOCK_H_
#if defined(sun) || defined(__FreeBSD__)
# include
#endif
#if defined(__FreeBSD__)
# include
#endif
#define VMBLOCK_FS_NAME "vmblock"
/* Commands for the control half of vmblock driver */
#if defined(linux)
# define VMBLOCK_ADD_FILEBLOCK 98
# define VMBLOCK_DEL_FILEBLOCK 99
# ifdef VMX86_DEVEL
# define VMBLOCK_LIST_FILEBLOCKS 100
# endif
# define VMBLOCK_CONTROL_DIRNAME VMBLOCK_FS_NAME
# define VMBLOCK_CONTROL_DEVNAME "dev"
# define VMBLOCK_CONTROL_MOUNTPOINT "mountPoint"
# define VMBLOCK_CONTROL_PROC_DIRNAME "fs/" VMBLOCK_CONTROL_DIRNAME
# define VMBLOCK_MOUNT_POINT "/proc/" VMBLOCK_CONTROL_PROC_DIRNAME \
"/" VMBLOCK_CONTROL_MOUNTPOINT
# define VMBLOCK_DEVICE "/proc/" VMBLOCK_CONTROL_PROC_DIRNAME \
"/" VMBLOCK_CONTROL_DEVNAME
# define VMBLOCK_DEVICE_MODE O_WRONLY
# define VMBLOCK_CONTROL(fd, op, path) write(fd, path, op)
#elif defined(sun) || defined(__FreeBSD__)
# define VMBLOCK_MOUNT_POINT "/var/run/" VMBLOCK_FS_NAME
# define VMBLOCK_DEVICE VMBLOCK_MOUNT_POINT
# define VMBLOCK_DEVICE_MODE O_RDONLY
# if defined(sun) /* if (sun) { */
/*
* Construct ioctl(2) commands for blocks. _IO() is a helper macro to
* construct unique command values more easily. I chose 'v' because I
* didn't see it being used elsewhere, and the command numbers begin at one.
*/
# define VMBLOCK_ADD_FILEBLOCK _IO('v', 1)
# define VMBLOCK_DEL_FILEBLOCK _IO('v', 2)
# ifdef VMX86_DEVEL
# define VMBLOCK_LIST_FILEBLOCKS _IO('v', 3)
# endif
# define VMBLOCK_CONTROL(fd, op, path) ioctl(fd, op, path)
# elif defined(__FreeBSD__) /* } else if (FreeBSD) { */
/*
* Similar to Solaris, construct ioctl(2) commands for block operations.
* Since the FreeBSD implementation does not change the user's passed-in
* data (pathname), we use the _IOW macro to define commands which write
* to the kernel. (As opposed to _IOR or _IOWR.) Groups 'v' and 'V'
* are taken by terminal drivers, so I opted for group 'Z'.
*/
# define VMBLOCK_ADD_FILEBLOCK _IOW('Z', 1, char[MAXPATHLEN] )
# define VMBLOCK_DEL_FILEBLOCK _IOW('Z', 2, char[MAXPATHLEN] )
# ifdef VMX86_DEVEL
# define VMBLOCK_LIST_FILEBLOCKS _IO('Z', 3)
# define VMBLOCK_PURGE_FILEBLOCKS _IO('Z', 4)
# endif
/*
* FreeBSD's ioctl data parameters must be of fixed size. Guarantee a safe
* buffer of size MAXPATHLEN by copying the user's string to one of our own.
*/
# define VMBLOCK_CONTROL(fd, cmd, path) \
({ \
char tpath[MAXPATHLEN]; \
if (path != NULL) { \
strlcpy(tpath, path, MAXPATHLEN); \
} \
ioctl((fd), (cmd), tpath); \
})
# endif /* } */
#else
# error "Unknown platform for vmblock."
#endif
#endif /* _VMBLOCK_H_ */
vmblock-only/include/includeCheck.h 0000444 0000000 0000000 00000000000 12025726674 016344 0 ustar root root vmblock-only/autoconf/ 0000755 0000000 0000000 00000000000 12025726673 014020 5 ustar root root vmblock-only/autoconf/geninclude.c 0000444 0000000 0000000 00000002264 12025726674 016304 0 ustar root root /*********************************************************
* Copyright (C) 2003 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include
#ifdef CONFIG_X86_VOYAGER
APATH/mach-voyager
#endif
#ifdef CONFIG_X86_VISWS
APATH/mach-visws
#endif
#ifdef CONFIG_X86_NUMAQ
APATH/mach-numaq
#endif
#ifdef CONFIG_X86_BIGSMP
APATH/mach-bigsmp
#endif
#ifdef CONFIG_X86_SUMMIT
APATH/mach-summit
#endif
#ifdef CONFIG_X86_GENERICARCH
APATH/mach-generic
#endif
APATH/mach-default
vmblock-only/autoconf/cachecreate.c 0000444 0000000 0000000 00000003206 12025726674 016413 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include
#include
/*
* All kernels before 2.6.22 take 6 arguments. All kernels since
* 2.6.23-rc1 take 5 arguments. Only kernels between 2.6.22 and
* 2.6.23-rc1 are questionable - we could ignore them if we wanted,
* nobody cares about them even now. But unfortunately RedHat is
* re-releasing 2.6.X-rc kernels under 2.6.(X-1) name, so they
* are releasing 2.6.23-rc1 as 2.6.22-5055-something, so we have
* to do autodetection for them.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
/* Success... */
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
#error "This test intentionally fails on 2.6.23 and newer kernels."
#else
#include
struct kmem_cache *kmemtest(void) {
return kmem_cache_create("test", 12, 0, 0, NULL, NULL);
}
#endif
vmblock-only/autoconf/cachector.c 0000444 0000000 0000000 00000003266 12025726674 016125 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include
#include
/*
* Between 2.6.23 and 2.6.24-rc1 ctor prototype was changed from
* ctor(ptr, cache, flags) to ctor(cache, ptr). Unfortunately there
* is no typedef for ctor, so we have to redefine kmem_cache_create
* to find out ctor prototype. This assumes that kmem_cache_create
* takes 5 arguments and not 6 - that change occured between
* 2.6.22 and 2.6.23-rc1. If prototype matches, then this is old
* kernel.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
#error "This test intentionally fails on 2.6.24 and newer kernels."
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23)
#include
struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
unsigned long,
void (*)(void *, struct kmem_cache *, unsigned long));
#endif
vmblock-only/autoconf/cachector1.c 0000444 0000000 0000000 00000003073 12025726674 016202 0 ustar root root /*********************************************************
* Copyright (C) 2008 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include
#include
/*
* Between 2.6.27-rc1 and 2.6.27-rc2 ctor prototype was changed from
* ctor(cache, ptr) to ctor(ptr). Unfortunately there
* is no typedef for ctor, so we have to redefine kmem_cache_create
* to find out ctor prototype. If prototype matches, then this is old
* kernel.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
#error "This test intentionally fails on 2.6.28 and newer kernels."
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#include
struct kmem_cache *kmem_cache_create(const char *, size_t, size_t,
unsigned long,
void (*)(struct kmem_cache *, void *));
#endif
vmblock-only/autoconf/epoll.c 0000444 0000000 0000000 00000002355 12025726674 015303 0 ustar root root /*********************************************************
* Copyright (C) 2004 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* Detect whether we have 'struct poll_wqueues'
* 2.6.x kernels always had this struct. Stock 2.4.x kernels
* never had it, but some distros backported epoll patch.
*/
#include
#include
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
#include
void poll_test(void) {
struct poll_wqueues test;
return poll_initwait(&test);
}
#endif
vmblock-only/autoconf/filldir1.c 0000444 0000000 0000000 00000003256 12025726674 015677 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include
#include
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
#include
#include /* loff_t */
#include /* NULL */
/*
* After 2.6.18, filldir and statfs were changed to send 64-bit inode
* numbers to user space. Red Hat backported this behavior into a 2.6.17
* kernel.
*
* This test will fail on a kernel with such a patch.
*/
static int LinuxDriverFilldir(void *buf,
const char *name,
int namelen,
loff_t offset,
ino_t ino,
unsigned int d_type)
{
return 0;
}
void test(void)
{
vfs_readdir(NULL, LinuxDriverFilldir, NULL);
}
#else
#error "This test intentionally fails on 2.6.20 and newer kernels."
#endif
vmblock-only/autoconf/getsb1.c 0000444 0000000 0000000 00000003074 12025726674 015354 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include
#include
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
#include
/*
* Around 2.6.18, a pointer to a vfsmount was added to get_sb. Red Hat
* backported this behavior into a 2.6.17 kernel.
*
* This test will fail on a kernel with such a patch.
*/
static struct super_block * LinuxDriverGetSb(struct file_system_type *fs_type,
int flags,
const char *dev_name,
void *rawData)
{
return 0;
}
struct file_system_type fs_type = {
.get_sb = LinuxDriverGetSb
};
#else
#error "This test intentionally fails on 2.6.19 or newer kernels."
#endif
vmblock-only/autoconf/setnice.c 0000444 0000000 0000000 00000002163 12025726674 015617 0 ustar root root /*********************************************************
* Copyright (C) 2005 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* set_user_nice appeared in 2.4.21. But some distros
* backported it to older kernels.
*/
#include
#include
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 21)
#include
void test(void) {
set_user_nice(current, -20);
}
#endif
vmblock-only/autoconf/skas1.c 0000444 0000000 0000000 00000002353 12025726674 015210 0 ustar root root /*********************************************************
* Copyright (C) 2004 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
/*
* SKAS patch adds 'struct mm *mm' as first argument to do_mmap_pgoff.
* This patch never hit mainstream kernel.
*/
#include
unsigned long check_do_mmap_pgoff(struct mm_struct *mm, struct file *file,
unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flag,
unsigned long pgoff) {
return do_mmap_pgoff(mm, file, addr, len, prot, flag, pgoff);
}
vmblock-only/autoconf/statfs1.c 0000444 0000000 0000000 00000002667 12025726674 015563 0 ustar root root /*********************************************************
* Copyright (C) 2006 VMware, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 and no later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*********************************************************/
#include
#include
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
#include
/*
* Around 2.6.18, the super_block pointer in statfs was changed to a dentry
* pointer. Red Hat backported this behavior into a 2.6.17 kernel.
*
* This test will fail on a kernel with such a patch.
*/
static int LinuxDriverStatFs(struct super_block *sb,
struct kstatfs *stat)
{
return 0;
}
struct super_operations super_ops = {
.statfs = LinuxDriverStatFs
};
#else
#error "This test intentionally fails on 2.6.19 and newer kernels."
#endif
vmblock-only/Makefile.normal 0000444 0000000 0000000 00000010050 12025726674 015124 0 ustar root root #!/usr/bin/make -f
##########################################################
# Copyright (C) 2006 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation version 2 and no later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
##########################################################
####
#### VMware vmblock Makefile to be distributed externally
####
vm_check_build = $(shell if $(CC) $(CC_OPTS) $(INCLUDE) -Werror -S -o /dev/null -xc $(1) \
> /dev/null 2>&1; then echo "$(2)"; else echo "$(3)"; fi)
####
#### DESTDIR is where the module, object files, and dependencies are built
####
DESTDIR := driver-$(VM_UNAME)
####
#### DRIVERNAME should be untouched unless you have a good reason to change
#### it. The form below is how the scripts expect it.
####
DRIVERNAME := $(DRIVER)-xxx-$(VM_UNAME)
ifneq (,$(filter x86_64%, $(shell $(CC) -dumpmachine)))
MACHINE := x86_64
else
MACHINE := x386
endif
ifdef QUIET
ECHO := @true
else
ECHO := @echo
endif
####
#### You must compile with at least -O level of optimization
#### or the module won't load.
#### If desparate, I think that bringing in might
#### suffice.
####
CC_WARNINGS := -Wall -Wstrict-prototypes
# Don't use -pipe or egcs-2.91.66 (shipped with RedHat) will die
CC_KFLAGS := -D__KERNEL__ -fno-strength-reduce -fno-omit-frame-pointer \
-fno-common -DKBUILD_MODNAME=$(DRIVER)
CC_KFLAGS += $(call vm_check_gcc,-falign-loops=2 -falign-jumps=2 -falign-functions=2, \
-malign-loops=2 -malign-jumps=2 -malign-functions=2)
CC_KFLAGS += $(call vm_check_gcc,-fno-strict-aliasing,)
ifeq ($(MACHINE),x86_64)
CC_KFLAGS += -mno-red-zone -mcmodel=kernel
else
# Gcc 3.0 deprecates -m486 --hpreg
CC_KFLAGS += -DCPU=586 $(call check_gcc,-march=i586,-m486)
endif
CC_OPTS := -O2 -DMODULE $(GLOBAL_DEFS) $(CC_KFLAGS) $(CC_WARNINGS)
INCLUDE := -I$(SRCROOT)/include
INCLUDE += -I$(SRCROOT)/linux
INCLUDE += -I$(SRCROOT)/common
INCLUDE += -I$(HEADER_DIR)
INCLUDE += $(shell $(CC) $(INCLUDE) -E $(SRCROOT)/autoconf/geninclude.c \
| sed -n -e 's!^APATH!-I$(HEADER_DIR)/asm!p')
CC_OPTS += $(call vm_check_build, $(SRCROOT)/autoconf/skas1.c, -DVMW_SKAS_MMAP, )
CC_OPTS += $(call vm_check_build, $(SRCROOT)/autoconf/epoll.c, -DVMW_HAVE_EPOLL, )
CC_OPTS += $(call vm_check_build, $(SRCROOT)/autoconf/setnice.c, -DVMW_HAVE_SET_USER_NICE, )
CC_OPTS += -DVMW_KMEMCR_HAS_DTOR
LINUX_OBJS := module.o
LINUX_OBJS += control.o
LINUX_OBJS += filesystem.o
LINUX_OBJS += super.o
LINUX_OBJS += file.o
LINUX_OBJS += inode.o
LINUX_OBJS += dentry.o
LINUX_OBJS += block.o
LINUX_OBJS += stubs.o
LINUX_OBJS += dbllnklst.o
LINUX_DEPS := ${LINUX_OBJS:.o=.d}
OBJS := $(LINUX_OBJS)
####
#### Make Targets are beneath here.
####
driver: setup deps
$(MAKE) -C $(DESTDIR) -f ../Makefile SRCROOT=../$(SRCROOT) ../$(DRIVER).o \
INCLUDE_DEPS=1
setup:
@if [ -d $(DESTDIR) ] ; then true ; else mkdir $(DESTDIR); chmod 755 $(DESTDIR) ; fi
$(DRIVER) $(DRIVER).o ../$(DRIVER).o: $(DRIVERNAME)
cp -f $< $@
$(DRIVERNAME): $(OBJS)
$(ECHO) "Building $(DRIVERNAME)"
ld -r -o $(DRIVERNAME) $^
auto-build:
$(MAKE) driver QUIET=1
cp -f $(DESTDIR)/$(DRIVERNAME) $(SRCROOT)/../$(DRIVER).o
$(LINUX_OBJS): %.o: $(SRCROOT)/linux/%.c
$(ECHO) "Compiling $<"
$(CC) $(CC_OPTS) $(INCLUDE) -c $<
clean:
rm -rf $(DESTDIR)/
$(LINUX_DEPS): %.d: $(SRCROOT)/linux/%.c
$(ECHO) "Dependencies for $<"
$(CC) -MM $(CC_OPTS) $(INCLUDE) $< > $@
deps: setup
$(MAKE) -C $(DESTDIR) -f ../Makefile SRCROOT=../$(SRCROOT) driver_deps
driver_deps: ${OBJS:.o=.d}
ifdef INCLUDE_DEPS
include ${OBJS:.o=.d}
endif
.SILENT:
vmblock-only/Makefile.kernel 0000444 0000000 0000000 00000004142 12025726674 015121 0 ustar root root #!/usr/bin/make -f
##########################################################
# Copyright (C) 2006 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation version 2 and no later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
##########################################################
INCLUDE := -I$(SRCROOT)/include
EXTRA_CFLAGS := $(CC_OPTS) $(INCLUDE)
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/setnice.c, -DVMW_HAVE_SET_USER_NICE, )
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/epoll.c, -DVMW_HAVE_EPOLL, )
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/skas1.c, -DVMW_SKAS_MMAP, )
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/cachecreate.c, -DVMW_KMEMCR_HAS_DTOR, )
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/cachector.c, -DVMW_KMEMCR_CTOR_HAS_3_ARGS, )
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/cachector1.c, -DVMW_KMEMCR_CTOR_HAS_2_ARGS, )
# Note: These tests are inverted.
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/getsb1.c, , -DVMW_GETSB_2618)
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/statfs1.c, , -DVMW_STATFS_2618)
EXTRA_CFLAGS += $(call vm_check_build, $(SRCROOT)/autoconf/filldir1.c, , -DVMW_FILLDIR_2618)
obj-m += $(DRIVER).o
$(DRIVER)-y := $(subst $(SRCROOT)/, , $(patsubst %.c, %.o, $(wildcard $(SRCROOT)/linux/*.c)))
clean:
rm -rf $(wildcard $(DRIVER).mod.c $(DRIVER).ko .tmp_versions \
Module.symvers Modules.symvers Module.markers modules.order \
$(foreach dir,./ linux/,$(addprefix $(dir),.*.cmd .*.o.flags *.o)))
vmblock-only/README 0000444 0000000 0000000 00000000741 12025726673 013062 0 ustar root root This files in this directory and its subdirectories are the kernel module
for the VMware Blocking File System. In order to build, make certain the
Makefile is correct and then just type
make
from this directory. A copy of the module will be left in
driver-/vmblock.o
(e.g. driver-up-2.4.20/vmblock.o) for 2.4 series kernels and in
../vmblock.o
for 2.6 series kernels.
If you have any problems or questions, send mail to support@vmware.com
vmblock-only/Makefile 0000444 0000000 0000000 00000007265 12025726674 013653 0 ustar root root #!/usr/bin/make -f
##########################################################
# Copyright (C) 1998 VMware, Inc. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation version 2 and no later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
##########################################################
####
#### VMware kernel module Makefile to be distributed externally
####
####
#### SRCROOT _must_ be a relative path.
####
SRCROOT = .
VM_UNAME = $(shell uname -r)
# Header directory for the running kernel
HEADER_DIR = /lib/modules/$(VM_UNAME)/build/include
BUILD_DIR = $(HEADER_DIR)/..
DRIVER := vmblock
PRODUCT := @PRODUCT@
# Grep program
GREP = /bin/grep
vm_check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
vm_check_file = $(shell if test -f $(1); then echo "yes"; else echo "no"; fi)
ifndef VM_KBUILD
VM_KBUILD := no
ifeq ($(call vm_check_file,$(BUILD_DIR)/Makefile), yes)
ifneq ($(call vm_check_file,$(BUILD_DIR)/Rules.make), yes)
VM_KBUILD := 26
endif
endif
export VM_KBUILD
endif
ifndef VM_KBUILD_SHOWN
ifeq ($(VM_KBUILD), no)
VM_DUMMY := $(shell echo >&2 "Using standalone build system.")
else
ifeq ($(VM_KBUILD), 24)
VM_DUMMY := $(shell echo >&2 "Using 2.4.x kernel build system.")
else
VM_DUMMY := $(shell echo >&2 "Using 2.6.x kernel build system.")
endif
endif
VM_KBUILD_SHOWN := yes
export VM_KBUILD_SHOWN
endif
ifneq ($(VM_KBUILD), no)
VMCCVER := $(shell $(CC) -dumpversion)
# If there is no version defined, we are in toplevel pass, not yet in kernel makefiles...
ifeq ($(VERSION),)
ifeq ($(VM_KBUILD), 24)
DRIVER_KO := $(DRIVER).o
else
DRIVER_KO := $(DRIVER).ko
endif
.PHONY: $(DRIVER_KO)
auto-build: $(DRIVER_KO)
cp -f $< $(SRCROOT)/../$(DRIVER).o
# $(DRIVER_KO) is a phony target, so compare file times explicitly
$(DRIVER): $(DRIVER_KO)
if [ $< -nt $@ ] || [ ! -e $@ ] ; then cp -f $< $@; fi
# Pass gcc version down the chain, so we can detect if kernel attempts to use unapproved compiler
VM_CCVER := $(VMCCVER)
export VM_CCVER
VM_CC := $(CC)
export VM_CC
MAKEOVERRIDES := $(filter-out CC=%,$(MAKEOVERRIDES))
#
# Define a setup target that gets built before the actual driver.
# This target may not be used at all, but if it is then it will be defined
# in Makefile.kernel
#
prebuild:: ;
postbuild:: ;
$(DRIVER_KO): prebuild
make -C $(BUILD_DIR) SUBDIRS=$$PWD SRCROOT=$$PWD/$(SRCROOT) modules
make -C $$PWD SRCROOT=$$PWD/$(SRCROOT) postbuild
endif
vm_check_build = $(shell if $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) \
$(CPPFLAGS) $(CFLAGS) $(CFLAGS_KERNEL) $(LINUXINCLUDE) \
$(EXTRA_CFLAGS) -Iinclude2/asm/mach-default \
-DKBUILD_BASENAME=\"$(DRIVER)\" \
-Werror -S -o /dev/null -xc $(1) \
> /dev/null 2>&1; then echo "$(2)"; else echo "$(3)"; fi)
CC_WARNINGS := -Wall -Wstrict-prototypes
CC_OPTS := $(GLOBAL_DEFS) $(CC_WARNINGS) -DVMW_USING_KBUILD
ifdef VMX86_DEVEL
CC_OPTS += -DVMX86_DEVEL
endif
ifdef VMX86_DEBUG
CC_OPTS += -DVMX86_DEBUG
endif
include $(SRCROOT)/Makefile.kernel
ifdef TOPDIR
ifeq ($(VM_KBUILD), 24)
O_TARGET := $(DRIVER).o
obj-y := $($(DRIVER)-y)
include $(TOPDIR)/Rules.make
endif
endif
else
include $(SRCROOT)/Makefile.normal
endif
#.SILENT:
vmblock-only/COPYING 0000444 0000000 0000000 00000043103 12025726673 013234 0 ustar root root GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.