diff -Naur ext4/namei.c ext4tb/namei.c
--- ext4/namei.c	2006-10-28 16:08:13.000000000 -0400
+++ ext4tb/namei.c	2006-10-28 16:08:27.000000000 -0400
@@ -41,6 +41,7 @@
 #include "namei.h"
 #include "xattr.h"
 #include "acl.h"
+#include "tb.h"
 
 /*
  * define how far ahead to read directories while searching them.
@@ -2098,15 +2099,27 @@
 			      inode->i_ino, inode->i_nlink);
 		inode->i_nlink = 1;
 	}
-	retval = ext4_delete_entry(handle, dir, de, bh);
-	if (retval)
-		goto end_unlink;
+#ifdef CONFIG_EXT4DEV_FS_TRASH_BIN
+	if (EXT4_I(dentry->d_inode)->i_flags & (EXT4_UNRM_FL | EXT4_SECRM_FL)) {
+		retval = ext4_trash_entry(dir, dentry);
+		if (retval)
+			goto end_unlink;
+	}
+#endif
+	if (!(EXT4_I(dentry->d_inode)->i_flags & (EXT4_UNRM_FL | 
+							EXT4_SECRM_FL))) {
+		retval = ext4_delete_entry(handle, dir, de, bh);
+		if (retval)
+			goto end_unlink;
+	}
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
 	ext4_update_dx_flag(dir);
 	ext4_mark_inode_dirty(handle, dir);
+#ifndef CONFIG_EXT4DEV_FS_TRASH_BIN
 	drop_nlink(inode);
 	if (!inode->i_nlink)
 		ext4_orphan_add(handle, inode);
+#endif
 	inode->i_ctime = dir->i_ctime;
 	ext4_mark_inode_dirty(handle, inode);
 	retval = 0;
diff -Naur ext4/super.c ext4tb/super.c
--- ext4/super.c	2006-10-28 16:08:13.000000000 -0400
+++ ext4tb/super.c	2006-10-28 16:08:27.000000000 -0400
@@ -41,6 +41,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "namei.h"
+#include "tb.h"
 
 static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
 			     unsigned long journal_devnum);
@@ -1837,6 +1838,11 @@
 		goto failed_mount4;
 	}
 
+#ifdef CONFIG_EXT4DEV_FS_TRASH_BIN
+        if (ext4_create_tb(sb))
+                goto failed_mount3;
+#endif
+
 	ext4_setup_super (sb, es, sb->s_flags & MS_RDONLY);
 	/*
 	 * akpm: core read_super() calls in here with the superblock locked.
diff -Naur ext4/tb.c ext4tb/tb.c
--- ext4/tb.c	1969-12-31 19:00:00.000000000 -0500
+++ ext4tb/tb.c	2006-10-28 16:52:30.000000000 -0400
@@ -0,0 +1,148 @@
+/*  linux/fs/ext4/tb.c
+ *
+ * Copyright (C) 2006 Stony Brook University
+ * Nikolai Joukov, Harry Papaxenopoulos, and Erez Zadok
+ */
+#include <linux/fs.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include "tb.h"
+
+int ext4_create_tb(struct super_block *sb)
+{
+	int err = 0;
+	struct dentry *dentry, *root_dentry;
+	struct inode *mnt_inode;
+
+	root_dentry = sb->s_root;
+	mnt_inode = root_dentry->d_inode;
+
+	dentry = lookup_one_len(TB_NAME, root_dentry, TB_NAME_LEN);
+
+	if (IS_ERR(dentry)){
+		err = PTR_ERR(dentry);
+		goto out;
+	}
+
+	if (!dentry->d_inode && mnt_inode->i_op && mnt_inode->i_op->mkdir) {
+		mutex_lock(&mnt_inode->i_mutex);
+		err = mnt_inode->i_op->mkdir(mnt_inode, dentry, TB_MODE);
+		mutex_unlock(&mnt_inode->i_mutex);
+		if (err)
+			goto release_out;
+	}
+
+release_out:
+	dput(dentry);
+out:
+	return err;
+}
+
+struct dentry *tb_sillyname( struct dentry *tb_dentry, struct dentry *dentry)
+{
+	unsigned sillycounter = 1;
+	char random[4];
+	char *silly = NULL;
+	char *tmp = NULL;
+	struct dentry *sdentry = NULL;
+
+	silly = kmalloc(PATH_MAX, GFP_KERNEL);
+	if (!silly)
+		goto out;
+
+	tmp = kmalloc(PATH_MAX, GFP_KERNEL);
+	if (!tmp)
+		goto out;
+
+	if (!tb_dentry->d_inode) {
+		sdentry = ERR_PTR(-EIO);
+		goto out;
+	}
+
+	sdentry = lookup_one_len(dentry->d_name.name, tb_dentry,
+				dentry->d_name.len);
+
+	if (IS_ERR(sdentry))
+		goto out;
+
+	while(sdentry->d_inode != NULL) {
+		if (PATH_MAX - 5 <= dentry->d_name.len)
+			snprintf(tmp, PATH_MAX - 6, dentry->d_name.name);
+		else
+			sprintf(tmp, dentry->d_name.name);
+
+		sprintf(silly, "%s_%u", dentry->d_name.name, sillycounter);
+		dput(sdentry);
+		sdentry = lookup_one_len(silly, tb_dentry, strlen(silly));
+		if (IS_ERR(sdentry))
+			goto out;
+		sillycounter++;
+	} 
+out:
+	if (silly)
+		kfree(silly);
+	if (tmp)
+		kfree(tmp);
+	return sdentry;
+}
+
+int ext4_trash_entry(struct inode *old_dir, struct dentry *old_dentry)
+{
+	int err = 0;
+	struct ext3_sb_info *ext3_sb;
+	struct dentry *new_dentry = NULL;
+	struct dentry *tb_dentry = NULL;
+	struct dentry *root_dentry = NULL;
+	struct inode *tb_inode;
+
+	if (old_dir && old_dir->i_sb && old_dir->i_sb->s_root)
+		root_dentry = old_dir->i_sb->s_root;
+	else {
+		err = -EIO;
+		goto out;
+	}
+
+	tb_dentry = lookup_one_len(TB_NAME, root_dentry, TB_NAME_LEN);
+	if (IS_ERR(tb_dentry)) {
+		err = PTR_ERR(tb_dentry);
+		goto out;
+	}
+
+	tb_inode = tb_dentry->d_inode;
+	if (!tb_inode) {
+		err = -EIO;
+		goto release_out;
+	}
+
+	if (tb_inode->i_ino == old_dir->i_ino)
+		goto release_out;
+
+	new_dentry = tb_sillyname(tb_dentry, old_dentry);
+	if (IS_ERR(new_dentry)) {
+		err = PTR_ERR(new_dentry);
+		goto release_out2;
+	}
+	if (tb_inode->i_op && tb_inode->i_op->rename) {
+		mutex_lock(&tb_inode->i_mutex);
+		err = tb_inode->i_op->rename(old_dir, old_dentry,
+					     tb_inode, new_dentry);
+		mutex_unlock(&tb_inode->i_mutex);
+		if (!err)
+			d_move(old_dentry, new_dentry);
+	} else {
+		err = -ENOSYS;
+		goto release_out;
+	}
+	//need to manually unhash the old dentry
+	if (!d_unhashed(old_dentry))
+		__d_drop(old_dentry);
+release_out:
+	dput(new_dentry);
+release_out2:
+	dput(tb_dentry);
+out:
+	return err;
+}
+
diff -Naur ext4/tb.h ext4tb/tb.h
--- ext4/tb.h	1969-12-31 19:00:00.000000000 -0500
+++ ext4tb/tb.h	2006-10-28 16:52:30.000000000 -0400
@@ -0,0 +1,15 @@
+/*  linux/fs/ext4/tb.h
+ *
+ * Copyright (C) 2006 Stony Brook University
+ * Nikolai Joukov, Harry Papaxenopoulos, and Erez Zadok
+ */
+#ifdef CONFIG_EXT4DEV_FS_TRASH_BIN
+
+#define TB_NAME ".trash"
+#define TB_NAME_LEN 6
+#define TB_MODE 0711
+#define TB_DEBUG 1
+
+extern int ext4_create_tb(struct super_block *);
+extern int ext4_trash_entry(struct inode *, struct dentry *);
+#endif /*CONFIG_EXT4_FS_TRASH_BIN*/
