[PATCH 1/3] Minimum wrapfs rename

Alin Dobre alin.dobre at elastichosts.com
Wed Oct 2 10:47:33 EDT 2013


From: Alin Dobre <alinmd at gmail.com>

wrapfs renamed to idmapfs, with minimum changes.

Signed-off-by: Alin Dobre <alinmd at gmail.com>
---
 fs/Kconfig          |   2 +-
 fs/Makefile         |   2 +-
 fs/idmapfs/Kconfig  |   8 +
 fs/idmapfs/Makefile |   7 +
 fs/idmapfs/dentry.c |  49 ++++++
 fs/idmapfs/file.c   | 295 +++++++++++++++++++++++++++++++++
 fs/idmapfs/inode.c  | 463 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/idmapfs/lookup.c | 332 +++++++++++++++++++++++++++++++++++++
 fs/idmapfs/main.c   | 174 ++++++++++++++++++++
 fs/idmapfs/mmap.c   |  53 ++++++
 fs/idmapfs/super.c  | 168 +++++++++++++++++++
 fs/idmapfs/wrapfs.h | 205 +++++++++++++++++++++++
 fs/wrapfs/Kconfig   |   8 -
 fs/wrapfs/Makefile  |   7 -
 fs/wrapfs/dentry.c  |  49 ------
 fs/wrapfs/file.c    | 295 ---------------------------------
 fs/wrapfs/inode.c   | 463 ----------------------------------------------------
 fs/wrapfs/lookup.c  | 332 -------------------------------------
 fs/wrapfs/main.c    | 174 --------------------
 fs/wrapfs/mmap.c    |  53 ------
 fs/wrapfs/super.c   | 168 -------------------
 fs/wrapfs/wrapfs.h  | 205 -----------------------
 22 files changed, 1756 insertions(+), 1756 deletions(-)
 create mode 100644 fs/idmapfs/Kconfig
 create mode 100644 fs/idmapfs/Makefile
 create mode 100644 fs/idmapfs/dentry.c
 create mode 100644 fs/idmapfs/file.c
 create mode 100644 fs/idmapfs/inode.c
 create mode 100644 fs/idmapfs/lookup.c
 create mode 100644 fs/idmapfs/main.c
 create mode 100644 fs/idmapfs/mmap.c
 create mode 100644 fs/idmapfs/super.c
 create mode 100644 fs/idmapfs/wrapfs.h
 delete mode 100644 fs/wrapfs/Kconfig
 delete mode 100644 fs/wrapfs/Makefile
 delete mode 100644 fs/wrapfs/dentry.c
 delete mode 100644 fs/wrapfs/file.c
 delete mode 100644 fs/wrapfs/inode.c
 delete mode 100644 fs/wrapfs/lookup.c
 delete mode 100644 fs/wrapfs/main.c
 delete mode 100644 fs/wrapfs/mmap.c
 delete mode 100644 fs/wrapfs/super.c
 delete mode 100644 fs/wrapfs/wrapfs.h

diff --git a/fs/Kconfig b/fs/Kconfig
index ef2b6c0..f9d0167 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -188,7 +188,7 @@ if MISC_FILESYSTEMS
 source "fs/adfs/Kconfig"
 source "fs/affs/Kconfig"
 source "fs/ecryptfs/Kconfig"
-source "fs/wrapfs/Kconfig"
+source "fs/idmapfs/Kconfig"
 source "fs/hfs/Kconfig"
 source "fs/hfsplus/Kconfig"
 source "fs/befs/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index b0baa95..a6d13fc 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -82,7 +82,7 @@ obj-$(CONFIG_ISO9660_FS)	+= isofs/
 obj-$(CONFIG_HFSPLUS_FS)	+= hfsplus/ # Before hfs to find wrapped HFS+
 obj-$(CONFIG_HFS_FS)		+= hfs/
 obj-$(CONFIG_ECRYPT_FS)		+= ecryptfs/
-obj-$(CONFIG_WRAP_FS)		+= wrapfs/
+obj-$(CONFIG_IDMAP_FS)		+= idmapfs/
 obj-$(CONFIG_VXFS_FS)		+= freevxfs/
 obj-$(CONFIG_NFS_FS)		+= nfs/
 obj-$(CONFIG_EXPORTFS)		+= exportfs/
diff --git a/fs/idmapfs/Kconfig b/fs/idmapfs/Kconfig
new file mode 100644
index 0000000..c4c7dd2
--- /dev/null
+++ b/fs/idmapfs/Kconfig
@@ -0,0 +1,8 @@
+config IDMAP_FS
+	tristate "Idmapfs stackable file system (EXPERIMENTAL)"
+	help
+	  Wrapfs is a stackable file system which simply passes its
+	  operations to the lower layer.  It is designed as a useful
+	  template for developing or debugging other stackable file systems,
+	  and more (see Documentation/filesystems/wrapfs.txt).  See
+	  <http://wrapfs.filesystems.org/> for details.
diff --git a/fs/idmapfs/Makefile b/fs/idmapfs/Makefile
new file mode 100644
index 0000000..bf88f3c
--- /dev/null
+++ b/fs/idmapfs/Makefile
@@ -0,0 +1,7 @@
+WRAPFS_VERSION="0.1"
+
+EXTRA_CFLAGS += -DWRAPFS_VERSION=\"$(WRAPFS_VERSION)\"
+
+obj-$(CONFIG_IDMAP_FS) += idmapfs.o
+
+idmapfs-y := dentry.o file.o inode.o main.o super.o lookup.o mmap.o
diff --git a/fs/idmapfs/dentry.c b/fs/idmapfs/dentry.c
new file mode 100644
index 0000000..ed1a0cb
--- /dev/null
+++ b/fs/idmapfs/dentry.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wrapfs.h"
+
+/*
+ * returns: -ERRNO if error (returned to user)
+ *          0: tell VFS to invalidate dentry
+ *          1: dentry is valid
+ */
+static int wrapfs_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+	struct path lower_path;
+	struct dentry *lower_dentry;
+	int err = 1;
+
+	if (flags & LOOKUP_RCU)
+		return -ECHILD;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
+		goto out;
+	err = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
+out:
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+static void wrapfs_d_release(struct dentry *dentry)
+{
+	/* release and reset the lower paths */
+	wrapfs_put_reset_lower_path(dentry);
+	free_dentry_private_data(dentry);
+	return;
+}
+
+const struct dentry_operations wrapfs_dops = {
+	.d_revalidate	= wrapfs_d_revalidate,
+	.d_release	= wrapfs_d_release,
+};
diff --git a/fs/idmapfs/file.c b/fs/idmapfs/file.c
new file mode 100644
index 0000000..9825816
--- /dev/null
+++ b/fs/idmapfs/file.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wrapfs.h"
+
+static ssize_t wrapfs_read(struct file *file, char __user *buf,
+			   size_t count, loff_t *ppos)
+{
+	int err;
+	struct file *lower_file;
+	struct dentry *dentry = file->f_path.dentry;
+
+	lower_file = wrapfs_lower_file(file);
+	err = vfs_read(lower_file, buf, count, ppos);
+	/* update our inode atime upon a successful lower read */
+	if (err >= 0)
+		fsstack_copy_attr_atime(dentry->d_inode,
+					lower_file->f_path.dentry->d_inode);
+
+	return err;
+}
+
+static ssize_t wrapfs_write(struct file *file, const char __user *buf,
+			    size_t count, loff_t *ppos)
+{
+	int err = 0;
+	struct file *lower_file;
+	struct dentry *dentry = file->f_path.dentry;
+
+	lower_file = wrapfs_lower_file(file);
+	err = vfs_write(lower_file, buf, count, ppos);
+	/* update our inode times+sizes upon a successful lower write */
+	if (err >= 0) {
+		fsstack_copy_inode_size(dentry->d_inode,
+					lower_file->f_path.dentry->d_inode);
+		fsstack_copy_attr_times(dentry->d_inode,
+					lower_file->f_path.dentry->d_inode);
+	}
+
+	return err;
+}
+
+static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir)
+{
+	int err = 0;
+	struct file *lower_file = NULL;
+	struct dentry *dentry = file->f_path.dentry;
+
+	lower_file = wrapfs_lower_file(file);
+	err = vfs_readdir(lower_file, filldir, dirent);
+	file->f_pos = lower_file->f_pos;
+	if (err >= 0)		/* copy the atime */
+		fsstack_copy_attr_atime(dentry->d_inode,
+					lower_file->f_path.dentry->d_inode);
+	return err;
+}
+
+static long wrapfs_unlocked_ioctl(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	long err = -ENOTTY;
+	struct file *lower_file;
+
+	lower_file = wrapfs_lower_file(file);
+
+	/* XXX: use vfs_ioctl if/when VFS exports it */
+	if (!lower_file || !lower_file->f_op)
+		goto out;
+	if (lower_file->f_op->unlocked_ioctl)
+		err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
+
+	/* some ioctls can change inode attributes (EXT2_IOC_SETFLAGS) */
+	if (!err)
+		fsstack_copy_attr_all(file->f_path.dentry->d_inode,
+				      lower_file->f_path.dentry->d_inode);
+out:
+	return err;
+}
+
+#ifdef CONFIG_COMPAT
+static long wrapfs_compat_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	long err = -ENOTTY;
+	struct file *lower_file;
+
+	lower_file = wrapfs_lower_file(file);
+
+	/* XXX: use vfs_ioctl if/when VFS exports it */
+	if (!lower_file || !lower_file->f_op)
+		goto out;
+	if (lower_file->f_op->compat_ioctl)
+		err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
+
+out:
+	return err;
+}
+#endif
+
+static int wrapfs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	int err = 0;
+	bool willwrite;
+	struct file *lower_file;
+	const struct vm_operations_struct *saved_vm_ops = NULL;
+
+	/* this might be deferred to mmap's writepage */
+	willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
+
+	/*
+	 * File systems which do not implement ->writepage may use
+	 * generic_file_readonly_mmap as their ->mmap op.  If you call
+	 * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
+	 * But we cannot call the lower ->mmap op, so we can't tell that
+	 * writeable mappings won't work.  Therefore, our only choice is to
+	 * check if the lower file system supports the ->writepage, and if
+	 * not, return EINVAL (the same error that
+	 * generic_file_readonly_mmap returns in that case).
+	 */
+	lower_file = wrapfs_lower_file(file);
+	if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
+		err = -EINVAL;
+		printk(KERN_ERR "wrapfs: lower file system does not "
+		       "support writeable mmap\n");
+		goto out;
+	}
+
+	/*
+	 * find and save lower vm_ops.
+	 *
+	 * XXX: the VFS should have a cleaner way of finding the lower vm_ops
+	 */
+	if (!WRAPFS_F(file)->lower_vm_ops) {
+		err = lower_file->f_op->mmap(lower_file, vma);
+		if (err) {
+			printk(KERN_ERR "wrapfs: lower mmap failed %d\n", err);
+			goto out;
+		}
+		saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */
+	}
+
+	/*
+	 * Next 3 lines are all I need from generic_file_mmap.  I definitely
+	 * don't want its test for ->readpage which returns -ENOEXEC.
+	 */
+	file_accessed(file);
+	vma->vm_ops = &wrapfs_vm_ops;
+
+	file->f_mapping->a_ops = &wrapfs_aops; /* set our aops */
+	if (!WRAPFS_F(file)->lower_vm_ops) /* save for our ->fault */
+		WRAPFS_F(file)->lower_vm_ops = saved_vm_ops;
+
+out:
+	return err;
+}
+
+static int wrapfs_open(struct inode *inode, struct file *file)
+{
+	int err = 0;
+	struct file *lower_file = NULL;
+	struct path lower_path;
+
+	/* don't open unhashed/deleted files */
+	if (d_unhashed(file->f_path.dentry)) {
+		err = -ENOENT;
+		goto out_err;
+	}
+
+	file->private_data =
+		kzalloc(sizeof(struct wrapfs_file_info), GFP_KERNEL);
+	if (!WRAPFS_F(file)) {
+		err = -ENOMEM;
+		goto out_err;
+	}
+
+	/* open lower object and link wrapfs's file struct to lower's */
+	wrapfs_get_lower_path(file->f_path.dentry, &lower_path);
+	lower_file = dentry_open(&lower_path, file->f_flags, current_cred());
+	path_put(&lower_path);
+	if (IS_ERR(lower_file)) {
+		err = PTR_ERR(lower_file);
+		lower_file = wrapfs_lower_file(file);
+		if (lower_file) {
+			wrapfs_set_lower_file(file, NULL);
+			fput(lower_file); /* fput calls dput for lower_dentry */
+		}
+	} else {
+		wrapfs_set_lower_file(file, lower_file);
+	}
+
+	if (err)
+		kfree(WRAPFS_F(file));
+	else
+		fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode));
+out_err:
+	return err;
+}
+
+static int wrapfs_flush(struct file *file, fl_owner_t id)
+{
+	int err = 0;
+	struct file *lower_file = NULL;
+
+	lower_file = wrapfs_lower_file(file);
+	if (lower_file && lower_file->f_op && lower_file->f_op->flush)
+		err = lower_file->f_op->flush(lower_file, id);
+
+	return err;
+}
+
+/* release all lower object references & free the file info structure */
+static int wrapfs_file_release(struct inode *inode, struct file *file)
+{
+	struct file *lower_file;
+
+	lower_file = wrapfs_lower_file(file);
+	if (lower_file) {
+		wrapfs_set_lower_file(file, NULL);
+		fput(lower_file);
+	}
+
+	kfree(WRAPFS_F(file));
+	return 0;
+}
+
+static int wrapfs_fsync(struct file *file, loff_t start, loff_t end,
+			int datasync)
+{
+	int err;
+	struct file *lower_file;
+	struct path lower_path;
+	struct dentry *dentry = file->f_path.dentry;
+
+	err = generic_file_fsync(file, start, end, datasync);
+	if (err)
+		goto out;
+	lower_file = wrapfs_lower_file(file);
+	wrapfs_get_lower_path(dentry, &lower_path);
+	err = vfs_fsync_range(lower_file, start, end, datasync);
+	wrapfs_put_lower_path(dentry, &lower_path);
+out:
+	return err;
+}
+
+static int wrapfs_fasync(int fd, struct file *file, int flag)
+{
+	int err = 0;
+	struct file *lower_file = NULL;
+
+	lower_file = wrapfs_lower_file(file);
+	if (lower_file->f_op && lower_file->f_op->fasync)
+		err = lower_file->f_op->fasync(fd, lower_file, flag);
+
+	return err;
+}
+
+const struct file_operations wrapfs_main_fops = {
+	.llseek		= generic_file_llseek,
+	.read		= wrapfs_read,
+	.write		= wrapfs_write,
+	.unlocked_ioctl	= wrapfs_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= wrapfs_compat_ioctl,
+#endif
+	.mmap		= wrapfs_mmap,
+	.open		= wrapfs_open,
+	.flush		= wrapfs_flush,
+	.release	= wrapfs_file_release,
+	.fsync		= wrapfs_fsync,
+	.fasync		= wrapfs_fasync,
+};
+
+/* trimmed directory options */
+const struct file_operations wrapfs_dir_fops = {
+	.llseek		= generic_file_llseek,
+	.read		= generic_read_dir,
+	.readdir	= wrapfs_readdir,
+	.unlocked_ioctl	= wrapfs_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= wrapfs_compat_ioctl,
+#endif
+	.open		= wrapfs_open,
+	.release	= wrapfs_file_release,
+	.flush		= wrapfs_flush,
+	.fsync		= wrapfs_fsync,
+	.fasync		= wrapfs_fasync,
+};
diff --git a/fs/idmapfs/inode.c b/fs/idmapfs/inode.c
new file mode 100644
index 0000000..d7fe145
--- /dev/null
+++ b/fs/idmapfs/inode.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wrapfs.h"
+
+static int wrapfs_create(struct inode *dir, struct dentry *dentry,
+			 umode_t mode, bool want_excl)
+{
+	int err = 0;
+	struct dentry *lower_dentry;
+	struct dentry *lower_parent_dentry = NULL;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	lower_parent_dentry = lock_parent(lower_dentry);
+
+	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode,
+			 want_excl);
+	if (err)
+		goto out;
+	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
+	if (err)
+		goto out;
+	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
+	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
+
+out:
+	unlock_dir(lower_parent_dentry);
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+static int wrapfs_link(struct dentry *old_dentry, struct inode *dir,
+		       struct dentry *new_dentry)
+{
+	struct dentry *lower_old_dentry;
+	struct dentry *lower_new_dentry;
+	struct dentry *lower_dir_dentry;
+	u64 file_size_save;
+	int err;
+	struct path lower_old_path, lower_new_path;
+
+	file_size_save = i_size_read(old_dentry->d_inode);
+	wrapfs_get_lower_path(old_dentry, &lower_old_path);
+	wrapfs_get_lower_path(new_dentry, &lower_new_path);
+	lower_old_dentry = lower_old_path.dentry;
+	lower_new_dentry = lower_new_path.dentry;
+	lower_dir_dentry = lock_parent(lower_new_dentry);
+
+	err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
+		       lower_new_dentry);
+	if (err || !lower_new_dentry->d_inode)
+		goto out;
+
+	err = wrapfs_interpose(new_dentry, dir->i_sb, &lower_new_path);
+	if (err)
+		goto out;
+	fsstack_copy_attr_times(dir, lower_new_dentry->d_inode);
+	fsstack_copy_inode_size(dir, lower_new_dentry->d_inode);
+	set_nlink(old_dentry->d_inode,
+		  wrapfs_lower_inode(old_dentry->d_inode)->i_nlink);
+	i_size_write(new_dentry->d_inode, file_size_save);
+out:
+	unlock_dir(lower_dir_dentry);
+	wrapfs_put_lower_path(old_dentry, &lower_old_path);
+	wrapfs_put_lower_path(new_dentry, &lower_new_path);
+	return err;
+}
+
+static int wrapfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int err;
+	struct dentry *lower_dentry;
+	struct inode *lower_dir_inode = wrapfs_lower_inode(dir);
+	struct dentry *lower_dir_dentry;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	dget(lower_dentry);
+	lower_dir_dentry = lock_parent(lower_dentry);
+
+	err = vfs_unlink(lower_dir_inode, lower_dentry);
+
+	/*
+	 * Note: unlinking on top of NFS can cause silly-renamed files.
+	 * Trying to delete such files results in EBUSY from NFS
+	 * below.  Silly-renamed files will get deleted by NFS later on, so
+	 * we just need to detect them here and treat such EBUSY errors as
+	 * if the upper file was successfully deleted.
+	 */
+	if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED)
+		err = 0;
+	if (err)
+		goto out;
+	fsstack_copy_attr_times(dir, lower_dir_inode);
+	fsstack_copy_inode_size(dir, lower_dir_inode);
+	set_nlink(dentry->d_inode,
+		  wrapfs_lower_inode(dentry->d_inode)->i_nlink);
+	dentry->d_inode->i_ctime = dir->i_ctime;
+	d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */
+out:
+	unlock_dir(lower_dir_dentry);
+	dput(lower_dentry);
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
+			  const char *symname)
+{
+	int err = 0;
+	struct dentry *lower_dentry;
+	struct dentry *lower_parent_dentry = NULL;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	lower_parent_dentry = lock_parent(lower_dentry);
+
+	err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname);
+	if (err)
+		goto out;
+	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
+	if (err)
+		goto out;
+	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
+	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
+
+out:
+	unlock_dir(lower_parent_dentry);
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+	int err = 0;
+	struct dentry *lower_dentry;
+	struct dentry *lower_parent_dentry = NULL;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	lower_parent_dentry = lock_parent(lower_dentry);
+
+	err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode);
+	if (err)
+		goto out;
+
+	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
+	if (err)
+		goto out;
+
+	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
+	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
+	/* update number of links on parent directory */
+	set_nlink(dir, wrapfs_lower_inode(dir)->i_nlink);
+
+out:
+	unlock_dir(lower_parent_dentry);
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	struct dentry *lower_dentry;
+	struct dentry *lower_dir_dentry;
+	int err;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	lower_dir_dentry = lock_parent(lower_dentry);
+
+	err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
+	if (err)
+		goto out;
+
+	d_drop(dentry);	/* drop our dentry on success (why not VFS's job?) */
+	if (dentry->d_inode)
+		clear_nlink(dentry->d_inode);
+	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
+	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
+
+out:
+	unlock_dir(lower_dir_dentry);
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
+			dev_t dev)
+{
+	int err = 0;
+	struct dentry *lower_dentry;
+	struct dentry *lower_parent_dentry = NULL;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	lower_parent_dentry = lock_parent(lower_dentry);
+
+	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
+	if (err)
+		goto out;
+
+	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
+	if (err)
+		goto out;
+	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
+	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
+
+out:
+	unlock_dir(lower_parent_dentry);
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+/*
+ * The locking rules in wrapfs_rename are complex.  We could use a simpler
+ * superblock-level name-space lock for renames and copy-ups.
+ */
+static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+			 struct inode *new_dir, struct dentry *new_dentry)
+{
+	int err = 0;
+	struct dentry *lower_old_dentry = NULL;
+	struct dentry *lower_new_dentry = NULL;
+	struct dentry *lower_old_dir_dentry = NULL;
+	struct dentry *lower_new_dir_dentry = NULL;
+	struct dentry *trap = NULL;
+	struct path lower_old_path, lower_new_path;
+
+	wrapfs_get_lower_path(old_dentry, &lower_old_path);
+	wrapfs_get_lower_path(new_dentry, &lower_new_path);
+	lower_old_dentry = lower_old_path.dentry;
+	lower_new_dentry = lower_new_path.dentry;
+	lower_old_dir_dentry = dget_parent(lower_old_dentry);
+	lower_new_dir_dentry = dget_parent(lower_new_dentry);
+
+	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
+	/* source should not be ancestor of target */
+	if (trap == lower_old_dentry) {
+		err = -EINVAL;
+		goto out;
+	}
+	/* target should not be ancestor of source */
+	if (trap == lower_new_dentry) {
+		err = -ENOTEMPTY;
+		goto out;
+	}
+
+	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
+			 lower_new_dir_dentry->d_inode, lower_new_dentry);
+	if (err)
+		goto out;
+
+	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
+	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
+	if (new_dir != old_dir) {
+		fsstack_copy_attr_all(old_dir,
+				      lower_old_dir_dentry->d_inode);
+		fsstack_copy_inode_size(old_dir,
+					lower_old_dir_dentry->d_inode);
+	}
+
+out:
+	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
+	dput(lower_old_dir_dentry);
+	dput(lower_new_dir_dentry);
+	wrapfs_put_lower_path(old_dentry, &lower_old_path);
+	wrapfs_put_lower_path(new_dentry, &lower_new_path);
+	return err;
+}
+
+static int wrapfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
+{
+	int err;
+	struct dentry *lower_dentry;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	if (!lower_dentry->d_inode->i_op ||
+	    !lower_dentry->d_inode->i_op->readlink) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
+						    buf, bufsiz);
+	if (err < 0)
+		goto out;
+	fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
+
+out:
+	wrapfs_put_lower_path(dentry, &lower_path);
+	return err;
+}
+
+static void *wrapfs_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	char *buf;
+	int len = PAGE_SIZE, err;
+	mm_segment_t old_fs;
+
+	/* This is freed by the put_link method assuming a successful call. */
+	buf = kmalloc(len, GFP_KERNEL);
+	if (!buf) {
+		buf = ERR_PTR(-ENOMEM);
+		goto out;
+	}
+
+	/* read the symlink, and then we will follow it */
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = wrapfs_readlink(dentry, buf, len);
+	set_fs(old_fs);
+	if (err < 0) {
+		kfree(buf);
+		buf = ERR_PTR(err);
+	} else {
+		buf[err] = '\0';
+	}
+out:
+	nd_set_link(nd, buf);
+	return NULL;
+}
+
+/* this @nd *IS* still used */
+static void wrapfs_put_link(struct dentry *dentry, struct nameidata *nd,
+			    void *cookie)
+{
+	char *buf = nd_get_link(nd);
+	if (!IS_ERR(buf))	/* free the char* */
+		kfree(buf);
+}
+
+static int wrapfs_permission(struct inode *inode, int mask)
+{
+	struct inode *lower_inode;
+	int err;
+
+	lower_inode = wrapfs_lower_inode(inode);
+	err = inode_permission(lower_inode, mask);
+	return err;
+}
+
+static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
+{
+	int err = 0;
+	struct dentry *lower_dentry;
+	struct inode *inode;
+	struct inode *lower_inode;
+	struct path lower_path;
+	struct iattr lower_ia;
+
+	inode = dentry->d_inode;
+
+	/*
+	 * Check if user has permission to change inode.  We don't check if
+	 * this user can change the lower inode: that should happen when
+	 * calling notify_change on the lower inode.
+	 */
+	err = inode_change_ok(inode, ia);
+	if (err)
+		goto out_err;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	lower_dentry = lower_path.dentry;
+	lower_inode = wrapfs_lower_inode(inode);
+
+	/* prepare our own lower struct iattr (with the lower file) */
+	memcpy(&lower_ia, ia, sizeof(lower_ia));
+	if (ia->ia_valid & ATTR_FILE)
+		lower_ia.ia_file = wrapfs_lower_file(ia->ia_file);
+
+	/*
+	 * If shrinking, first truncate upper level to cancel writing dirty
+	 * pages beyond the new eof; and also if its' maxbytes is more
+	 * limiting (fail with -EFBIG before making any change to the lower
+	 * level).  There is no need to vmtruncate the upper level
+	 * afterwards in the other cases: we fsstack_copy_inode_size from
+	 * the lower level.
+	 */
+	if (ia->ia_valid & ATTR_SIZE) {
+		err = inode_newsize_ok(inode, ia->ia_size);
+		if (err)
+			goto out;
+		truncate_setsize(inode, ia->ia_size);
+	}
+
+	/*
+	 * mode change is for clearing setuid/setgid bits. Allow lower fs
+	 * to interpret this in its own way.
+	 */
+	if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
+		lower_ia.ia_valid &= ~ATTR_MODE;
+
+	/* notify the (possibly copied-up) lower inode */
+	/*
+	 * Note: we use lower_dentry->d_inode, because lower_inode may be
+	 * unlinked (no inode->i_sb and i_ino==0.  This happens if someone
+	 * tries to open(), unlink(), then ftruncate() a file.
+	 */
+	mutex_lock(&lower_dentry->d_inode->i_mutex);
+	err = notify_change(lower_dentry, &lower_ia); /* note: lower_ia */
+	mutex_unlock(&lower_dentry->d_inode->i_mutex);
+	if (err)
+		goto out;
+
+	/* get attributes from the lower inode */
+	fsstack_copy_attr_all(inode, lower_inode);
+	/*
+	 * Not running fsstack_copy_inode_size(inode, lower_inode), because
+	 * VFS should update our inode size, and notify_change on
+	 * lower_inode should update its size.
+	 */
+
+out:
+	wrapfs_put_lower_path(dentry, &lower_path);
+out_err:
+	return err;
+}
+
+const struct inode_operations wrapfs_symlink_iops = {
+	.readlink	= wrapfs_readlink,
+	.permission	= wrapfs_permission,
+	.follow_link	= wrapfs_follow_link,
+	.setattr	= wrapfs_setattr,
+	.put_link	= wrapfs_put_link,
+};
+
+const struct inode_operations wrapfs_dir_iops = {
+	.create		= wrapfs_create,
+	.lookup		= wrapfs_lookup,
+	.link		= wrapfs_link,
+	.unlink		= wrapfs_unlink,
+	.symlink	= wrapfs_symlink,
+	.mkdir		= wrapfs_mkdir,
+	.rmdir		= wrapfs_rmdir,
+	.mknod		= wrapfs_mknod,
+	.rename		= wrapfs_rename,
+	.permission	= wrapfs_permission,
+	.setattr	= wrapfs_setattr,
+};
+
+const struct inode_operations wrapfs_main_iops = {
+	.permission	= wrapfs_permission,
+	.setattr	= wrapfs_setattr,
+};
diff --git a/fs/idmapfs/lookup.c b/fs/idmapfs/lookup.c
new file mode 100644
index 0000000..fa6e019
--- /dev/null
+++ b/fs/idmapfs/lookup.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wrapfs.h"
+
+/* The dentry cache is just so we have properly sized dentries */
+static struct kmem_cache *wrapfs_dentry_cachep;
+
+int wrapfs_init_dentry_cache(void)
+{
+	wrapfs_dentry_cachep =
+		kmem_cache_create("wrapfs_dentry",
+				  sizeof(struct wrapfs_dentry_info),
+				  0, SLAB_RECLAIM_ACCOUNT, NULL);
+
+	return wrapfs_dentry_cachep ? 0 : -ENOMEM;
+}
+
+void wrapfs_destroy_dentry_cache(void)
+{
+	if (wrapfs_dentry_cachep)
+		kmem_cache_destroy(wrapfs_dentry_cachep);
+}
+
+void free_dentry_private_data(struct dentry *dentry)
+{
+	if (!dentry || !dentry->d_fsdata)
+		return;
+	kmem_cache_free(wrapfs_dentry_cachep, dentry->d_fsdata);
+	dentry->d_fsdata = NULL;
+}
+
+/* allocate new dentry private data */
+int new_dentry_private_data(struct dentry *dentry)
+{
+	struct wrapfs_dentry_info *info = WRAPFS_D(dentry);
+
+	/* use zalloc to init dentry_info.lower_path */
+	info = kmem_cache_zalloc(wrapfs_dentry_cachep, GFP_ATOMIC);
+	if (!info)
+		return -ENOMEM;
+
+	spin_lock_init(&info->lock);
+	dentry->d_fsdata = info;
+
+	return 0;
+}
+
+/*
+ * Initialize a nameidata structure (the intent part) we can pass to a lower
+ * file system.  Returns 0 on success or -error (only -ENOMEM possible).
+ */
+int init_lower_nd(struct nameidata *nd, unsigned int flags)
+{
+	int err = 0;
+
+	memset(nd, 0, sizeof(struct nameidata));
+	if (!flags)
+		goto out;
+
+	switch (flags) {
+	case LOOKUP_CREATE:
+	case LOOKUP_OPEN:
+		nd->flags = flags;
+		break;
+	default:
+		/* We should never get here, for now */
+		pr_debug("wrapfs: unknown nameidata flag 0x%x\n", flags);
+		BUG();
+		break;
+	}
+
+out:
+	return err;
+}
+
+static int wrapfs_inode_test(struct inode *inode, void *candidate_lower_inode)
+{
+	struct inode *current_lower_inode = wrapfs_lower_inode(inode);
+	if (current_lower_inode == (struct inode *)candidate_lower_inode)
+		return 1; /* found a match */
+	else
+		return 0; /* no match */
+}
+
+static int wrapfs_inode_set(struct inode *inode, void *lower_inode)
+{
+	/* we do actual inode initialization in wrapfs_iget */
+	return 0;
+}
+
+struct inode *wrapfs_iget(struct super_block *sb, struct inode *lower_inode)
+{
+	struct wrapfs_inode_info *info;
+	struct inode *inode; /* the new inode to return */
+	int err;
+
+	inode = iget5_locked(sb, /* our superblock */
+			     /*
+			      * hashval: we use inode number, but we can
+			      * also use "(unsigned long)lower_inode"
+			      * instead.
+			      */
+			     lower_inode->i_ino, /* hashval */
+			     wrapfs_inode_test,	/* inode comparison function */
+			     wrapfs_inode_set, /* inode init function */
+			     lower_inode); /* data passed to test+set fxns */
+	if (!inode) {
+		err = -EACCES;
+		iput(lower_inode);
+		return ERR_PTR(err);
+	}
+	/* if found a cached inode, then just return it */
+	if (!(inode->i_state & I_NEW))
+		return inode;
+
+	/* initialize new inode */
+	info = WRAPFS_I(inode);
+
+	inode->i_ino = lower_inode->i_ino;
+	if (!igrab(lower_inode)) {
+		err = -ESTALE;
+		return ERR_PTR(err);
+	}
+	wrapfs_set_lower_inode(inode, lower_inode);
+
+	inode->i_version++;
+
+	/* use different set of inode ops for symlinks & directories */
+	if (S_ISDIR(lower_inode->i_mode))
+		inode->i_op = &wrapfs_dir_iops;
+	else if (S_ISLNK(lower_inode->i_mode))
+		inode->i_op = &wrapfs_symlink_iops;
+	else
+		inode->i_op = &wrapfs_main_iops;
+
+	/* use different set of file ops for directories */
+	if (S_ISDIR(lower_inode->i_mode))
+		inode->i_fop = &wrapfs_dir_fops;
+	else
+		inode->i_fop = &wrapfs_main_fops;
+
+	inode->i_mapping->a_ops = &wrapfs_aops;
+
+	inode->i_atime.tv_sec = 0;
+	inode->i_atime.tv_nsec = 0;
+	inode->i_mtime.tv_sec = 0;
+	inode->i_mtime.tv_nsec = 0;
+	inode->i_ctime.tv_sec = 0;
+	inode->i_ctime.tv_nsec = 0;
+
+	/* properly initialize special inodes */
+	if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
+	    S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
+		init_special_inode(inode, lower_inode->i_mode,
+				   lower_inode->i_rdev);
+
+	/* all well, copy inode attributes */
+	fsstack_copy_attr_all(inode, lower_inode);
+	fsstack_copy_inode_size(inode, lower_inode);
+
+	unlock_new_inode(inode);
+	return inode;
+}
+
+/*
+ * Connect a wrapfs inode dentry/inode with several lower ones.  This is
+ * the classic stackable file system "vnode interposition" action.
+ *
+ * @dentry: wrapfs's dentry which interposes on lower one
+ * @sb: wrapfs's super_block
+ * @lower_path: the lower path (caller does path_get/put)
+ */
+int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
+		     struct path *lower_path)
+{
+	int err = 0;
+	struct inode *inode;
+	struct inode *lower_inode;
+	struct super_block *lower_sb;
+
+	lower_inode = lower_path->dentry->d_inode;
+	lower_sb = wrapfs_lower_super(sb);
+
+	/* check that the lower file system didn't cross a mount point */
+	if (lower_inode->i_sb != lower_sb) {
+		err = -EXDEV;
+		goto out;
+	}
+
+	/*
+	 * We allocate our new inode below by calling wrapfs_iget,
+	 * which will initialize some of the new inode's fields
+	 */
+
+	/* inherit lower inode number for wrapfs's inode */
+	inode = wrapfs_iget(sb, lower_inode);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		goto out;
+	}
+
+	d_add(dentry, inode);
+
+out:
+	return err;
+}
+
+/*
+ * Main driver function for wrapfs's lookup.
+ *
+ * Returns: NULL (ok), ERR_PTR if an error occurred.
+ * Fills in lower_parent_path with <dentry,mnt> on success.
+ */
+static struct dentry *__wrapfs_lookup(struct dentry *dentry,
+				      unsigned int flags,
+				      struct path *lower_parent_path)
+{
+	int err = 0;
+	struct vfsmount *lower_dir_mnt;
+	struct dentry *lower_dir_dentry = NULL;
+	struct dentry *lower_dentry;
+	const char *name;
+	struct path lower_path;
+	struct qstr this;
+
+	/* must initialize dentry operations */
+	d_set_d_op(dentry, &wrapfs_dops);
+
+	if (IS_ROOT(dentry))
+		goto out;
+
+	name = dentry->d_name.name;
+
+	/* now start the actual lookup procedure */
+	lower_dir_dentry = lower_parent_path->dentry;
+	lower_dir_mnt = lower_parent_path->mnt;
+
+	/* Use vfs_path_lookup to check if the dentry exists or not */
+	err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0,
+			      &lower_path);
+
+	/* no error: handle positive dentries */
+	if (!err) {
+		wrapfs_set_lower_path(dentry, &lower_path);
+		err = wrapfs_interpose(dentry, dentry->d_sb, &lower_path);
+		if (err) /* path_put underlying path on error */
+			wrapfs_put_reset_lower_path(dentry);
+		goto out;
+	}
+
+	/*
+	 * We don't consider ENOENT an error, and we want to return a
+	 * negative dentry.
+	 */
+	if (err && err != -ENOENT)
+		goto out;
+
+	/* instatiate a new negative dentry */
+	this.name = name;
+	this.len = strlen(name);
+	this.hash = full_name_hash(this.name, this.len);
+	lower_dentry = d_lookup(lower_dir_dentry, &this);
+	if (lower_dentry)
+		goto setup_lower;
+
+	lower_dentry = d_alloc(lower_dir_dentry, &this);
+	if (!lower_dentry) {
+		err = -ENOMEM;
+		goto out;
+	}
+	d_add(lower_dentry, NULL); /* instantiate and hash */
+
+setup_lower:
+	lower_path.dentry = lower_dentry;
+	lower_path.mnt = mntget(lower_dir_mnt);
+	wrapfs_set_lower_path(dentry, &lower_path);
+
+	/*
+	 * If the intent is to create a file, then don't return an error, so
+	 * the VFS will continue the process of making this negative dentry
+	 * into a positive one.
+	 */
+	if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
+		err = 0;
+
+out:
+	return ERR_PTR(err);
+}
+
+struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry,
+			     unsigned int flags)
+{
+	struct dentry *ret, *parent;
+	struct path lower_parent_path;
+	int err = 0;
+
+	parent = dget_parent(dentry);
+
+	wrapfs_get_lower_path(parent, &lower_parent_path);
+
+	/* allocate dentry private data.  We free it in ->d_release */
+	err = new_dentry_private_data(dentry);
+	if (err) {
+		ret = ERR_PTR(err);
+		goto out;
+	}
+	ret = __wrapfs_lookup(dentry, flags, &lower_parent_path);
+	if (IS_ERR(ret))
+		goto out;
+	if (ret)
+		dentry = ret;
+	if (dentry->d_inode)
+		fsstack_copy_attr_times(dentry->d_inode,
+					wrapfs_lower_inode(dentry->d_inode));
+	/* update parent directory's atime */
+	fsstack_copy_attr_atime(parent->d_inode,
+				wrapfs_lower_inode(parent->d_inode));
+
+out:
+	wrapfs_put_lower_path(parent, &lower_parent_path);
+	dput(parent);
+	return ret;
+}
diff --git a/fs/idmapfs/main.c b/fs/idmapfs/main.c
new file mode 100644
index 0000000..73153fd
--- /dev/null
+++ b/fs/idmapfs/main.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wrapfs.h"
+#include <linux/module.h>
+
+/*
+ * There is no need to lock the wrapfs_super_info's rwsem as there is no
+ * way anyone can have a reference to the superblock at this point in time.
+ */
+static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent)
+{
+	int err = 0;
+	struct super_block *lower_sb;
+	struct path lower_path;
+	char *dev_name = (char *) raw_data;
+	struct inode *inode;
+
+	if (!dev_name) {
+		printk(KERN_ERR
+		       "wrapfs: read_super: missing dev_name argument\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* parse lower path */
+	err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
+			&lower_path);
+	if (err) {
+		printk(KERN_ERR	"wrapfs: error accessing "
+		       "lower directory '%s'\n", dev_name);
+		goto out;
+	}
+
+	/* allocate superblock private data */
+	sb->s_fs_info = kzalloc(sizeof(struct wrapfs_sb_info), GFP_KERNEL);
+	if (!WRAPFS_SB(sb)) {
+		printk(KERN_CRIT "wrapfs: read_super: out of memory\n");
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	/* set the lower superblock field of upper superblock */
+	lower_sb = lower_path.dentry->d_sb;
+	atomic_inc(&lower_sb->s_active);
+	wrapfs_set_lower_super(sb, lower_sb);
+
+	/* inherit maxbytes from lower file system */
+	sb->s_maxbytes = lower_sb->s_maxbytes;
+
+	/*
+	 * Our c/m/atime granularity is 1 ns because we may stack on file
+	 * systems whose granularity is as good.
+	 */
+	sb->s_time_gran = 1;
+
+	sb->s_op = &wrapfs_sops;
+
+	/* get a new inode and allocate our root dentry */
+	inode = wrapfs_iget(sb, lower_path.dentry->d_inode);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		goto out_sput;
+	}
+	sb->s_root = d_make_root(inode);
+	if (!sb->s_root) {
+		err = -ENOMEM;
+		goto out_iput;
+	}
+	d_set_d_op(sb->s_root, &wrapfs_dops);
+
+	/* link the upper and lower dentries */
+	sb->s_root->d_fsdata = NULL;
+	err = new_dentry_private_data(sb->s_root);
+	if (err)
+		goto out_freeroot;
+
+	/* if get here: cannot have error */
+
+	/* set the lower dentries for s_root */
+	wrapfs_set_lower_path(sb->s_root, &lower_path);
+
+	/*
+	 * No need to call interpose because we already have a positive
+	 * dentry, which was instantiated by d_make_root.  Just need to
+	 * d_rehash it.
+	 */
+	d_rehash(sb->s_root);
+	if (!silent)
+		printk(KERN_INFO
+		       "wrapfs: mounted on top of %s type %s\n",
+		       dev_name, lower_sb->s_type->name);
+	goto out; /* all is well */
+
+	/* no longer needed: free_dentry_private_data(sb->s_root); */
+out_freeroot:
+	dput(sb->s_root);
+out_iput:
+	iput(inode);
+out_sput:
+	/* drop refs we took earlier */
+	atomic_dec(&lower_sb->s_active);
+	kfree(WRAPFS_SB(sb));
+	sb->s_fs_info = NULL;
+out_free:
+	path_put(&lower_path);
+
+out:
+	return err;
+}
+
+struct dentry *wrapfs_mount(struct file_system_type *fs_type, int flags,
+			    const char *dev_name, void *raw_data)
+{
+	void *lower_path_name = (void *) dev_name;
+
+	return mount_nodev(fs_type, flags, lower_path_name,
+			   wrapfs_read_super);
+}
+
+static struct file_system_type wrapfs_fs_type = {
+	.owner		= THIS_MODULE,
+	.name		= WRAPFS_NAME,
+	.mount		= wrapfs_mount,
+	.kill_sb	= generic_shutdown_super,
+	.fs_flags	= 0,
+};
+MODULE_ALIAS_FS(WRAPFS_NAME);
+
+static int __init init_wrapfs_fs(void)
+{
+	int err;
+
+	pr_info("Registering wrapfs " WRAPFS_VERSION "\n");
+
+	err = wrapfs_init_inode_cache();
+	if (err)
+		goto out;
+	err = wrapfs_init_dentry_cache();
+	if (err)
+		goto out;
+	err = register_filesystem(&wrapfs_fs_type);
+out:
+	if (err) {
+		wrapfs_destroy_inode_cache();
+		wrapfs_destroy_dentry_cache();
+	}
+	return err;
+}
+
+static void __exit exit_wrapfs_fs(void)
+{
+	wrapfs_destroy_inode_cache();
+	wrapfs_destroy_dentry_cache();
+	unregister_filesystem(&wrapfs_fs_type);
+	pr_info("Completed wrapfs module unload\n");
+}
+
+MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
+	      " (http://www.fsl.cs.sunysb.edu/)");
+MODULE_DESCRIPTION("Wrapfs " WRAPFS_VERSION
+		   " (http://wrapfs.filesystems.org/)");
+MODULE_LICENSE("GPL");
+
+module_init(init_wrapfs_fs);
+module_exit(exit_wrapfs_fs);
diff --git a/fs/idmapfs/mmap.c b/fs/idmapfs/mmap.c
new file mode 100644
index 0000000..c224fc3
--- /dev/null
+++ b/fs/idmapfs/mmap.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wrapfs.h"
+
+static int wrapfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+	int err;
+	struct file *file, *lower_file;
+	const struct vm_operations_struct *lower_vm_ops;
+	struct vm_area_struct lower_vma;
+
+	memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
+	file = lower_vma.vm_file;
+	lower_vm_ops = WRAPFS_F(file)->lower_vm_ops;
+	BUG_ON(!lower_vm_ops);
+
+	lower_file = wrapfs_lower_file(file);
+	/*
+	 * XXX: vm_ops->fault may be called in parallel.  Because we have to
+	 * resort to temporarily changing the vma->vm_file to point to the
+	 * lower file, a concurrent invocation of wrapfs_fault could see a
+	 * different value.  In this workaround, we keep a different copy of
+	 * the vma structure in our stack, so we never expose a different
+	 * value of the vma->vm_file called to us, even temporarily.  A
+	 * better fix would be to change the calling semantics of ->fault to
+	 * take an explicit file pointer.
+	 */
+	lower_vma.vm_file = lower_file;
+	err = lower_vm_ops->fault(&lower_vma, vmf);
+	return err;
+}
+
+/*
+ * XXX: the default address_space_ops for wrapfs is empty.  We cannot set
+ * our inode->i_mapping->a_ops to NULL because too many code paths expect
+ * the a_ops vector to be non-NULL.
+ */
+const struct address_space_operations wrapfs_aops = {
+	/* empty on purpose */
+};
+
+const struct vm_operations_struct wrapfs_vm_ops = {
+	.fault		= wrapfs_fault,
+};
diff --git a/fs/idmapfs/super.c b/fs/idmapfs/super.c
new file mode 100644
index 0000000..aec2093
--- /dev/null
+++ b/fs/idmapfs/super.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wrapfs.h"
+
+/*
+ * The inode cache is used with alloc_inode for both our inode info and the
+ * vfs inode.
+ */
+static struct kmem_cache *wrapfs_inode_cachep;
+
+/* final actions when unmounting a file system */
+static void wrapfs_put_super(struct super_block *sb)
+{
+	struct wrapfs_sb_info *spd;
+	struct super_block *s;
+
+	spd = WRAPFS_SB(sb);
+	if (!spd)
+		return;
+
+	/* decrement lower super references */
+	s = wrapfs_lower_super(sb);
+	wrapfs_set_lower_super(sb, NULL);
+	atomic_dec(&s->s_active);
+
+	kfree(spd);
+	sb->s_fs_info = NULL;
+}
+
+static int wrapfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	int err;
+	struct path lower_path;
+
+	wrapfs_get_lower_path(dentry, &lower_path);
+	err = vfs_statfs(&lower_path, buf);
+	wrapfs_put_lower_path(dentry, &lower_path);
+
+	/* set return buf to our f/s to avoid confusing user-level utils */
+	buf->f_type = WRAPFS_SUPER_MAGIC;
+
+	return err;
+}
+
+/*
+ * @flags: numeric mount options
+ * @options: mount options string
+ */
+static int wrapfs_remount_fs(struct super_block *sb, int *flags, char *options)
+{
+	int err = 0;
+
+	/*
+	 * The VFS will take care of "ro" and "rw" flags among others.  We
+	 * can safely accept a few flags (RDONLY, MANDLOCK), and honor
+	 * SILENT, but anything else left over is an error.
+	 */
+	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT)) != 0) {
+		printk(KERN_ERR
+		       "wrapfs: remount flags 0x%x unsupported\n", *flags);
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+/*
+ * Called by iput() when the inode reference count reached zero
+ * and the inode is not hashed anywhere.  Used to clear anything
+ * that needs to be, before the inode is completely destroyed and put
+ * on the inode free list.
+ */
+static void wrapfs_evict_inode(struct inode *inode)
+{
+	struct inode *lower_inode;
+
+	truncate_inode_pages(&inode->i_data, 0);
+	clear_inode(inode);
+	/*
+	 * Decrement a reference to a lower_inode, which was incremented
+	 * by our read_inode when it was created initially.
+	 */
+	lower_inode = wrapfs_lower_inode(inode);
+	wrapfs_set_lower_inode(inode, NULL);
+	iput(lower_inode);
+}
+
+static struct inode *wrapfs_alloc_inode(struct super_block *sb)
+{
+	struct wrapfs_inode_info *i;
+
+	i = kmem_cache_alloc(wrapfs_inode_cachep, GFP_KERNEL);
+	if (!i)
+		return NULL;
+
+	/* memset everything up to the inode to 0 */
+	memset(i, 0, offsetof(struct wrapfs_inode_info, vfs_inode));
+
+	i->vfs_inode.i_version = 1;
+	return &i->vfs_inode;
+}
+
+static void wrapfs_destroy_inode(struct inode *inode)
+{
+	kmem_cache_free(wrapfs_inode_cachep, WRAPFS_I(inode));
+}
+
+/* wrapfs inode cache constructor */
+static void init_once(void *obj)
+{
+	struct wrapfs_inode_info *i = obj;
+
+	inode_init_once(&i->vfs_inode);
+}
+
+int wrapfs_init_inode_cache(void)
+{
+	int err = 0;
+
+	wrapfs_inode_cachep =
+		kmem_cache_create("wrapfs_inode_cache",
+				  sizeof(struct wrapfs_inode_info), 0,
+				  SLAB_RECLAIM_ACCOUNT, init_once);
+	if (!wrapfs_inode_cachep)
+		err = -ENOMEM;
+	return err;
+}
+
+/* wrapfs inode cache destructor */
+void wrapfs_destroy_inode_cache(void)
+{
+	if (wrapfs_inode_cachep)
+		kmem_cache_destroy(wrapfs_inode_cachep);
+}
+
+/*
+ * Used only in nfs, to kill any pending RPC tasks, so that subsequent
+ * code can actually succeed and won't leave tasks that need handling.
+ */
+static void wrapfs_umount_begin(struct super_block *sb)
+{
+	struct super_block *lower_sb;
+
+	lower_sb = wrapfs_lower_super(sb);
+	if (lower_sb && lower_sb->s_op && lower_sb->s_op->umount_begin)
+		lower_sb->s_op->umount_begin(lower_sb);
+}
+
+const struct super_operations wrapfs_sops = {
+	.put_super	= wrapfs_put_super,
+	.statfs		= wrapfs_statfs,
+	.remount_fs	= wrapfs_remount_fs,
+	.evict_inode	= wrapfs_evict_inode,
+	.umount_begin	= wrapfs_umount_begin,
+	.show_options	= generic_show_options,
+	.alloc_inode	= wrapfs_alloc_inode,
+	.destroy_inode	= wrapfs_destroy_inode,
+	.drop_inode	= generic_delete_inode,
+};
diff --git a/fs/idmapfs/wrapfs.h b/fs/idmapfs/wrapfs.h
new file mode 100644
index 0000000..a85b07e
--- /dev/null
+++ b/fs/idmapfs/wrapfs.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1998-2011 Erez Zadok
+ * Copyright (c) 2009	   Shrikar Archak
+ * Copyright (c) 2003-2011 Stony Brook University
+ * Copyright (c) 2003-2011 The Research Foundation of SUNY
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _WRAPFS_H_
+#define _WRAPFS_H_
+
+#include <linux/dcache.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/seq_file.h>
+#include <linux/statfs.h>
+#include <linux/fs_stack.h>
+#include <linux/magic.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+/* the file system name */
+#define WRAPFS_NAME "idmapfs"
+
+/* wrapfs root inode number */
+#define WRAPFS_ROOT_INO     1
+
+/* useful for tracking code reachability */
+#define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
+
+/* operations vectors defined in specific files */
+extern const struct file_operations wrapfs_main_fops;
+extern const struct file_operations wrapfs_dir_fops;
+extern const struct inode_operations wrapfs_main_iops;
+extern const struct inode_operations wrapfs_dir_iops;
+extern const struct inode_operations wrapfs_symlink_iops;
+extern const struct super_operations wrapfs_sops;
+extern const struct dentry_operations wrapfs_dops;
+extern const struct address_space_operations wrapfs_aops, wrapfs_dummy_aops;
+extern const struct vm_operations_struct wrapfs_vm_ops;
+
+extern int wrapfs_init_inode_cache(void);
+extern void wrapfs_destroy_inode_cache(void);
+extern int wrapfs_init_dentry_cache(void);
+extern void wrapfs_destroy_dentry_cache(void);
+extern int new_dentry_private_data(struct dentry *dentry);
+extern void free_dentry_private_data(struct dentry *dentry);
+extern int init_lower_nd(struct nameidata *nd, unsigned int flags);
+extern struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry,
+				    unsigned int flags);
+extern struct inode *wrapfs_iget(struct super_block *sb,
+				 struct inode *lower_inode);
+extern int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
+			    struct path *lower_path);
+
+/* file private data */
+struct wrapfs_file_info {
+	struct file *lower_file;
+	const struct vm_operations_struct *lower_vm_ops;
+};
+
+/* wrapfs inode data in memory */
+struct wrapfs_inode_info {
+	struct inode *lower_inode;
+	struct inode vfs_inode;
+};
+
+/* wrapfs dentry data in memory */
+struct wrapfs_dentry_info {
+	spinlock_t lock;	/* protects lower_path */
+	struct path lower_path;
+};
+
+/* wrapfs super-block data in memory */
+struct wrapfs_sb_info {
+	struct super_block *lower_sb;
+};
+
+/*
+ * inode to private data
+ *
+ * Since we use containers and the struct inode is _inside_ the
+ * wrapfs_inode_info structure, WRAPFS_I will always (given a non-NULL
+ * inode pointer), return a valid non-NULL pointer.
+ */
+static inline struct wrapfs_inode_info *WRAPFS_I(const struct inode *inode)
+{
+	return container_of(inode, struct wrapfs_inode_info, vfs_inode);
+}
+
+/* dentry to private data */
+#define WRAPFS_D(dent) ((struct wrapfs_dentry_info *)(dent)->d_fsdata)
+
+/* superblock to private data */
+#define WRAPFS_SB(super) ((struct wrapfs_sb_info *)(super)->s_fs_info)
+
+/* file to private Data */
+#define WRAPFS_F(file) ((struct wrapfs_file_info *)((file)->private_data))
+
+/* file to lower file */
+static inline struct file *wrapfs_lower_file(const struct file *f)
+{
+	return WRAPFS_F(f)->lower_file;
+}
+
+static inline void wrapfs_set_lower_file(struct file *f, struct file *val)
+{
+	WRAPFS_F(f)->lower_file = val;
+}
+
+/* inode to lower inode. */
+static inline struct inode *wrapfs_lower_inode(const struct inode *i)
+{
+	return WRAPFS_I(i)->lower_inode;
+}
+
+static inline void wrapfs_set_lower_inode(struct inode *i, struct inode *val)
+{
+	WRAPFS_I(i)->lower_inode = val;
+}
+
+/* superblock to lower superblock */
+static inline struct super_block *wrapfs_lower_super(
+	const struct super_block *sb)
+{
+	return WRAPFS_SB(sb)->lower_sb;
+}
+
+static inline void wrapfs_set_lower_super(struct super_block *sb,
+					  struct super_block *val)
+{
+	WRAPFS_SB(sb)->lower_sb = val;
+}
+
+/* path based (dentry/mnt) macros */
+static inline void pathcpy(struct path *dst, const struct path *src)
+{
+	dst->dentry = src->dentry;
+	dst->mnt = src->mnt;
+}
+/* Returns struct path.  Caller must path_put it. */
+static inline void wrapfs_get_lower_path(const struct dentry *dent,
+					 struct path *lower_path)
+{
+	spin_lock(&WRAPFS_D(dent)->lock);
+	pathcpy(lower_path, &WRAPFS_D(dent)->lower_path);
+	path_get(lower_path);
+	spin_unlock(&WRAPFS_D(dent)->lock);
+	return;
+}
+static inline void wrapfs_put_lower_path(const struct dentry *dent,
+					 struct path *lower_path)
+{
+	path_put(lower_path);
+	return;
+}
+static inline void wrapfs_set_lower_path(const struct dentry *dent,
+					 struct path *lower_path)
+{
+	spin_lock(&WRAPFS_D(dent)->lock);
+	pathcpy(&WRAPFS_D(dent)->lower_path, lower_path);
+	spin_unlock(&WRAPFS_D(dent)->lock);
+	return;
+}
+static inline void wrapfs_reset_lower_path(const struct dentry *dent)
+{
+	spin_lock(&WRAPFS_D(dent)->lock);
+	WRAPFS_D(dent)->lower_path.dentry = NULL;
+	WRAPFS_D(dent)->lower_path.mnt = NULL;
+	spin_unlock(&WRAPFS_D(dent)->lock);
+	return;
+}
+static inline void wrapfs_put_reset_lower_path(const struct dentry *dent)
+{
+	struct path lower_path;
+	spin_lock(&WRAPFS_D(dent)->lock);
+	pathcpy(&lower_path, &WRAPFS_D(dent)->lower_path);
+	WRAPFS_D(dent)->lower_path.dentry = NULL;
+	WRAPFS_D(dent)->lower_path.mnt = NULL;
+	spin_unlock(&WRAPFS_D(dent)->lock);
+	path_put(&lower_path);
+	return;
+}
+
+/* locking helpers */
+static inline struct dentry *lock_parent(struct dentry *dentry)
+{
+	struct dentry *dir = dget_parent(dentry);
+	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
+	return dir;
+}
+
+static inline void unlock_dir(struct dentry *dir)
+{
+	mutex_unlock(&dir->d_inode->i_mutex);
+	dput(dir);
+}
+#endif	/* not _WRAPFS_H_ */
diff --git a/fs/wrapfs/Kconfig b/fs/wrapfs/Kconfig
deleted file mode 100644
index a495c7d..0000000
--- a/fs/wrapfs/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-config WRAP_FS
-	tristate "Wrapfs stackable file system (EXPERIMENTAL)"
-	help
-	  Wrapfs is a stackable file system which simply passes its
-	  operations to the lower layer.  It is designed as a useful
-	  template for developing or debugging other stackable file systems,
-	  and more (see Documentation/filesystems/wrapfs.txt).  See
-	  <http://wrapfs.filesystems.org/> for details.
diff --git a/fs/wrapfs/Makefile b/fs/wrapfs/Makefile
deleted file mode 100644
index f318d11..0000000
--- a/fs/wrapfs/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-WRAPFS_VERSION="0.1"
-
-EXTRA_CFLAGS += -DWRAPFS_VERSION=\"$(WRAPFS_VERSION)\"
-
-obj-$(CONFIG_WRAP_FS) += wrapfs.o
-
-wrapfs-y := dentry.o file.o inode.o main.o super.o lookup.o mmap.o
diff --git a/fs/wrapfs/dentry.c b/fs/wrapfs/dentry.c
deleted file mode 100644
index ed1a0cb..0000000
--- a/fs/wrapfs/dentry.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "wrapfs.h"
-
-/*
- * returns: -ERRNO if error (returned to user)
- *          0: tell VFS to invalidate dentry
- *          1: dentry is valid
- */
-static int wrapfs_d_revalidate(struct dentry *dentry, unsigned int flags)
-{
-	struct path lower_path;
-	struct dentry *lower_dentry;
-	int err = 1;
-
-	if (flags & LOOKUP_RCU)
-		return -ECHILD;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
-		goto out;
-	err = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
-out:
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-static void wrapfs_d_release(struct dentry *dentry)
-{
-	/* release and reset the lower paths */
-	wrapfs_put_reset_lower_path(dentry);
-	free_dentry_private_data(dentry);
-	return;
-}
-
-const struct dentry_operations wrapfs_dops = {
-	.d_revalidate	= wrapfs_d_revalidate,
-	.d_release	= wrapfs_d_release,
-};
diff --git a/fs/wrapfs/file.c b/fs/wrapfs/file.c
deleted file mode 100644
index 9825816..0000000
--- a/fs/wrapfs/file.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "wrapfs.h"
-
-static ssize_t wrapfs_read(struct file *file, char __user *buf,
-			   size_t count, loff_t *ppos)
-{
-	int err;
-	struct file *lower_file;
-	struct dentry *dentry = file->f_path.dentry;
-
-	lower_file = wrapfs_lower_file(file);
-	err = vfs_read(lower_file, buf, count, ppos);
-	/* update our inode atime upon a successful lower read */
-	if (err >= 0)
-		fsstack_copy_attr_atime(dentry->d_inode,
-					lower_file->f_path.dentry->d_inode);
-
-	return err;
-}
-
-static ssize_t wrapfs_write(struct file *file, const char __user *buf,
-			    size_t count, loff_t *ppos)
-{
-	int err = 0;
-	struct file *lower_file;
-	struct dentry *dentry = file->f_path.dentry;
-
-	lower_file = wrapfs_lower_file(file);
-	err = vfs_write(lower_file, buf, count, ppos);
-	/* update our inode times+sizes upon a successful lower write */
-	if (err >= 0) {
-		fsstack_copy_inode_size(dentry->d_inode,
-					lower_file->f_path.dentry->d_inode);
-		fsstack_copy_attr_times(dentry->d_inode,
-					lower_file->f_path.dentry->d_inode);
-	}
-
-	return err;
-}
-
-static int wrapfs_readdir(struct file *file, void *dirent, filldir_t filldir)
-{
-	int err = 0;
-	struct file *lower_file = NULL;
-	struct dentry *dentry = file->f_path.dentry;
-
-	lower_file = wrapfs_lower_file(file);
-	err = vfs_readdir(lower_file, filldir, dirent);
-	file->f_pos = lower_file->f_pos;
-	if (err >= 0)		/* copy the atime */
-		fsstack_copy_attr_atime(dentry->d_inode,
-					lower_file->f_path.dentry->d_inode);
-	return err;
-}
-
-static long wrapfs_unlocked_ioctl(struct file *file, unsigned int cmd,
-				  unsigned long arg)
-{
-	long err = -ENOTTY;
-	struct file *lower_file;
-
-	lower_file = wrapfs_lower_file(file);
-
-	/* XXX: use vfs_ioctl if/when VFS exports it */
-	if (!lower_file || !lower_file->f_op)
-		goto out;
-	if (lower_file->f_op->unlocked_ioctl)
-		err = lower_file->f_op->unlocked_ioctl(lower_file, cmd, arg);
-
-	/* some ioctls can change inode attributes (EXT2_IOC_SETFLAGS) */
-	if (!err)
-		fsstack_copy_attr_all(file->f_path.dentry->d_inode,
-				      lower_file->f_path.dentry->d_inode);
-out:
-	return err;
-}
-
-#ifdef CONFIG_COMPAT
-static long wrapfs_compat_ioctl(struct file *file, unsigned int cmd,
-				unsigned long arg)
-{
-	long err = -ENOTTY;
-	struct file *lower_file;
-
-	lower_file = wrapfs_lower_file(file);
-
-	/* XXX: use vfs_ioctl if/when VFS exports it */
-	if (!lower_file || !lower_file->f_op)
-		goto out;
-	if (lower_file->f_op->compat_ioctl)
-		err = lower_file->f_op->compat_ioctl(lower_file, cmd, arg);
-
-out:
-	return err;
-}
-#endif
-
-static int wrapfs_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	int err = 0;
-	bool willwrite;
-	struct file *lower_file;
-	const struct vm_operations_struct *saved_vm_ops = NULL;
-
-	/* this might be deferred to mmap's writepage */
-	willwrite = ((vma->vm_flags | VM_SHARED | VM_WRITE) == vma->vm_flags);
-
-	/*
-	 * File systems which do not implement ->writepage may use
-	 * generic_file_readonly_mmap as their ->mmap op.  If you call
-	 * generic_file_readonly_mmap with VM_WRITE, you'd get an -EINVAL.
-	 * But we cannot call the lower ->mmap op, so we can't tell that
-	 * writeable mappings won't work.  Therefore, our only choice is to
-	 * check if the lower file system supports the ->writepage, and if
-	 * not, return EINVAL (the same error that
-	 * generic_file_readonly_mmap returns in that case).
-	 */
-	lower_file = wrapfs_lower_file(file);
-	if (willwrite && !lower_file->f_mapping->a_ops->writepage) {
-		err = -EINVAL;
-		printk(KERN_ERR "wrapfs: lower file system does not "
-		       "support writeable mmap\n");
-		goto out;
-	}
-
-	/*
-	 * find and save lower vm_ops.
-	 *
-	 * XXX: the VFS should have a cleaner way of finding the lower vm_ops
-	 */
-	if (!WRAPFS_F(file)->lower_vm_ops) {
-		err = lower_file->f_op->mmap(lower_file, vma);
-		if (err) {
-			printk(KERN_ERR "wrapfs: lower mmap failed %d\n", err);
-			goto out;
-		}
-		saved_vm_ops = vma->vm_ops; /* save: came from lower ->mmap */
-	}
-
-	/*
-	 * Next 3 lines are all I need from generic_file_mmap.  I definitely
-	 * don't want its test for ->readpage which returns -ENOEXEC.
-	 */
-	file_accessed(file);
-	vma->vm_ops = &wrapfs_vm_ops;
-
-	file->f_mapping->a_ops = &wrapfs_aops; /* set our aops */
-	if (!WRAPFS_F(file)->lower_vm_ops) /* save for our ->fault */
-		WRAPFS_F(file)->lower_vm_ops = saved_vm_ops;
-
-out:
-	return err;
-}
-
-static int wrapfs_open(struct inode *inode, struct file *file)
-{
-	int err = 0;
-	struct file *lower_file = NULL;
-	struct path lower_path;
-
-	/* don't open unhashed/deleted files */
-	if (d_unhashed(file->f_path.dentry)) {
-		err = -ENOENT;
-		goto out_err;
-	}
-
-	file->private_data =
-		kzalloc(sizeof(struct wrapfs_file_info), GFP_KERNEL);
-	if (!WRAPFS_F(file)) {
-		err = -ENOMEM;
-		goto out_err;
-	}
-
-	/* open lower object and link wrapfs's file struct to lower's */
-	wrapfs_get_lower_path(file->f_path.dentry, &lower_path);
-	lower_file = dentry_open(&lower_path, file->f_flags, current_cred());
-	path_put(&lower_path);
-	if (IS_ERR(lower_file)) {
-		err = PTR_ERR(lower_file);
-		lower_file = wrapfs_lower_file(file);
-		if (lower_file) {
-			wrapfs_set_lower_file(file, NULL);
-			fput(lower_file); /* fput calls dput for lower_dentry */
-		}
-	} else {
-		wrapfs_set_lower_file(file, lower_file);
-	}
-
-	if (err)
-		kfree(WRAPFS_F(file));
-	else
-		fsstack_copy_attr_all(inode, wrapfs_lower_inode(inode));
-out_err:
-	return err;
-}
-
-static int wrapfs_flush(struct file *file, fl_owner_t id)
-{
-	int err = 0;
-	struct file *lower_file = NULL;
-
-	lower_file = wrapfs_lower_file(file);
-	if (lower_file && lower_file->f_op && lower_file->f_op->flush)
-		err = lower_file->f_op->flush(lower_file, id);
-
-	return err;
-}
-
-/* release all lower object references & free the file info structure */
-static int wrapfs_file_release(struct inode *inode, struct file *file)
-{
-	struct file *lower_file;
-
-	lower_file = wrapfs_lower_file(file);
-	if (lower_file) {
-		wrapfs_set_lower_file(file, NULL);
-		fput(lower_file);
-	}
-
-	kfree(WRAPFS_F(file));
-	return 0;
-}
-
-static int wrapfs_fsync(struct file *file, loff_t start, loff_t end,
-			int datasync)
-{
-	int err;
-	struct file *lower_file;
-	struct path lower_path;
-	struct dentry *dentry = file->f_path.dentry;
-
-	err = generic_file_fsync(file, start, end, datasync);
-	if (err)
-		goto out;
-	lower_file = wrapfs_lower_file(file);
-	wrapfs_get_lower_path(dentry, &lower_path);
-	err = vfs_fsync_range(lower_file, start, end, datasync);
-	wrapfs_put_lower_path(dentry, &lower_path);
-out:
-	return err;
-}
-
-static int wrapfs_fasync(int fd, struct file *file, int flag)
-{
-	int err = 0;
-	struct file *lower_file = NULL;
-
-	lower_file = wrapfs_lower_file(file);
-	if (lower_file->f_op && lower_file->f_op->fasync)
-		err = lower_file->f_op->fasync(fd, lower_file, flag);
-
-	return err;
-}
-
-const struct file_operations wrapfs_main_fops = {
-	.llseek		= generic_file_llseek,
-	.read		= wrapfs_read,
-	.write		= wrapfs_write,
-	.unlocked_ioctl	= wrapfs_unlocked_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= wrapfs_compat_ioctl,
-#endif
-	.mmap		= wrapfs_mmap,
-	.open		= wrapfs_open,
-	.flush		= wrapfs_flush,
-	.release	= wrapfs_file_release,
-	.fsync		= wrapfs_fsync,
-	.fasync		= wrapfs_fasync,
-};
-
-/* trimmed directory options */
-const struct file_operations wrapfs_dir_fops = {
-	.llseek		= generic_file_llseek,
-	.read		= generic_read_dir,
-	.readdir	= wrapfs_readdir,
-	.unlocked_ioctl	= wrapfs_unlocked_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= wrapfs_compat_ioctl,
-#endif
-	.open		= wrapfs_open,
-	.release	= wrapfs_file_release,
-	.flush		= wrapfs_flush,
-	.fsync		= wrapfs_fsync,
-	.fasync		= wrapfs_fasync,
-};
diff --git a/fs/wrapfs/inode.c b/fs/wrapfs/inode.c
deleted file mode 100644
index d7fe145..0000000
--- a/fs/wrapfs/inode.c
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "wrapfs.h"
-
-static int wrapfs_create(struct inode *dir, struct dentry *dentry,
-			 umode_t mode, bool want_excl)
-{
-	int err = 0;
-	struct dentry *lower_dentry;
-	struct dentry *lower_parent_dentry = NULL;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_parent_dentry = lock_parent(lower_dentry);
-
-	err = vfs_create(lower_parent_dentry->d_inode, lower_dentry, mode,
-			 want_excl);
-	if (err)
-		goto out;
-	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
-	if (err)
-		goto out;
-	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
-	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
-
-out:
-	unlock_dir(lower_parent_dentry);
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-static int wrapfs_link(struct dentry *old_dentry, struct inode *dir,
-		       struct dentry *new_dentry)
-{
-	struct dentry *lower_old_dentry;
-	struct dentry *lower_new_dentry;
-	struct dentry *lower_dir_dentry;
-	u64 file_size_save;
-	int err;
-	struct path lower_old_path, lower_new_path;
-
-	file_size_save = i_size_read(old_dentry->d_inode);
-	wrapfs_get_lower_path(old_dentry, &lower_old_path);
-	wrapfs_get_lower_path(new_dentry, &lower_new_path);
-	lower_old_dentry = lower_old_path.dentry;
-	lower_new_dentry = lower_new_path.dentry;
-	lower_dir_dentry = lock_parent(lower_new_dentry);
-
-	err = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
-		       lower_new_dentry);
-	if (err || !lower_new_dentry->d_inode)
-		goto out;
-
-	err = wrapfs_interpose(new_dentry, dir->i_sb, &lower_new_path);
-	if (err)
-		goto out;
-	fsstack_copy_attr_times(dir, lower_new_dentry->d_inode);
-	fsstack_copy_inode_size(dir, lower_new_dentry->d_inode);
-	set_nlink(old_dentry->d_inode,
-		  wrapfs_lower_inode(old_dentry->d_inode)->i_nlink);
-	i_size_write(new_dentry->d_inode, file_size_save);
-out:
-	unlock_dir(lower_dir_dentry);
-	wrapfs_put_lower_path(old_dentry, &lower_old_path);
-	wrapfs_put_lower_path(new_dentry, &lower_new_path);
-	return err;
-}
-
-static int wrapfs_unlink(struct inode *dir, struct dentry *dentry)
-{
-	int err;
-	struct dentry *lower_dentry;
-	struct inode *lower_dir_inode = wrapfs_lower_inode(dir);
-	struct dentry *lower_dir_dentry;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	dget(lower_dentry);
-	lower_dir_dentry = lock_parent(lower_dentry);
-
-	err = vfs_unlink(lower_dir_inode, lower_dentry);
-
-	/*
-	 * Note: unlinking on top of NFS can cause silly-renamed files.
-	 * Trying to delete such files results in EBUSY from NFS
-	 * below.  Silly-renamed files will get deleted by NFS later on, so
-	 * we just need to detect them here and treat such EBUSY errors as
-	 * if the upper file was successfully deleted.
-	 */
-	if (err == -EBUSY && lower_dentry->d_flags & DCACHE_NFSFS_RENAMED)
-		err = 0;
-	if (err)
-		goto out;
-	fsstack_copy_attr_times(dir, lower_dir_inode);
-	fsstack_copy_inode_size(dir, lower_dir_inode);
-	set_nlink(dentry->d_inode,
-		  wrapfs_lower_inode(dentry->d_inode)->i_nlink);
-	dentry->d_inode->i_ctime = dir->i_ctime;
-	d_drop(dentry); /* this is needed, else LTP fails (VFS won't do it) */
-out:
-	unlock_dir(lower_dir_dentry);
-	dput(lower_dentry);
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-static int wrapfs_symlink(struct inode *dir, struct dentry *dentry,
-			  const char *symname)
-{
-	int err = 0;
-	struct dentry *lower_dentry;
-	struct dentry *lower_parent_dentry = NULL;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_parent_dentry = lock_parent(lower_dentry);
-
-	err = vfs_symlink(lower_parent_dentry->d_inode, lower_dentry, symname);
-	if (err)
-		goto out;
-	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
-	if (err)
-		goto out;
-	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
-	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
-
-out:
-	unlock_dir(lower_parent_dentry);
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-static int wrapfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
-{
-	int err = 0;
-	struct dentry *lower_dentry;
-	struct dentry *lower_parent_dentry = NULL;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_parent_dentry = lock_parent(lower_dentry);
-
-	err = vfs_mkdir(lower_parent_dentry->d_inode, lower_dentry, mode);
-	if (err)
-		goto out;
-
-	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
-	if (err)
-		goto out;
-
-	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
-	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
-	/* update number of links on parent directory */
-	set_nlink(dir, wrapfs_lower_inode(dir)->i_nlink);
-
-out:
-	unlock_dir(lower_parent_dentry);
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-static int wrapfs_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	struct dentry *lower_dentry;
-	struct dentry *lower_dir_dentry;
-	int err;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_dir_dentry = lock_parent(lower_dentry);
-
-	err = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
-	if (err)
-		goto out;
-
-	d_drop(dentry);	/* drop our dentry on success (why not VFS's job?) */
-	if (dentry->d_inode)
-		clear_nlink(dentry->d_inode);
-	fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
-	fsstack_copy_inode_size(dir, lower_dir_dentry->d_inode);
-	set_nlink(dir, lower_dir_dentry->d_inode->i_nlink);
-
-out:
-	unlock_dir(lower_dir_dentry);
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-static int wrapfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
-			dev_t dev)
-{
-	int err = 0;
-	struct dentry *lower_dentry;
-	struct dentry *lower_parent_dentry = NULL;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_parent_dentry = lock_parent(lower_dentry);
-
-	err = vfs_mknod(lower_parent_dentry->d_inode, lower_dentry, mode, dev);
-	if (err)
-		goto out;
-
-	err = wrapfs_interpose(dentry, dir->i_sb, &lower_path);
-	if (err)
-		goto out;
-	fsstack_copy_attr_times(dir, wrapfs_lower_inode(dir));
-	fsstack_copy_inode_size(dir, lower_parent_dentry->d_inode);
-
-out:
-	unlock_dir(lower_parent_dentry);
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-/*
- * The locking rules in wrapfs_rename are complex.  We could use a simpler
- * superblock-level name-space lock for renames and copy-ups.
- */
-static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
-			 struct inode *new_dir, struct dentry *new_dentry)
-{
-	int err = 0;
-	struct dentry *lower_old_dentry = NULL;
-	struct dentry *lower_new_dentry = NULL;
-	struct dentry *lower_old_dir_dentry = NULL;
-	struct dentry *lower_new_dir_dentry = NULL;
-	struct dentry *trap = NULL;
-	struct path lower_old_path, lower_new_path;
-
-	wrapfs_get_lower_path(old_dentry, &lower_old_path);
-	wrapfs_get_lower_path(new_dentry, &lower_new_path);
-	lower_old_dentry = lower_old_path.dentry;
-	lower_new_dentry = lower_new_path.dentry;
-	lower_old_dir_dentry = dget_parent(lower_old_dentry);
-	lower_new_dir_dentry = dget_parent(lower_new_dentry);
-
-	trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-	/* source should not be ancestor of target */
-	if (trap == lower_old_dentry) {
-		err = -EINVAL;
-		goto out;
-	}
-	/* target should not be ancestor of source */
-	if (trap == lower_new_dentry) {
-		err = -ENOTEMPTY;
-		goto out;
-	}
-
-	err = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
-			 lower_new_dir_dentry->d_inode, lower_new_dentry);
-	if (err)
-		goto out;
-
-	fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
-	fsstack_copy_inode_size(new_dir, lower_new_dir_dentry->d_inode);
-	if (new_dir != old_dir) {
-		fsstack_copy_attr_all(old_dir,
-				      lower_old_dir_dentry->d_inode);
-		fsstack_copy_inode_size(old_dir,
-					lower_old_dir_dentry->d_inode);
-	}
-
-out:
-	unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-	dput(lower_old_dir_dentry);
-	dput(lower_new_dir_dentry);
-	wrapfs_put_lower_path(old_dentry, &lower_old_path);
-	wrapfs_put_lower_path(new_dentry, &lower_new_path);
-	return err;
-}
-
-static int wrapfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
-{
-	int err;
-	struct dentry *lower_dentry;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	if (!lower_dentry->d_inode->i_op ||
-	    !lower_dentry->d_inode->i_op->readlink) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	err = lower_dentry->d_inode->i_op->readlink(lower_dentry,
-						    buf, bufsiz);
-	if (err < 0)
-		goto out;
-	fsstack_copy_attr_atime(dentry->d_inode, lower_dentry->d_inode);
-
-out:
-	wrapfs_put_lower_path(dentry, &lower_path);
-	return err;
-}
-
-static void *wrapfs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	char *buf;
-	int len = PAGE_SIZE, err;
-	mm_segment_t old_fs;
-
-	/* This is freed by the put_link method assuming a successful call. */
-	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf) {
-		buf = ERR_PTR(-ENOMEM);
-		goto out;
-	}
-
-	/* read the symlink, and then we will follow it */
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = wrapfs_readlink(dentry, buf, len);
-	set_fs(old_fs);
-	if (err < 0) {
-		kfree(buf);
-		buf = ERR_PTR(err);
-	} else {
-		buf[err] = '\0';
-	}
-out:
-	nd_set_link(nd, buf);
-	return NULL;
-}
-
-/* this @nd *IS* still used */
-static void wrapfs_put_link(struct dentry *dentry, struct nameidata *nd,
-			    void *cookie)
-{
-	char *buf = nd_get_link(nd);
-	if (!IS_ERR(buf))	/* free the char* */
-		kfree(buf);
-}
-
-static int wrapfs_permission(struct inode *inode, int mask)
-{
-	struct inode *lower_inode;
-	int err;
-
-	lower_inode = wrapfs_lower_inode(inode);
-	err = inode_permission(lower_inode, mask);
-	return err;
-}
-
-static int wrapfs_setattr(struct dentry *dentry, struct iattr *ia)
-{
-	int err = 0;
-	struct dentry *lower_dentry;
-	struct inode *inode;
-	struct inode *lower_inode;
-	struct path lower_path;
-	struct iattr lower_ia;
-
-	inode = dentry->d_inode;
-
-	/*
-	 * Check if user has permission to change inode.  We don't check if
-	 * this user can change the lower inode: that should happen when
-	 * calling notify_change on the lower inode.
-	 */
-	err = inode_change_ok(inode, ia);
-	if (err)
-		goto out_err;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	lower_dentry = lower_path.dentry;
-	lower_inode = wrapfs_lower_inode(inode);
-
-	/* prepare our own lower struct iattr (with the lower file) */
-	memcpy(&lower_ia, ia, sizeof(lower_ia));
-	if (ia->ia_valid & ATTR_FILE)
-		lower_ia.ia_file = wrapfs_lower_file(ia->ia_file);
-
-	/*
-	 * If shrinking, first truncate upper level to cancel writing dirty
-	 * pages beyond the new eof; and also if its' maxbytes is more
-	 * limiting (fail with -EFBIG before making any change to the lower
-	 * level).  There is no need to vmtruncate the upper level
-	 * afterwards in the other cases: we fsstack_copy_inode_size from
-	 * the lower level.
-	 */
-	if (ia->ia_valid & ATTR_SIZE) {
-		err = inode_newsize_ok(inode, ia->ia_size);
-		if (err)
-			goto out;
-		truncate_setsize(inode, ia->ia_size);
-	}
-
-	/*
-	 * mode change is for clearing setuid/setgid bits. Allow lower fs
-	 * to interpret this in its own way.
-	 */
-	if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
-		lower_ia.ia_valid &= ~ATTR_MODE;
-
-	/* notify the (possibly copied-up) lower inode */
-	/*
-	 * Note: we use lower_dentry->d_inode, because lower_inode may be
-	 * unlinked (no inode->i_sb and i_ino==0.  This happens if someone
-	 * tries to open(), unlink(), then ftruncate() a file.
-	 */
-	mutex_lock(&lower_dentry->d_inode->i_mutex);
-	err = notify_change(lower_dentry, &lower_ia); /* note: lower_ia */
-	mutex_unlock(&lower_dentry->d_inode->i_mutex);
-	if (err)
-		goto out;
-
-	/* get attributes from the lower inode */
-	fsstack_copy_attr_all(inode, lower_inode);
-	/*
-	 * Not running fsstack_copy_inode_size(inode, lower_inode), because
-	 * VFS should update our inode size, and notify_change on
-	 * lower_inode should update its size.
-	 */
-
-out:
-	wrapfs_put_lower_path(dentry, &lower_path);
-out_err:
-	return err;
-}
-
-const struct inode_operations wrapfs_symlink_iops = {
-	.readlink	= wrapfs_readlink,
-	.permission	= wrapfs_permission,
-	.follow_link	= wrapfs_follow_link,
-	.setattr	= wrapfs_setattr,
-	.put_link	= wrapfs_put_link,
-};
-
-const struct inode_operations wrapfs_dir_iops = {
-	.create		= wrapfs_create,
-	.lookup		= wrapfs_lookup,
-	.link		= wrapfs_link,
-	.unlink		= wrapfs_unlink,
-	.symlink	= wrapfs_symlink,
-	.mkdir		= wrapfs_mkdir,
-	.rmdir		= wrapfs_rmdir,
-	.mknod		= wrapfs_mknod,
-	.rename		= wrapfs_rename,
-	.permission	= wrapfs_permission,
-	.setattr	= wrapfs_setattr,
-};
-
-const struct inode_operations wrapfs_main_iops = {
-	.permission	= wrapfs_permission,
-	.setattr	= wrapfs_setattr,
-};
diff --git a/fs/wrapfs/lookup.c b/fs/wrapfs/lookup.c
deleted file mode 100644
index fa6e019..0000000
--- a/fs/wrapfs/lookup.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "wrapfs.h"
-
-/* The dentry cache is just so we have properly sized dentries */
-static struct kmem_cache *wrapfs_dentry_cachep;
-
-int wrapfs_init_dentry_cache(void)
-{
-	wrapfs_dentry_cachep =
-		kmem_cache_create("wrapfs_dentry",
-				  sizeof(struct wrapfs_dentry_info),
-				  0, SLAB_RECLAIM_ACCOUNT, NULL);
-
-	return wrapfs_dentry_cachep ? 0 : -ENOMEM;
-}
-
-void wrapfs_destroy_dentry_cache(void)
-{
-	if (wrapfs_dentry_cachep)
-		kmem_cache_destroy(wrapfs_dentry_cachep);
-}
-
-void free_dentry_private_data(struct dentry *dentry)
-{
-	if (!dentry || !dentry->d_fsdata)
-		return;
-	kmem_cache_free(wrapfs_dentry_cachep, dentry->d_fsdata);
-	dentry->d_fsdata = NULL;
-}
-
-/* allocate new dentry private data */
-int new_dentry_private_data(struct dentry *dentry)
-{
-	struct wrapfs_dentry_info *info = WRAPFS_D(dentry);
-
-	/* use zalloc to init dentry_info.lower_path */
-	info = kmem_cache_zalloc(wrapfs_dentry_cachep, GFP_ATOMIC);
-	if (!info)
-		return -ENOMEM;
-
-	spin_lock_init(&info->lock);
-	dentry->d_fsdata = info;
-
-	return 0;
-}
-
-/*
- * Initialize a nameidata structure (the intent part) we can pass to a lower
- * file system.  Returns 0 on success or -error (only -ENOMEM possible).
- */
-int init_lower_nd(struct nameidata *nd, unsigned int flags)
-{
-	int err = 0;
-
-	memset(nd, 0, sizeof(struct nameidata));
-	if (!flags)
-		goto out;
-
-	switch (flags) {
-	case LOOKUP_CREATE:
-	case LOOKUP_OPEN:
-		nd->flags = flags;
-		break;
-	default:
-		/* We should never get here, for now */
-		pr_debug("wrapfs: unknown nameidata flag 0x%x\n", flags);
-		BUG();
-		break;
-	}
-
-out:
-	return err;
-}
-
-static int wrapfs_inode_test(struct inode *inode, void *candidate_lower_inode)
-{
-	struct inode *current_lower_inode = wrapfs_lower_inode(inode);
-	if (current_lower_inode == (struct inode *)candidate_lower_inode)
-		return 1; /* found a match */
-	else
-		return 0; /* no match */
-}
-
-static int wrapfs_inode_set(struct inode *inode, void *lower_inode)
-{
-	/* we do actual inode initialization in wrapfs_iget */
-	return 0;
-}
-
-struct inode *wrapfs_iget(struct super_block *sb, struct inode *lower_inode)
-{
-	struct wrapfs_inode_info *info;
-	struct inode *inode; /* the new inode to return */
-	int err;
-
-	inode = iget5_locked(sb, /* our superblock */
-			     /*
-			      * hashval: we use inode number, but we can
-			      * also use "(unsigned long)lower_inode"
-			      * instead.
-			      */
-			     lower_inode->i_ino, /* hashval */
-			     wrapfs_inode_test,	/* inode comparison function */
-			     wrapfs_inode_set, /* inode init function */
-			     lower_inode); /* data passed to test+set fxns */
-	if (!inode) {
-		err = -EACCES;
-		iput(lower_inode);
-		return ERR_PTR(err);
-	}
-	/* if found a cached inode, then just return it */
-	if (!(inode->i_state & I_NEW))
-		return inode;
-
-	/* initialize new inode */
-	info = WRAPFS_I(inode);
-
-	inode->i_ino = lower_inode->i_ino;
-	if (!igrab(lower_inode)) {
-		err = -ESTALE;
-		return ERR_PTR(err);
-	}
-	wrapfs_set_lower_inode(inode, lower_inode);
-
-	inode->i_version++;
-
-	/* use different set of inode ops for symlinks & directories */
-	if (S_ISDIR(lower_inode->i_mode))
-		inode->i_op = &wrapfs_dir_iops;
-	else if (S_ISLNK(lower_inode->i_mode))
-		inode->i_op = &wrapfs_symlink_iops;
-	else
-		inode->i_op = &wrapfs_main_iops;
-
-	/* use different set of file ops for directories */
-	if (S_ISDIR(lower_inode->i_mode))
-		inode->i_fop = &wrapfs_dir_fops;
-	else
-		inode->i_fop = &wrapfs_main_fops;
-
-	inode->i_mapping->a_ops = &wrapfs_aops;
-
-	inode->i_atime.tv_sec = 0;
-	inode->i_atime.tv_nsec = 0;
-	inode->i_mtime.tv_sec = 0;
-	inode->i_mtime.tv_nsec = 0;
-	inode->i_ctime.tv_sec = 0;
-	inode->i_ctime.tv_nsec = 0;
-
-	/* properly initialize special inodes */
-	if (S_ISBLK(lower_inode->i_mode) || S_ISCHR(lower_inode->i_mode) ||
-	    S_ISFIFO(lower_inode->i_mode) || S_ISSOCK(lower_inode->i_mode))
-		init_special_inode(inode, lower_inode->i_mode,
-				   lower_inode->i_rdev);
-
-	/* all well, copy inode attributes */
-	fsstack_copy_attr_all(inode, lower_inode);
-	fsstack_copy_inode_size(inode, lower_inode);
-
-	unlock_new_inode(inode);
-	return inode;
-}
-
-/*
- * Connect a wrapfs inode dentry/inode with several lower ones.  This is
- * the classic stackable file system "vnode interposition" action.
- *
- * @dentry: wrapfs's dentry which interposes on lower one
- * @sb: wrapfs's super_block
- * @lower_path: the lower path (caller does path_get/put)
- */
-int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
-		     struct path *lower_path)
-{
-	int err = 0;
-	struct inode *inode;
-	struct inode *lower_inode;
-	struct super_block *lower_sb;
-
-	lower_inode = lower_path->dentry->d_inode;
-	lower_sb = wrapfs_lower_super(sb);
-
-	/* check that the lower file system didn't cross a mount point */
-	if (lower_inode->i_sb != lower_sb) {
-		err = -EXDEV;
-		goto out;
-	}
-
-	/*
-	 * We allocate our new inode below by calling wrapfs_iget,
-	 * which will initialize some of the new inode's fields
-	 */
-
-	/* inherit lower inode number for wrapfs's inode */
-	inode = wrapfs_iget(sb, lower_inode);
-	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
-		goto out;
-	}
-
-	d_add(dentry, inode);
-
-out:
-	return err;
-}
-
-/*
- * Main driver function for wrapfs's lookup.
- *
- * Returns: NULL (ok), ERR_PTR if an error occurred.
- * Fills in lower_parent_path with <dentry,mnt> on success.
- */
-static struct dentry *__wrapfs_lookup(struct dentry *dentry,
-				      unsigned int flags,
-				      struct path *lower_parent_path)
-{
-	int err = 0;
-	struct vfsmount *lower_dir_mnt;
-	struct dentry *lower_dir_dentry = NULL;
-	struct dentry *lower_dentry;
-	const char *name;
-	struct path lower_path;
-	struct qstr this;
-
-	/* must initialize dentry operations */
-	d_set_d_op(dentry, &wrapfs_dops);
-
-	if (IS_ROOT(dentry))
-		goto out;
-
-	name = dentry->d_name.name;
-
-	/* now start the actual lookup procedure */
-	lower_dir_dentry = lower_parent_path->dentry;
-	lower_dir_mnt = lower_parent_path->mnt;
-
-	/* Use vfs_path_lookup to check if the dentry exists or not */
-	err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, name, 0,
-			      &lower_path);
-
-	/* no error: handle positive dentries */
-	if (!err) {
-		wrapfs_set_lower_path(dentry, &lower_path);
-		err = wrapfs_interpose(dentry, dentry->d_sb, &lower_path);
-		if (err) /* path_put underlying path on error */
-			wrapfs_put_reset_lower_path(dentry);
-		goto out;
-	}
-
-	/*
-	 * We don't consider ENOENT an error, and we want to return a
-	 * negative dentry.
-	 */
-	if (err && err != -ENOENT)
-		goto out;
-
-	/* instatiate a new negative dentry */
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = full_name_hash(this.name, this.len);
-	lower_dentry = d_lookup(lower_dir_dentry, &this);
-	if (lower_dentry)
-		goto setup_lower;
-
-	lower_dentry = d_alloc(lower_dir_dentry, &this);
-	if (!lower_dentry) {
-		err = -ENOMEM;
-		goto out;
-	}
-	d_add(lower_dentry, NULL); /* instantiate and hash */
-
-setup_lower:
-	lower_path.dentry = lower_dentry;
-	lower_path.mnt = mntget(lower_dir_mnt);
-	wrapfs_set_lower_path(dentry, &lower_path);
-
-	/*
-	 * If the intent is to create a file, then don't return an error, so
-	 * the VFS will continue the process of making this negative dentry
-	 * into a positive one.
-	 */
-	if (flags & (LOOKUP_CREATE|LOOKUP_RENAME_TARGET))
-		err = 0;
-
-out:
-	return ERR_PTR(err);
-}
-
-struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry,
-			     unsigned int flags)
-{
-	struct dentry *ret, *parent;
-	struct path lower_parent_path;
-	int err = 0;
-
-	parent = dget_parent(dentry);
-
-	wrapfs_get_lower_path(parent, &lower_parent_path);
-
-	/* allocate dentry private data.  We free it in ->d_release */
-	err = new_dentry_private_data(dentry);
-	if (err) {
-		ret = ERR_PTR(err);
-		goto out;
-	}
-	ret = __wrapfs_lookup(dentry, flags, &lower_parent_path);
-	if (IS_ERR(ret))
-		goto out;
-	if (ret)
-		dentry = ret;
-	if (dentry->d_inode)
-		fsstack_copy_attr_times(dentry->d_inode,
-					wrapfs_lower_inode(dentry->d_inode));
-	/* update parent directory's atime */
-	fsstack_copy_attr_atime(parent->d_inode,
-				wrapfs_lower_inode(parent->d_inode));
-
-out:
-	wrapfs_put_lower_path(parent, &lower_parent_path);
-	dput(parent);
-	return ret;
-}
diff --git a/fs/wrapfs/main.c b/fs/wrapfs/main.c
deleted file mode 100644
index 73153fd..0000000
--- a/fs/wrapfs/main.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "wrapfs.h"
-#include <linux/module.h>
-
-/*
- * There is no need to lock the wrapfs_super_info's rwsem as there is no
- * way anyone can have a reference to the superblock at this point in time.
- */
-static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent)
-{
-	int err = 0;
-	struct super_block *lower_sb;
-	struct path lower_path;
-	char *dev_name = (char *) raw_data;
-	struct inode *inode;
-
-	if (!dev_name) {
-		printk(KERN_ERR
-		       "wrapfs: read_super: missing dev_name argument\n");
-		err = -EINVAL;
-		goto out;
-	}
-
-	/* parse lower path */
-	err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
-			&lower_path);
-	if (err) {
-		printk(KERN_ERR	"wrapfs: error accessing "
-		       "lower directory '%s'\n", dev_name);
-		goto out;
-	}
-
-	/* allocate superblock private data */
-	sb->s_fs_info = kzalloc(sizeof(struct wrapfs_sb_info), GFP_KERNEL);
-	if (!WRAPFS_SB(sb)) {
-		printk(KERN_CRIT "wrapfs: read_super: out of memory\n");
-		err = -ENOMEM;
-		goto out_free;
-	}
-
-	/* set the lower superblock field of upper superblock */
-	lower_sb = lower_path.dentry->d_sb;
-	atomic_inc(&lower_sb->s_active);
-	wrapfs_set_lower_super(sb, lower_sb);
-
-	/* inherit maxbytes from lower file system */
-	sb->s_maxbytes = lower_sb->s_maxbytes;
-
-	/*
-	 * Our c/m/atime granularity is 1 ns because we may stack on file
-	 * systems whose granularity is as good.
-	 */
-	sb->s_time_gran = 1;
-
-	sb->s_op = &wrapfs_sops;
-
-	/* get a new inode and allocate our root dentry */
-	inode = wrapfs_iget(sb, lower_path.dentry->d_inode);
-	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
-		goto out_sput;
-	}
-	sb->s_root = d_make_root(inode);
-	if (!sb->s_root) {
-		err = -ENOMEM;
-		goto out_iput;
-	}
-	d_set_d_op(sb->s_root, &wrapfs_dops);
-
-	/* link the upper and lower dentries */
-	sb->s_root->d_fsdata = NULL;
-	err = new_dentry_private_data(sb->s_root);
-	if (err)
-		goto out_freeroot;
-
-	/* if get here: cannot have error */
-
-	/* set the lower dentries for s_root */
-	wrapfs_set_lower_path(sb->s_root, &lower_path);
-
-	/*
-	 * No need to call interpose because we already have a positive
-	 * dentry, which was instantiated by d_make_root.  Just need to
-	 * d_rehash it.
-	 */
-	d_rehash(sb->s_root);
-	if (!silent)
-		printk(KERN_INFO
-		       "wrapfs: mounted on top of %s type %s\n",
-		       dev_name, lower_sb->s_type->name);
-	goto out; /* all is well */
-
-	/* no longer needed: free_dentry_private_data(sb->s_root); */
-out_freeroot:
-	dput(sb->s_root);
-out_iput:
-	iput(inode);
-out_sput:
-	/* drop refs we took earlier */
-	atomic_dec(&lower_sb->s_active);
-	kfree(WRAPFS_SB(sb));
-	sb->s_fs_info = NULL;
-out_free:
-	path_put(&lower_path);
-
-out:
-	return err;
-}
-
-struct dentry *wrapfs_mount(struct file_system_type *fs_type, int flags,
-			    const char *dev_name, void *raw_data)
-{
-	void *lower_path_name = (void *) dev_name;
-
-	return mount_nodev(fs_type, flags, lower_path_name,
-			   wrapfs_read_super);
-}
-
-static struct file_system_type wrapfs_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= WRAPFS_NAME,
-	.mount		= wrapfs_mount,
-	.kill_sb	= generic_shutdown_super,
-	.fs_flags	= 0,
-};
-MODULE_ALIAS_FS(WRAPFS_NAME);
-
-static int __init init_wrapfs_fs(void)
-{
-	int err;
-
-	pr_info("Registering wrapfs " WRAPFS_VERSION "\n");
-
-	err = wrapfs_init_inode_cache();
-	if (err)
-		goto out;
-	err = wrapfs_init_dentry_cache();
-	if (err)
-		goto out;
-	err = register_filesystem(&wrapfs_fs_type);
-out:
-	if (err) {
-		wrapfs_destroy_inode_cache();
-		wrapfs_destroy_dentry_cache();
-	}
-	return err;
-}
-
-static void __exit exit_wrapfs_fs(void)
-{
-	wrapfs_destroy_inode_cache();
-	wrapfs_destroy_dentry_cache();
-	unregister_filesystem(&wrapfs_fs_type);
-	pr_info("Completed wrapfs module unload\n");
-}
-
-MODULE_AUTHOR("Erez Zadok, Filesystems and Storage Lab, Stony Brook University"
-	      " (http://www.fsl.cs.sunysb.edu/)");
-MODULE_DESCRIPTION("Wrapfs " WRAPFS_VERSION
-		   " (http://wrapfs.filesystems.org/)");
-MODULE_LICENSE("GPL");
-
-module_init(init_wrapfs_fs);
-module_exit(exit_wrapfs_fs);
diff --git a/fs/wrapfs/mmap.c b/fs/wrapfs/mmap.c
deleted file mode 100644
index c224fc3..0000000
--- a/fs/wrapfs/mmap.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "wrapfs.h"
-
-static int wrapfs_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
-	int err;
-	struct file *file, *lower_file;
-	const struct vm_operations_struct *lower_vm_ops;
-	struct vm_area_struct lower_vma;
-
-	memcpy(&lower_vma, vma, sizeof(struct vm_area_struct));
-	file = lower_vma.vm_file;
-	lower_vm_ops = WRAPFS_F(file)->lower_vm_ops;
-	BUG_ON(!lower_vm_ops);
-
-	lower_file = wrapfs_lower_file(file);
-	/*
-	 * XXX: vm_ops->fault may be called in parallel.  Because we have to
-	 * resort to temporarily changing the vma->vm_file to point to the
-	 * lower file, a concurrent invocation of wrapfs_fault could see a
-	 * different value.  In this workaround, we keep a different copy of
-	 * the vma structure in our stack, so we never expose a different
-	 * value of the vma->vm_file called to us, even temporarily.  A
-	 * better fix would be to change the calling semantics of ->fault to
-	 * take an explicit file pointer.
-	 */
-	lower_vma.vm_file = lower_file;
-	err = lower_vm_ops->fault(&lower_vma, vmf);
-	return err;
-}
-
-/*
- * XXX: the default address_space_ops for wrapfs is empty.  We cannot set
- * our inode->i_mapping->a_ops to NULL because too many code paths expect
- * the a_ops vector to be non-NULL.
- */
-const struct address_space_operations wrapfs_aops = {
-	/* empty on purpose */
-};
-
-const struct vm_operations_struct wrapfs_vm_ops = {
-	.fault		= wrapfs_fault,
-};
diff --git a/fs/wrapfs/super.c b/fs/wrapfs/super.c
deleted file mode 100644
index aec2093..0000000
--- a/fs/wrapfs/super.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include "wrapfs.h"
-
-/*
- * The inode cache is used with alloc_inode for both our inode info and the
- * vfs inode.
- */
-static struct kmem_cache *wrapfs_inode_cachep;
-
-/* final actions when unmounting a file system */
-static void wrapfs_put_super(struct super_block *sb)
-{
-	struct wrapfs_sb_info *spd;
-	struct super_block *s;
-
-	spd = WRAPFS_SB(sb);
-	if (!spd)
-		return;
-
-	/* decrement lower super references */
-	s = wrapfs_lower_super(sb);
-	wrapfs_set_lower_super(sb, NULL);
-	atomic_dec(&s->s_active);
-
-	kfree(spd);
-	sb->s_fs_info = NULL;
-}
-
-static int wrapfs_statfs(struct dentry *dentry, struct kstatfs *buf)
-{
-	int err;
-	struct path lower_path;
-
-	wrapfs_get_lower_path(dentry, &lower_path);
-	err = vfs_statfs(&lower_path, buf);
-	wrapfs_put_lower_path(dentry, &lower_path);
-
-	/* set return buf to our f/s to avoid confusing user-level utils */
-	buf->f_type = WRAPFS_SUPER_MAGIC;
-
-	return err;
-}
-
-/*
- * @flags: numeric mount options
- * @options: mount options string
- */
-static int wrapfs_remount_fs(struct super_block *sb, int *flags, char *options)
-{
-	int err = 0;
-
-	/*
-	 * The VFS will take care of "ro" and "rw" flags among others.  We
-	 * can safely accept a few flags (RDONLY, MANDLOCK), and honor
-	 * SILENT, but anything else left over is an error.
-	 */
-	if ((*flags & ~(MS_RDONLY | MS_MANDLOCK | MS_SILENT)) != 0) {
-		printk(KERN_ERR
-		       "wrapfs: remount flags 0x%x unsupported\n", *flags);
-		err = -EINVAL;
-	}
-
-	return err;
-}
-
-/*
- * Called by iput() when the inode reference count reached zero
- * and the inode is not hashed anywhere.  Used to clear anything
- * that needs to be, before the inode is completely destroyed and put
- * on the inode free list.
- */
-static void wrapfs_evict_inode(struct inode *inode)
-{
-	struct inode *lower_inode;
-
-	truncate_inode_pages(&inode->i_data, 0);
-	clear_inode(inode);
-	/*
-	 * Decrement a reference to a lower_inode, which was incremented
-	 * by our read_inode when it was created initially.
-	 */
-	lower_inode = wrapfs_lower_inode(inode);
-	wrapfs_set_lower_inode(inode, NULL);
-	iput(lower_inode);
-}
-
-static struct inode *wrapfs_alloc_inode(struct super_block *sb)
-{
-	struct wrapfs_inode_info *i;
-
-	i = kmem_cache_alloc(wrapfs_inode_cachep, GFP_KERNEL);
-	if (!i)
-		return NULL;
-
-	/* memset everything up to the inode to 0 */
-	memset(i, 0, offsetof(struct wrapfs_inode_info, vfs_inode));
-
-	i->vfs_inode.i_version = 1;
-	return &i->vfs_inode;
-}
-
-static void wrapfs_destroy_inode(struct inode *inode)
-{
-	kmem_cache_free(wrapfs_inode_cachep, WRAPFS_I(inode));
-}
-
-/* wrapfs inode cache constructor */
-static void init_once(void *obj)
-{
-	struct wrapfs_inode_info *i = obj;
-
-	inode_init_once(&i->vfs_inode);
-}
-
-int wrapfs_init_inode_cache(void)
-{
-	int err = 0;
-
-	wrapfs_inode_cachep =
-		kmem_cache_create("wrapfs_inode_cache",
-				  sizeof(struct wrapfs_inode_info), 0,
-				  SLAB_RECLAIM_ACCOUNT, init_once);
-	if (!wrapfs_inode_cachep)
-		err = -ENOMEM;
-	return err;
-}
-
-/* wrapfs inode cache destructor */
-void wrapfs_destroy_inode_cache(void)
-{
-	if (wrapfs_inode_cachep)
-		kmem_cache_destroy(wrapfs_inode_cachep);
-}
-
-/*
- * Used only in nfs, to kill any pending RPC tasks, so that subsequent
- * code can actually succeed and won't leave tasks that need handling.
- */
-static void wrapfs_umount_begin(struct super_block *sb)
-{
-	struct super_block *lower_sb;
-
-	lower_sb = wrapfs_lower_super(sb);
-	if (lower_sb && lower_sb->s_op && lower_sb->s_op->umount_begin)
-		lower_sb->s_op->umount_begin(lower_sb);
-}
-
-const struct super_operations wrapfs_sops = {
-	.put_super	= wrapfs_put_super,
-	.statfs		= wrapfs_statfs,
-	.remount_fs	= wrapfs_remount_fs,
-	.evict_inode	= wrapfs_evict_inode,
-	.umount_begin	= wrapfs_umount_begin,
-	.show_options	= generic_show_options,
-	.alloc_inode	= wrapfs_alloc_inode,
-	.destroy_inode	= wrapfs_destroy_inode,
-	.drop_inode	= generic_delete_inode,
-};
diff --git a/fs/wrapfs/wrapfs.h b/fs/wrapfs/wrapfs.h
deleted file mode 100644
index ed49521..0000000
--- a/fs/wrapfs/wrapfs.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 1998-2011 Erez Zadok
- * Copyright (c) 2009	   Shrikar Archak
- * Copyright (c) 2003-2011 Stony Brook University
- * Copyright (c) 2003-2011 The Research Foundation of SUNY
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _WRAPFS_H_
-#define _WRAPFS_H_
-
-#include <linux/dcache.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/mount.h>
-#include <linux/namei.h>
-#include <linux/seq_file.h>
-#include <linux/statfs.h>
-#include <linux/fs_stack.h>
-#include <linux/magic.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-
-/* the file system name */
-#define WRAPFS_NAME "wrapfs"
-
-/* wrapfs root inode number */
-#define WRAPFS_ROOT_INO     1
-
-/* useful for tracking code reachability */
-#define UDBG printk(KERN_DEFAULT "DBG:%s:%s:%d\n", __FILE__, __func__, __LINE__)
-
-/* operations vectors defined in specific files */
-extern const struct file_operations wrapfs_main_fops;
-extern const struct file_operations wrapfs_dir_fops;
-extern const struct inode_operations wrapfs_main_iops;
-extern const struct inode_operations wrapfs_dir_iops;
-extern const struct inode_operations wrapfs_symlink_iops;
-extern const struct super_operations wrapfs_sops;
-extern const struct dentry_operations wrapfs_dops;
-extern const struct address_space_operations wrapfs_aops, wrapfs_dummy_aops;
-extern const struct vm_operations_struct wrapfs_vm_ops;
-
-extern int wrapfs_init_inode_cache(void);
-extern void wrapfs_destroy_inode_cache(void);
-extern int wrapfs_init_dentry_cache(void);
-extern void wrapfs_destroy_dentry_cache(void);
-extern int new_dentry_private_data(struct dentry *dentry);
-extern void free_dentry_private_data(struct dentry *dentry);
-extern int init_lower_nd(struct nameidata *nd, unsigned int flags);
-extern struct dentry *wrapfs_lookup(struct inode *dir, struct dentry *dentry,
-				    unsigned int flags);
-extern struct inode *wrapfs_iget(struct super_block *sb,
-				 struct inode *lower_inode);
-extern int wrapfs_interpose(struct dentry *dentry, struct super_block *sb,
-			    struct path *lower_path);
-
-/* file private data */
-struct wrapfs_file_info {
-	struct file *lower_file;
-	const struct vm_operations_struct *lower_vm_ops;
-};
-
-/* wrapfs inode data in memory */
-struct wrapfs_inode_info {
-	struct inode *lower_inode;
-	struct inode vfs_inode;
-};
-
-/* wrapfs dentry data in memory */
-struct wrapfs_dentry_info {
-	spinlock_t lock;	/* protects lower_path */
-	struct path lower_path;
-};
-
-/* wrapfs super-block data in memory */
-struct wrapfs_sb_info {
-	struct super_block *lower_sb;
-};
-
-/*
- * inode to private data
- *
- * Since we use containers and the struct inode is _inside_ the
- * wrapfs_inode_info structure, WRAPFS_I will always (given a non-NULL
- * inode pointer), return a valid non-NULL pointer.
- */
-static inline struct wrapfs_inode_info *WRAPFS_I(const struct inode *inode)
-{
-	return container_of(inode, struct wrapfs_inode_info, vfs_inode);
-}
-
-/* dentry to private data */
-#define WRAPFS_D(dent) ((struct wrapfs_dentry_info *)(dent)->d_fsdata)
-
-/* superblock to private data */
-#define WRAPFS_SB(super) ((struct wrapfs_sb_info *)(super)->s_fs_info)
-
-/* file to private Data */
-#define WRAPFS_F(file) ((struct wrapfs_file_info *)((file)->private_data))
-
-/* file to lower file */
-static inline struct file *wrapfs_lower_file(const struct file *f)
-{
-	return WRAPFS_F(f)->lower_file;
-}
-
-static inline void wrapfs_set_lower_file(struct file *f, struct file *val)
-{
-	WRAPFS_F(f)->lower_file = val;
-}
-
-/* inode to lower inode. */
-static inline struct inode *wrapfs_lower_inode(const struct inode *i)
-{
-	return WRAPFS_I(i)->lower_inode;
-}
-
-static inline void wrapfs_set_lower_inode(struct inode *i, struct inode *val)
-{
-	WRAPFS_I(i)->lower_inode = val;
-}
-
-/* superblock to lower superblock */
-static inline struct super_block *wrapfs_lower_super(
-	const struct super_block *sb)
-{
-	return WRAPFS_SB(sb)->lower_sb;
-}
-
-static inline void wrapfs_set_lower_super(struct super_block *sb,
-					  struct super_block *val)
-{
-	WRAPFS_SB(sb)->lower_sb = val;
-}
-
-/* path based (dentry/mnt) macros */
-static inline void pathcpy(struct path *dst, const struct path *src)
-{
-	dst->dentry = src->dentry;
-	dst->mnt = src->mnt;
-}
-/* Returns struct path.  Caller must path_put it. */
-static inline void wrapfs_get_lower_path(const struct dentry *dent,
-					 struct path *lower_path)
-{
-	spin_lock(&WRAPFS_D(dent)->lock);
-	pathcpy(lower_path, &WRAPFS_D(dent)->lower_path);
-	path_get(lower_path);
-	spin_unlock(&WRAPFS_D(dent)->lock);
-	return;
-}
-static inline void wrapfs_put_lower_path(const struct dentry *dent,
-					 struct path *lower_path)
-{
-	path_put(lower_path);
-	return;
-}
-static inline void wrapfs_set_lower_path(const struct dentry *dent,
-					 struct path *lower_path)
-{
-	spin_lock(&WRAPFS_D(dent)->lock);
-	pathcpy(&WRAPFS_D(dent)->lower_path, lower_path);
-	spin_unlock(&WRAPFS_D(dent)->lock);
-	return;
-}
-static inline void wrapfs_reset_lower_path(const struct dentry *dent)
-{
-	spin_lock(&WRAPFS_D(dent)->lock);
-	WRAPFS_D(dent)->lower_path.dentry = NULL;
-	WRAPFS_D(dent)->lower_path.mnt = NULL;
-	spin_unlock(&WRAPFS_D(dent)->lock);
-	return;
-}
-static inline void wrapfs_put_reset_lower_path(const struct dentry *dent)
-{
-	struct path lower_path;
-	spin_lock(&WRAPFS_D(dent)->lock);
-	pathcpy(&lower_path, &WRAPFS_D(dent)->lower_path);
-	WRAPFS_D(dent)->lower_path.dentry = NULL;
-	WRAPFS_D(dent)->lower_path.mnt = NULL;
-	spin_unlock(&WRAPFS_D(dent)->lock);
-	path_put(&lower_path);
-	return;
-}
-
-/* locking helpers */
-static inline struct dentry *lock_parent(struct dentry *dentry)
-{
-	struct dentry *dir = dget_parent(dentry);
-	mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
-	return dir;
-}
-
-static inline void unlock_dir(struct dentry *dir)
-{
-	mutex_unlock(&dir->d_inode->i_mutex);
-	dput(dir);
-}
-#endif	/* not _WRAPFS_H_ */
-- 
1.8.3.2




More information about the Kernelnewbies mailing list