diff -Naur ext3/inode.c ext3sd/inode.c
--- ext3/inode.c	2006-10-28 15:59:40.000000000 -0400
+++ ext3sd/inode.c	2006-10-28 16:00:00.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/writeback.h>
 #include <linux/mpage.h>
 #include <linux/uio.h>
+#include <linux/random.h>
 #include "xattr.h"
 #include "acl.h"
 
@@ -192,6 +193,13 @@
 	if (is_bad_inode(inode))
 		goto no_delete;
 
+#ifdef CONFIG_EXT3_FS_SECDEL
+	if (EXT3_I(inode)->i_flags & EXT3_SECRM_FL) {
+		if (ext3_secdel_inode(inode))
+			goto no_delete;
+	}
+#endif
+
 	handle = start_transaction(inode);
 	if (IS_ERR(handle)) {
 		/* If we're going to skip the normal cleanup, we still
@@ -802,6 +810,295 @@
 	return ret;
 }
 
+#ifdef CONFIG_EXT3_FS_SECDEL
+static int ext3_ovwt_blocks(handle_t *handle, struct inode *inode, char param,
+		sector_t first, sector_t last)
+{               
+	int retval = 0;
+	sector_t i;
+	sector_t j;
+	/* TODO: Change batch number to something better? */
+	sector_t batch = 4;
+	struct buffer_head *bh = NULL;
+	struct buffer_head tmp;
+	struct super_block *sb;
+
+	J_ASSERT(handle != NULL);
+
+	tmp.b_state = 0;
+	tmp.b_blocknr = 0;
+	sb = inode->i_sb;
+
+	J_ASSERT( last >= first );
+
+	if (IS_ERR(handle)) {
+		retval = PTR_ERR(handle);
+		goto out;
+	}
+
+	if ( last - first < batch)
+		batch = last - first;
+
+	j = first;
+next_batch:
+	if (ext3_should_journal_data(inode)) {
+		retval = ext3_journal_extend(handle, batch);
+		if (retval)
+			retval = ext3_journal_restart(handle, batch);
+		if (retval)
+			goto out;
+	}
+
+	/* Are we at the end? */
+	if (batch > last - j)
+		batch = last - j;
+
+	for (i = 0; i < batch; i++, j++) {
+		ext3_get_block(inode, j, &tmp, 0);
+		bh = sb_getblk(sb, tmp.b_blocknr);
+
+		if (ext3_should_journal_data(inode)) {
+			retval = ext3_journal_get_write_access(handle, bh);
+			if (retval)
+				goto out;
+		}
+
+		lock_buffer(bh);
+		if (param == 'R')
+			get_random_bytes(bh->b_data, bh->b_size);
+		else
+			memset(bh->b_data, param, bh->b_size);
+		unlock_buffer(bh);
+        
+		if (ext3_should_journal_data(inode)) {
+			retval = ext3_journal_dirty_metadata(handle, bh);
+			if (retval)
+				goto out;
+		}
+		else
+			mark_buffer_dirty(bh);
+
+		brelse(bh);
+	}
+	if ( j < last)
+		goto next_batch;
+	bh = NULL;
+out:
+	if (retval)
+		ext3_journal_abort_handle(NULL, NULL, bh, handle, retval);
+	if (bh)
+		brelse(bh);
+	return retval; 
+}
+
+static int ext3_ovwt_metadata(handle_t *handle, struct inode *inode, char param)
+{
+        int retval = 0;
+	int param_int = 0;
+
+	if (param == 'R')
+		get_random_bytes( (char *)&param_int, sizeof(int));
+	else
+		param_int = param | param<<8 | param<<16 | param<<24;
+
+        inode->i_uid = param_int;
+        inode->i_gid = param_int;
+        inode->i_atime.tv_sec = param_int;
+        inode->i_atime.tv_nsec = param_int;
+        inode->i_mtime.tv_sec = param_int;
+        inode->i_mtime.tv_nsec = param_int;
+        inode->i_ctime.tv_sec = param_int;
+        inode->i_ctime.tv_nsec = param_int;
+
+        return retval;
+}
+
+static 
+int ext3_secure_truncate(struct inode *inode, sector_t first, sector_t last)
+{
+
+	struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb);
+	int err = 0;
+	int num_ovwt = 0;
+	int char_pos = 0;
+	handle_t *handle;
+
+	/* Copy all secure deletion options so I don't have to dereference
+	 * every time. */
+	int data_num = sbi->s_data_num_ovwt;
+	int data_size = sbi->s_data_char_size;
+	char *data_c = sbi->s_data_char;
+
+	/* I'm adding the inode to the orphan in a dirty way (making it a 
+	 * transaction of it's own), since I don't want to add it inside the
+	 * loop. Normally I should put it within the first transaction since
+	 * I'll probably have a performance hit if I keep it here.
+	 */
+	handle = start_transaction(inode);
+
+	if (IS_ERR(handle)) {
+		err = PTR_ERR(handle);
+		goto out;
+	}
+	/* 
+	 * Ok start secure truncation. Add the inode to the orhpan list
+	 * for any possible crashes during the operation.
+	 */
+	if ( ext3_orphan_add(handle, inode) )
+		goto out;
+
+	ext3_journal_stop(handle);
+
+	handle = NULL;
+
+next_ovwt:
+	char_pos = 0;
+	while ( char_pos < data_size ) {
+
+		handle = start_transaction(inode);
+
+		if (IS_ERR(handle)) {
+			err = PTR_ERR(handle);
+			goto del_orphan_out;
+		}
+		if ( char_pos < data_size && num_ovwt < data_num) {
+			err = ext3_ovwt_blocks(handle, inode, 
+			*(data_c + char_pos), first, last);
+			if (err)
+				goto stop_out;
+		}
+
+		ext3_journal_stop(handle);
+
+		if ( !(char_pos == data_size -1 && num_ovwt == data_num -1) ) {
+			journal_lock_updates(EXT3_SB(inode->i_sb)->s_journal);
+			err = journal_flush(EXT3_SB(inode->i_sb)->s_journal);
+			journal_unlock_updates(EXT3_SB(inode->i_sb)->s_journal);
+			if (err)
+				goto del_orphan_out;
+			err = sync_blockdev(inode->i_sb->s_bdev);
+			if (err)
+				goto del_orphan_out;
+			
+		}
+		char_pos++;
+	}
+	num_ovwt++;
+	
+	if (num_ovwt < data_num)
+		goto next_ovwt;
+	return err;
+stop_out:	
+	ext3_journal_stop(handle);
+del_orphan_out:
+	ext3_orphan_del(handle, inode);
+out:
+	return err;
+}
+
+int ext3_secdel_inode(struct inode *inode)
+{
+
+	struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb);
+	int err = 0;
+	int num_ovwt = 0;
+	int char_pos = 0;
+	handle_t *handle;
+	sector_t last_block;
+
+	/* 
+	 * Copy all secure deletion options so I don't have to dereference
+	 * every time.
+	 */
+	int data_num = sbi->s_data_num_ovwt;
+	int meta_num = sbi->s_meta_num_ovwt;
+	int data_size = sbi->s_data_char_size;
+	int meta_size = sbi->s_meta_char_size;
+	char *data_c = sbi->s_data_char;
+	char *meta_c = sbi->s_meta_char;
+	last_block = (inode->i_size + inode->i_blksize-1 )
+					>> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
+
+	/* I'm adding the inode to the orphan in a dirty way (making it a 
+	 * transaction of it's own), since I don't want to add it inside the
+	 * loop. Normally I should put it within the first transaction since
+	 * I'll probably have a performance hit if I keep it here.
+	 */
+	handle = start_transaction(inode);
+
+	if (IS_ERR(handle)) {
+		err = PTR_ERR(handle);
+		goto out;
+	}
+
+	/* 
+	 * We need add to the inode to the orphan list. We want the 
+	 * block overwrites and the truncation to be an atomic operation, so
+	 * we will remove the inode from the orphan list only after the 
+	 * truncation has sucessfully finished.
+	 */
+	if ( ext3_orphan_add(handle, inode) )
+		goto out;
+
+	ext3_journal_stop(handle);
+
+	handle = NULL;
+
+
+next_ovwt:
+	char_pos = 0;
+	while ( char_pos < data_size ||
+		char_pos < meta_size ) {
+
+		handle = start_transaction(inode);
+
+		if (IS_ERR(handle)) {
+			err = PTR_ERR(handle);
+			goto del_orphan_out;
+		}
+		if ( char_pos < data_size && num_ovwt < data_num) {
+			err = ext3_ovwt_blocks(handle, inode, 
+					*(data_c + char_pos), 0, last_block);
+			if (err)
+				goto stop_out;
+		}
+		if ( char_pos < meta_size && num_ovwt < meta_num) {
+			err = ext3_ovwt_metadata(handle, inode,
+							 *(meta_c + char_pos));
+			if (err)
+				goto stop_out;
+			mark_inode_dirty(inode);
+		}
+
+		ext3_journal_stop(handle);
+
+		if ( !(char_pos == data_size -1 && num_ovwt == data_num -1) ) {
+			journal_lock_updates(EXT3_SB(inode->i_sb)->s_journal);
+			err = journal_flush(EXT3_SB(inode->i_sb)->s_journal);
+			journal_unlock_updates(EXT3_SB(inode->i_sb)->s_journal);
+			if (err)
+				goto del_orphan_out;
+			err = sync_blockdev(inode->i_sb->s_bdev);
+			if (err)
+				goto del_orphan_out;
+		}
+		char_pos++;
+	}
+	num_ovwt++;
+	
+	if (num_ovwt < data_num || num_ovwt < meta_num)
+		goto next_ovwt;
+	return err;
+stop_out:	
+	ext3_journal_stop(handle);
+del_orphan_out:
+	ext3_orphan_del(handle,inode);
+out:
+	return err;
+
+}
+#endif
+
 #define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
 
 static int
@@ -1432,6 +1729,7 @@
 
 static int ext3_invalidatepage(struct page *page, unsigned long offset)
 {
+	int err = 0;
 	journal_t *journal = EXT3_JOURNAL(page->mapping->host);
 
 	/*
@@ -1440,7 +1738,8 @@
 	if (offset == 0)
 		ClearPageChecked(page);
 
-	return journal_invalidatepage(journal, page, offset);
+	err = journal_invalidatepage(journal, page, offset);
+	return err;
 }
 
 static int ext3_releasepage(struct page *page, gfp_t wait)
@@ -2137,6 +2436,14 @@
 		goto out_stop;	/* error */
 
 	/*
+	 * If secure deletion is compiled in the file-system, we have
+	 * already added the inode to the orphan list because we need to
+	 * make the overwrites and the truncation an atomic operation.
+	 * Otherwise under and system crash our inode will not be correctly
+	 * deleted.
+	 */
+#ifndef CONFIG_EXT3_FS_SECDEL
+	/*
 	 * OK.  This truncate is going to happen.  We add the inode to the
 	 * orphan list, so that if this truncate spans multiple transactions,
 	 * and we crash, we will resume the truncate when the filesystem
@@ -2147,6 +2454,7 @@
 	 */
 	if (ext3_orphan_add(handle, inode))
 		goto out_stop;
+#endif
 
 	/*
 	 * The orphan list entry will now protect us from any crash which
@@ -2763,6 +3071,11 @@
 {
 	struct inode *inode = dentry->d_inode;
 	int error, rc = 0;
+	handle_t *handle;
+#ifdef CONFIG_EXT3_FS_SECDEL
+	sector_t first;
+	sector_t last;
+#endif
 	const unsigned int ia_valid = attr->ia_valid;
 
 	error = inode_change_ok(inode, attr);
@@ -2798,7 +3111,22 @@
 
 	if (S_ISREG(inode->i_mode) &&
 	    attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
-		handle_t *handle;
+
+#ifdef CONFIG_EXT3_FS_SECDEL
+		/* Get range of blocks that will be freed and secure delete
+		 * if necessary. */
+		first = (attr->ia_size + inode->i_blksize-1)
+					>> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
+		last = (inode->i_size + inode->i_blksize-1)
+					>> EXT3_BLOCK_SIZE_BITS(inode->i_sb);
+
+		if (EXT3_I(inode)->i_flags & EXT3_SECRM_FL) {
+			error = ext3_secure_truncate(inode, first, last);
+			if (error)
+				goto err_out;
+		}
+#endif
+
 
 		handle = ext3_journal_start(inode, 3);
 		if (IS_ERR(handle)) {
diff -Naur ext3/namei.c ext3sd/namei.c
--- ext3/namei.c	2006-10-28 15:59:40.000000000 -0400
+++ ext3sd/namei.c	2006-10-28 16:00:00.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/quotaops.h>
 #include <linux/buffer_head.h>
 #include <linux/smp_lock.h>
+#include <linux/random.h>
 
 #include "namei.h"
 #include "xattr.h"
@@ -2053,6 +2054,86 @@
 	return retval;
 }
 
+#ifdef CONFIG_EXT3_FS_SECDEL
+static int ext3_ovwt_dentry(handle_t *handle, struct buffer_head *bh,
+				struct ext3_dir_entry_2 *de, char param)
+{
+	int retval = 0;
+	get_bh(bh);
+
+	if ( (retval = ext3_journal_get_write_access(handle, bh)) )
+		goto out;
+
+	if (test_set_buffer_locked(bh))
+		goto out;
+
+	if (param == 'R')
+		get_random_bytes(de->name, de->name_len);
+	else
+		memset(de->name, param, de->name_len);
+	unlock_buffer(bh);
+
+	retval = ext3_journal_dirty_data(handle, bh);
+out:
+	return retval;
+}
+
+static int ext3_secdel_dentry(struct inode *inode, struct buffer_head *bh,
+			struct ext3_dir_entry_2 *de)
+{
+	struct ext3_sb_info *sbi = EXT3_SB(inode->i_sb);
+	int err = 0;
+	int num_ovwt = 0;
+	int char_pos = 0;
+	handle_t *handle;
+
+	/* Copy  secure deletion options for the filename so I don't have to 
+	 * dereference every time. */
+	int file_num = sbi->s_file_num_ovwt;
+	int file_size = sbi->s_file_char_size;
+	char *file_c = sbi->s_file_char;
+
+next_ovwt:
+	char_pos = 0;
+	while ( char_pos < file_size ) {
+
+		handle = ext3_journal_start(inode, 1);
+
+		if (IS_ERR(handle)) {
+			err = PTR_ERR(handle);
+			goto out;
+		}
+
+		err = ext3_ovwt_dentry(handle, bh, de, *(file_c + char_pos));
+		if (err)
+			goto stop_out;
+
+		ext3_journal_stop(handle);
+
+		/* TODO: I don't think we need to explicitly flush the
+		 * journal. Since each transaction is atomic, the jbd
+		 * will take care of checkpointing the journal. Should
+		 * check this out. If we can we should get rid of this,
+		 * since it might be a performance hit for no reason. */
+		journal_lock_updates(EXT3_SB(inode->i_sb)->s_journal);
+		err = journal_flush(EXT3_SB(inode->i_sb)->s_journal);
+		journal_unlock_updates(EXT3_SB(inode->i_sb)->s_journal);
+		if (err)
+			goto out;
+		char_pos++;
+	}
+	num_ovwt++;
+	
+	if (num_ovwt < file_num)
+		goto next_ovwt;
+	return err;
+stop_out:
+	ext3_journal_stop(handle);
+out:
+	return err;
+}
+#endif
+
 static int ext3_unlink(struct inode * dir, struct dentry *dentry)
 {
 	int retval;
@@ -2064,23 +2145,17 @@
 	/* Initialize quotas before so that eventual writes go
 	 * in separate transaction */
 	DQUOT_INIT(dentry->d_inode);
-	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
-	if (IS_ERR(handle))
-		return PTR_ERR(handle);
-
-	if (IS_DIRSYNC(dir))
-		handle->h_sync = 1;
-
+	
 	retval = -ENOENT;
 	bh = ext3_find_entry (dentry, &de);
 	if (!bh)
-		goto end_unlink;
+		goto end_nostop;
 
 	inode = dentry->d_inode;
 
 	retval = -EIO;
 	if (le32_to_cpu(de->inode) != inode->i_ino)
-		goto end_unlink;
+		goto end_nostop;
 
 	if (!inode->i_nlink) {
 		ext3_warning (inode->i_sb, "ext3_unlink",
@@ -2088,6 +2163,20 @@
 			      inode->i_ino, inode->i_nlink);
 		inode->i_nlink = 1;
 	}
+#ifdef CONFIG_EXT3_FS_SECDEL
+	if (EXT3_I(dentry->d_inode)->i_flags & EXT3_SECRM_FL) {
+		retval = ext3_secdel_dentry(inode, bh, de);
+		if (retval)
+			goto end_nostop;
+	}
+#endif
+	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+
+	if (IS_DIRSYNC(dir))
+		handle->h_sync = 1;
+
 	retval = ext3_delete_entry(handle, dir, de, bh);
 	if (retval)
 		goto end_unlink;
@@ -2103,6 +2192,7 @@
 
 end_unlink:
 	ext3_journal_stop(handle);
+end_nostop:
 	brelse (bh);
 	return retval;
 }
diff -Naur ext3/super.c ext3sd/super.c
--- ext3/super.c	2006-10-28 15:59:40.000000000 -0400
+++ ext3sd/super.c	2006-10-28 16:00:00.000000000 -0400
@@ -42,6 +42,7 @@
 #include "xattr.h"
 #include "acl.h"
 #include "namei.h"
+#include "tb.h"
 
 static int ext3_load_journal(struct super_block *, struct ext3_super_block *,
 			     unsigned long journal_devnum);
@@ -62,6 +63,10 @@
 static void ext3_unlockfs(struct super_block *sb);
 static void ext3_write_super (struct super_block * sb);
 static void ext3_write_super_lockfs(struct super_block *sb);
+#ifdef CONFIG_EXT3_FS_SECDEL
+static int ext3_store_secdel_options(struct ext3_sb_info *sbi, char *args);
+static void ext3_secdel_put_super(struct ext3_sb_info *sbi);
+#endif
 
 /* 
  * Wrappers for journal_start/end.
@@ -412,6 +417,10 @@
 		kfree(sbi->s_qf_names[i]);
 #endif
 
+#ifdef CONFIG_EXT3_FS_SECDEL
+	ext3_secdel_put_super(sbi);
+#endif
+
 	/* Debugging code just in case the in-memory inode orphan list
 	 * isn't empty.  The on-disk one can be non-empty if we've
 	 * detected an error and taken the fs readonly, but the
@@ -634,7 +643,7 @@
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
 	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
-	Opt_grpquota
+	Opt_grpquota, Opt_secdel
 };
 
 static match_table_t tokens = {
@@ -672,6 +681,7 @@
 	{Opt_data_journal, "data=journal"},
 	{Opt_data_ordered, "data=ordered"},
 	{Opt_data_writeback, "data=writeback"},
+	{Opt_secdel, "secdel=%s"},
 	{Opt_offusrjquota, "usrjquota="},
 	{Opt_usrjquota, "usrjquota=%s"},
 	{Opt_offgrpjquota, "grpjquota="},
@@ -720,6 +730,9 @@
 	int qtype;
 	char *qname;
 #endif
+#ifdef CONFIG_EXT3_FS_SECDEL
+	char *sd_params;
+#endif
 
 	if (!options)
 		return 1;
@@ -1011,6 +1024,31 @@
 		case Opt_nobh:
 			set_opt(sbi->s_mount_opt, NOBH);
 			break;
+#ifdef CONFIG_EXT3_FS_SECDEL
+		case Opt_secdel:
+			sd_params = match_strdup(&args[0]);
+			if (!sd_params) {
+				printk(KERN_ERR
+					"EXT3-fs: not enough memory for "
+					"storing secure deletion options.\n");
+					return 0;
+			}
+			if (ext3_store_secdel_options(sbi, sd_params)) {
+				printk(KERN_ERR
+					"EXT3-fs: invalid option(s) for "
+					"secure deletion.\n");
+				kfree(sd_params);
+				return 0;
+			}
+			kfree(sd_params);
+			break;
+#else
+		case Opt_secdel:
+			printk(KERN_ERR
+				"EXT3-fs: secure deletion option not "
+				"supported.\n");
+			break;
+#endif
 		default:
 			printk (KERN_ERR
 				"EXT3-fs: Unrecognized mount option \"%s\" "
@@ -1257,6 +1295,10 @@
 				__FUNCTION__, inode->i_ino, inode->i_size);
 			jbd_debug(2, "truncating inode %ld to %Ld bytes\n",
 				  inode->i_ino, inode->i_size);
+#ifdef CONFIG_EXT3_FS_SECDEL
+		if (EXT3_I(inode)->i_flags & EXT3_SECRM_FL)
+			ext3_secdel_inode(inode);
+#endif
 			ext3_truncate(inode);
 			nr_truncates++;
 		} else {
@@ -1423,6 +1465,13 @@
 	sbi->s_resuid = le16_to_cpu(es->s_def_resuid);
 	sbi->s_resgid = le16_to_cpu(es->s_def_resgid);
 
+#ifdef CONFIG_EXT3_FS_SECDEL
+	/* Set default options for secure deletion. */
+	sbi->s_data_num_ovwt = 0;
+        sbi->s_meta_num_ovwt = 0;
+        sbi->s_file_num_ovwt = 0;
+#endif
+
 	set_opt(sbi->s_mount_opt, RESERVATION);
 
 	if (!parse_options ((char *) data, sb, &journal_inum, &journal_devnum,
@@ -2650,6 +2699,200 @@
 
 #endif
 
+#ifdef CONFIG_EXT3_FS_SECDEL
+enum {
+	opt_ovwt, opt_chars, opt_data_ovwt, opt_data_chars, opt_meta_ovwt,
+	opt_meta_chars, opt_file_ovwt, opt_file_chars, opt_err,
+};
+
+static match_table_t sd_tokens = {
+	{opt_ovwt, "all_ovwt=%u"},
+	{opt_chars, "all_chars=%s"},
+	{opt_data_ovwt, "data_ovwt=%u"},
+	{opt_data_chars, "data_chars=%s"},
+	{opt_meta_ovwt, "meta_ovwt=%u"},
+	{opt_meta_chars, "meta_chars=%s"},
+	{opt_file_ovwt, "file_ovwt=%u"},
+	{opt_file_chars, "file_chars=%s"},
+	{opt_err, NULL},
+
+};
+
+static int ext3_store_secdel_options(struct ext3_sb_info *sbi, char *options)
+{
+	int err = 0;
+	u32 num_ovwt = 0;
+	u32 data_ovwt = 0;
+	u32 meta_ovwt = 0;
+	u32 file_ovwt = 0;
+	char *ovwt_chars = NULL;
+	char *data_chars = NULL;
+	char *meta_chars = NULL;
+	char *file_chars = NULL;
+	char * p;       
+	substring_t args[MAX_OPT_ARGS];
+
+	if (!options)
+		return 1;
+	while ((p = strsep (&options, ";")) != NULL) {
+		int token;
+		if (!*p)
+			continue;
+
+		token = match_token(p, sd_tokens, args);
+		switch (token) {
+		case opt_ovwt:
+			if (match_int(&args[0], &num_ovwt)) {
+				printk("EXT3-fs: Invalid argument to "
+					"all_ovwt.\n");
+				err = -EINVAL;
+				goto err_out;
+			}
+		break;
+		case opt_chars:
+			ovwt_chars = match_strdup(&args[0]);
+			if (!ovwt_chars) {
+				printk("EXT3-fs: Not enough memory to set "
+					"secure deletion option.\n");
+				err = -ENOMEM;
+				goto err_out;
+			}
+		break;
+		case opt_data_ovwt:
+			if (match_int(&args[0], &data_ovwt)) {
+				printk("EXT3-fs: Invalid argument to "
+					"data_ovwt.\n");
+				err = -EINVAL;
+				goto err_out;
+
+			}
+		break;
+		case opt_data_chars:
+			data_chars = match_strdup(&args[0]);
+			if (!data_chars) {
+				printk("EXT3-fs: Not enough memory to set "
+					"secure deletion option.\n");
+				err = -ENOMEM;
+				goto err_out;
+			}
+		break;
+		case opt_meta_ovwt:
+			if (match_int(&args[0], &meta_ovwt)) {
+				printk("EXT3-fs: Invalid argument to "
+					"meta_ovwt.\n");
+				err = -EINVAL;
+				goto err_out;
+
+			}
+		break;
+		case opt_meta_chars:
+			meta_chars = match_strdup(&args[0]);
+			if (!meta_chars) {
+				printk("EXT3-fs: Not enough memory to set "
+					"secure deletion option.\n");
+				err = -ENOMEM;
+				goto err_out;
+			}
+		break;
+		case opt_file_ovwt:
+			if (match_int(&args[0], &file_ovwt)) {
+				printk("EXT3-fs: Invalid argument to "
+					"file_ovwt.\n");
+				err = -EINVAL;
+				goto err_out;
+
+			}
+		break;
+		case opt_file_chars:
+			file_chars = match_strdup(&args[0]);
+			if (!file_chars) {
+				printk("EXT3-fs: Not enough memory to set "
+					"secure deletion option.\n");
+				err = -ENOMEM;
+				goto err_out;
+			}
+		break;
+		default:
+			err = -EINVAL;
+			goto err_out;
+		}
+	}
+
+	/* Now populate the sbi */
+	if (data_ovwt)
+		sbi->s_data_num_ovwt = data_ovwt;
+	else
+		sbi->s_data_num_ovwt = num_ovwt;
+
+	if (meta_ovwt)
+		sbi->s_meta_num_ovwt = meta_ovwt;
+	else
+		sbi->s_meta_num_ovwt = num_ovwt;
+
+	if (file_ovwt)
+		sbi->s_file_num_ovwt = file_ovwt;
+	else
+		sbi->s_file_num_ovwt = num_ovwt;
+
+	if (data_chars) {
+		sbi->s_data_char = data_chars;
+		sbi->s_data_char_size = strlen(data_chars);
+	}
+	else if (ovwt_chars) {
+		sbi->s_data_char = ovwt_chars;
+		sbi->s_data_char_size = strlen(ovwt_chars);
+	}
+
+	if (meta_chars) {
+		sbi->s_meta_char = meta_chars;
+		sbi->s_meta_char_size = strlen(meta_chars);
+	}
+	else if (ovwt_chars) {
+		sbi->s_meta_char = ovwt_chars;
+		sbi->s_meta_char_size = strlen(ovwt_chars);
+	}
+
+	if (file_chars) {
+		sbi->s_file_char = file_chars;
+		sbi->s_file_char_size = strlen(file_chars);
+	}
+	else if (ovwt_chars) {
+		sbi->s_file_char = ovwt_chars;
+		sbi->s_file_char_size = strlen(ovwt_chars);
+	}
+
+	/* If all fields are individually allocated we don't need
+	 * ovwt_chars anymore */
+	if (data_chars && meta_chars && file_chars && data_chars)
+		kfree(ovwt_chars);
+
+	return err;
+
+err_out:
+	if (ovwt_chars)
+		kfree(ovwt_chars);
+	if (data_chars)
+		kfree(data_chars);
+	if (meta_chars)
+		kfree(meta_chars);
+	if (file_chars)
+		kfree(file_chars);
+out:
+	return err;
+}
+
+static void ext3_secdel_put_super(struct ext3_sb_info *sbi)
+{
+	if (sbi->s_data_char)
+		kfree(sbi->s_data_char);
+	if (sbi->s_meta_char &&  sbi->s_data_char != sbi->s_meta_char)
+		kfree(sbi->s_meta_char);
+	if (sbi->s_file_char && sbi->s_data_char != sbi->s_file_char &&
+				sbi->s_meta_char != sbi->s_file_char)
+		kfree(sbi->s_file_char);
+}
+#endif
+
 static struct super_block *ext3_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
