diff --git a/lustre/snapfs/cache.c b/lustre/snapfs/cache.c
index d0c8f1bb49d142069702de57ea5e69fdecffc92d..bb1ed305309d21a09099b66b153c1dd8f768fee7 100644
--- a/lustre/snapfs/cache.c
+++ b/lustre/snapfs/cache.c
@@ -1,56 +1,35 @@
-/*
- *
- *
- *  Copyright (C) 2000 Stelias Computing, Inc.
- *  Copyright (C) 2000 Red Hat, Inc.
- *
- *
+/*  
+ *  snapfs/cache.c
  */
 
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#define __NO_VERSION__
-#include <linux/module.h>
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
-
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+#include <portals/list.h>
+#include "snapfs_internal.h" 
 /*
  * XXX - Not sure for snapfs that the cache functions are even needed.
  * Can't all lookups be done by an inode->superblock->u.generic_sbp
  * lookup?
  */
 
-/*
-   This file contains the routines associated with managing a
-   cache of files .  These caches need to be found
-   fast so they are hashed by the device, with an attempt to have
-   collision chains of length 1.
-*/
+extern struct snap_table snap_tables[SNAP_MAX_TABLES];
 
 /* the intent of this hash is to have collision chains of length 1 */
 #define CACHES_BITS 8
 #define CACHES_SIZE (1 << CACHES_BITS)
 #define CACHES_MASK CACHES_SIZE - 1
+
 static struct list_head snap_caches[CACHES_SIZE];
 
+
 static inline int snap_cache_hash(kdev_t dev)
 {
 	return (CACHES_MASK) & ((0x000F & (dev)) + ((0x0F00 & (dev)) >>8));
@@ -78,68 +57,39 @@ struct snap_cache *snap_find_cache(kdev_t dev)
 	struct list_head *lh, *tmp;
 
 	lh = tmp = &(snap_caches[snap_cache_hash(dev)]);
-	while ( (tmp = lh->next) != lh ) {
-		cache = list_entry(tmp, struct snap_cache, cache_chain);
+        list_for_each_entry(cache, lh, cache_chain) { 
 		if ( cache->cache_dev == dev )
 			return cache;
 	}
 	return NULL;
 }
 
-
-/* map an inode to a cache */
-struct snap_cache *snap_get_cache(struct inode *inode)
-{
-	struct snap_cache *cache;
-
-	/* find the correct snap_cache here, based on the device */
-	cache = snap_find_cache(inode->i_dev);
-	if ( !cache ) {
-		printk("WARNING: no  cache for dev %d, ino %ld\n",
-		       inode->i_dev, inode->i_ino);
-		return NULL;
-	}
-
-	return cache;
-}
-
-
-/* another debugging routine: check fs is InterMezzo fs */
-int snap_ispresto(struct inode *inode)
-{
-	struct snap_cache *cache;
-
-	if ( !inode )
-		return 0;
-	cache = snap_get_cache(inode);
-	if ( !cache )
-		return 0;
-	return (inode->i_dev == cache->cache_dev);
-}
-
 /* setup a cache structure when we need one */
 struct snap_cache *snap_init_cache(void)
 {
 	struct snap_cache *cache;
 
 	/* make a snap_cache structure for the hash */
-	SNAP_ALLOC(cache, struct snap_cache *, sizeof(struct snap_cache));
+	SNAP_ALLOC(cache,  sizeof(struct snap_cache));
 	if ( cache ) {
-		memset(cache, 0, sizeof(struct snap_cache));
+		int i;
+                
+                memset(cache, 0, sizeof(struct snap_cache));
 		INIT_LIST_HEAD(&cache->cache_chain);
 		INIT_LIST_HEAD(&cache->cache_clone_list);
-	}
+                        	
+                for (i = 0; i < SNAP_MAX_TABLES; i++) {
+                        init_MUTEX(&snap_tables[i].tbl_sema); 
+                }
+        }
 	return cache;
 }
 
-
 /* free a cache structure and all of the memory it is pointing to */
 inline void snap_free_cache(struct snap_cache *cache)
 {
 	if (!cache)
 		return;
-
-
 	SNAP_FREE(cache, sizeof(struct snap_cache));
 }
 
diff --git a/lustre/snapfs/clonefs.c b/lustre/snapfs/clonefs.c
index 1ef807807698b09a80f7d60d8186466672466ce2..708b083b4aa863189246485f65b5fdcf95ff69e3 100644
--- a/lustre/snapfs/clonefs.c
+++ b/lustre/snapfs/clonefs.c
@@ -13,45 +13,33 @@
  * 
  */
 
-#define __NO_VERSION__
+#define DEBUG_SUBSYSTEM S_SNAP
+
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/string.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
 #include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+#include "snapfs_internal.h" 
 
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <linux/string.h>
-#include <asm/uaccess.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <asm/segment.h>
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 /* Clone is a simple file system, read only that just follows redirectors
    we have placed the entire implementation except clone_read_super in
    this file 
  */
 
-struct inode_operations clonefs_dir_inode_operations;
-struct inode_operations clonefs_file_inode_operations;
-struct inode_operations clonefs_symlink_inode_operations;
-struct inode_operations clonefs_special_inode_operations;
-struct file_operations clonefs_dir_file_operations;
-struct file_operations clonefs_file_file_operations;
-struct file_operations clonefs_special_file_operations;
+struct inode_operations clonefs_dir_inode_ops;
+struct inode_operations clonefs_file_inode_ops;
+struct inode_operations clonefs_symlink_inode_ops;
+//struct inode_operations clonefs_special_inode_operations;
+struct file_operations clonefs_dir_file_ops;
+struct file_operations clonefs_file_file_ops;
+//struct file_operations clonefs_special_file_operations;
+struct address_space_operations clonefs_file_address_ops;
 
 /* support routines for following redirectors */
 
@@ -82,14 +70,14 @@ struct inode *clonefs_get_inode(struct inode *inode)
 	redirected_inode = snap_redirect(cache_inode, inode->i_sb);
 
 	CDEBUG(D_SNAP, "redirected_inode: %lx, cache_inode %lx\n",
-	       (ulong) redirected_inode, (ulong) cache_inode);
+	       (unsigned long) redirected_inode, (unsigned long) cache_inode);
 
 	CDEBUG(D_SNAP, "cache_inode: %lx, ino %ld, sb %lx, count %d\n",
-	       (ulong) cache_inode, cache_inode->i_ino, 
-	       (ulong) cache_inode->i_sb, cache_inode->i_count);
-
+	       (unsigned long) cache_inode, cache_inode->i_ino, 
+	       (unsigned long) cache_inode->i_sb, atomic_read(&cache_inode->i_count));
+	
 	iput(cache_inode); 
-	EXIT;
+	
 	return redirected_inode;
 }
 
@@ -102,39 +90,43 @@ static void clonefs_read_inode(struct inode *inode)
 	ENTRY;
 
 	CDEBUG(D_SNAP, "inode: %lx, ino %ld, sb %lx, count %d\n",
-	       (ulong) inode , inode->i_ino, (long) inode->i_sb, 
-	       inode->i_count);
+	       (unsigned long)inode, inode->i_ino, (long) inode->i_sb, 
+	       atomic_read(&inode->i_count));
 
 	/* redirecting inode in the cache */
         cache_inode = clonefs_get_inode(inode);
 	if (!cache_inode) {
 		make_bad_inode(inode);
-		EXIT;
 		return;
 	}
 	/* copy attrs of that inode to our clone inode */
 	snapfs_cpy_attrs(inode, cache_inode);
 
-	if (S_ISREG(inode->i_mode))
-		inode->i_op = &clonefs_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode))
-		inode->i_op = &clonefs_dir_inode_operations;
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &clonefs_symlink_inode_operations;
-	else if (S_ISCHR(inode->i_mode))
-		inode->i_op = &chrdev_inode_operations;
-	else if (S_ISBLK(inode->i_mode))
-		inode->i_op = &blkdev_inode_operations;
-	else if (S_ISFIFO(inode->i_mode))
-		init_fifo(inode);
-
+	if (S_ISREG(inode->i_mode)) {
+		inode->i_op = &clonefs_file_inode_ops;
+		if (inode->i_mapping)
+			inode->i_mapping->a_ops = &clonefs_file_address_ops;
+	} else if (S_ISDIR(inode->i_mode)) {
+		inode->i_op = &clonefs_dir_inode_ops;
+	} else if (S_ISLNK(inode->i_mode)) {
+		inode->i_op = &clonefs_symlink_inode_ops;
+	} else {
+	/* init special inode 
+	 * FIXME whether we should replace special inode ops*/
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+                init_special_inode(inode, inode->i_mode,
+                                   kdev_t_to_nr(inode->i_rdev));
+#else
+                init_special_inode(inode, inode->i_mode, inode->i_rdev);
+#endif
+	}
 	iput(cache_inode);
 
 	CDEBUG(D_SNAP, "cache_inode: %lx ino %ld, sb %lx, count %d\n",
-                (ulong) cache_inode, cache_inode->i_ino, 
-	       (ulong) cache_inode->i_sb, cache_inode->i_count);
-	EXIT;
-	return; 
+               (unsigned long) cache_inode, cache_inode->i_ino, 
+	       (unsigned long) cache_inode->i_sb, 
+	       atomic_read(&cache_inode->i_count));
+	EXIT; 
 }
 
 
@@ -144,18 +136,15 @@ static void clonefs_put_super(struct super_block *sb)
 
 	ENTRY;
 	CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
-                (ulong) sb, (ulong) &sb->u.generic_sbp);
+                (unsigned long) sb, (unsigned long) &sb->u.generic_sbp);
 	clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
-	dput( clone_sb->clone_cache->cache_sb->s_root );
+	dput(clone_sb->clone_cache->cache_sb->s_root);
 	list_del(&clone_sb->clone_list_entry);
 
-	MOD_DEC_USE_COUNT;
-
 	EXIT;
 }
 
-static int clonefs_statfs(struct super_block *sb, struct statfs *buf, 
-			int bufsiz)
+static int clonefs_statfs(struct super_block *sb, struct statfs *buf) 
 {
 	struct snap_clone_info *clone_sb;
 	struct snap_cache *cache; 
@@ -165,26 +154,19 @@ static int clonefs_statfs(struct super_block *sb, struct statfs *buf,
 
 	cache = clone_sb->clone_cache;
 	if (!cache) {
-		printk("clone_statfs: no cache\n");
-		return -EINVAL;
+		CERROR("clone_statfs: no cache\n");
+		RETURN(-EINVAL);
 	}
 
-	EXIT;
 	return cache->cache_filter->o_caops.cache_sops->statfs
-		(cache->cache_sb, buf, bufsiz);
+		(cache->cache_sb, buf);
 }
 
 struct super_operations clone_super_ops =
 {
-	clonefs_read_inode,       /* read_inode */
-	NULL,                   /* write_inode */
-	NULL,	                /* put_inode */
-	NULL,                   /* delete_inode */
-	NULL,	                /* notify_change */
-	clonefs_put_super,	/* put_super */
-	NULL,			/* write_super */
-	clonefs_statfs,   	/* statfs */
-	NULL			/* remount_fs */
+	read_inode:	clonefs_read_inode,     /* read_inode */
+	put_super:	clonefs_put_super,	/* put_super */
+	statfs:		clonefs_statfs,   	/* statfs */
 };
 
 
@@ -220,8 +202,7 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
 	cache_dentry = d_alloc(dentry->d_parent, &dentry->d_name);
 	if (!cache_dentry) {
                 iput(cache_dir);
-		EXIT;
-		return ERR_PTR(-ENOENT);
+		RETURN(ERR_PTR(-ENOENT));
 	}
 
         /* Lock cache directory inode. */
@@ -239,8 +220,7 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
 	        up(&cache_dir->i_sem);
                 iput(cache_dir);
 		dentry->d_inode = NULL;
-		EXIT;
-		return ERR_PTR(-ENOENT);
+		RETURN(ERR_PTR(-ENOENT));
 	}
         /* Unlock cache directory inode. */
 	up(&cache_dir->i_sem);
@@ -268,8 +248,8 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
 
 	if ( cache_inode != NULL ) {
 		CDEBUG(D_INODE, "cache ino %ld, count %d, dir %ld, count %d\n", 
-				cache_inode->i_ino, cache_inode->i_count, cache_dir->i_ino, 
-				cache_dir->i_count);
+		       cache_inode->i_ino, atomic_read(&cache_inode->i_count), 
+		       cache_dir->i_ino, atomic_read(&cache_dir->i_count));
 	}
 
 	d_unalloc(cache_dentry);
@@ -280,8 +260,7 @@ struct dentry *clonefs_lookup(struct inode *dir,  struct dentry *dentry)
          */
 	d_add(dentry, inode);
 
-	EXIT;
-        return NULL;
+        RETURN(NULL);
 }
 
 
@@ -293,16 +272,17 @@ static void clonefs_prepare_snapfile(struct inode *i,
 				     struct dentry *cache_dentry)
 {
 	ENTRY;
-        cache_file->f_pos = clone_file->f_pos;
+        
+	cache_file->f_pos = clone_file->f_pos;
         cache_file->f_mode = clone_file->f_mode;
         cache_file->f_flags = clone_file->f_flags;
         cache_file->f_count  = clone_file->f_count;
         cache_file->f_owner  = clone_file->f_owner;
-	cache_file->f_op = cache_inode->i_op->default_file_ops;
+	cache_file->f_op = cache_inode->i_fop;
 	cache_file->f_dentry = cache_dentry;
         cache_file->f_dentry->d_inode = cache_inode;
+	
 	EXIT;
-        return ;
 }
 
 /* update the clonefs file struct after IO in cache file */
@@ -312,10 +292,11 @@ static void clonefs_restore_snapfile(struct inode *cache_inode,
 				   struct file *clone_file)
 {
 	ENTRY;
-        cache_file->f_pos = clone_file->f_pos;
+ 
+	cache_file->f_pos = clone_file->f_pos;
 	cache_inode->i_size = clone_inode->i_size;
+	
 	EXIT;
-        return;
 }
 
 static int clonefs_readdir(struct file *file, void *dirent, 
@@ -330,15 +311,13 @@ static int clonefs_readdir(struct file *file, void *dirent,
 	ENTRY;
 
 	if(!inode) {
- 		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
         cache_inode = clonefs_get_inode(inode);
 
 	if (!cache_inode) {
 		make_bad_inode(inode);
-		EXIT;
-		return -ENOMEM;
+		RETURN(-ENOMEM);
 	}
 
 	CDEBUG(D_INODE,"clone ino %ld\n",cache_inode->i_ino);
@@ -354,56 +333,22 @@ static int clonefs_readdir(struct file *file, void *dirent,
 	}
 	clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
 	iput(cache_inode);
-        EXIT;
-	return result;
+	RETURN(result);
 }
 
-struct file_operations clonefs_dir_file_operations = {
-        NULL,                   /* lseek */
-        NULL,                   /* read -- bad */
-        NULL,                   /* write */
-        clonefs_readdir,        /* readdir */
-        NULL,                   /* select */
-        NULL,                   /* ioctl */
-        NULL,                   /* mmap */
-        NULL,                   /* open */
-	NULL,
-        NULL,                   /* release */
-	NULL,                   /* fsync */
-        NULL,                   
-	NULL,
-	NULL
+struct file_operations clonefs_dir_file_ops = {
+	readdir:	clonefs_readdir,        /* readdir */
 };
 
-struct inode_operations clonefs_dir_inode_operations =
-{
-	&clonefs_dir_file_operations,
-	NULL,	        /* create */
-	clonefs_lookup,   /* lookup */
-	NULL,	        /* link */
-	NULL,           /* unlink */
-	NULL,	        /* symlink */
-	NULL,	        /* mkdir */
-	NULL,           /* rmdir */
-	NULL,	        /* mknod */
-	NULL,	        /* rename */
-	NULL,           /* readlink */
-	NULL,           /* follow_link */
-	NULL,           /* readpage */
-	NULL,           /* writepage */
-	NULL,	        /* bmap */
-	NULL,	        /* truncate */
-	NULL,	        /* permission */
-	NULL,           /* smap */
-	NULL,           /* update page */
-        NULL,           /* revalidate */
+struct inode_operations clonefs_dir_inode_ops = {
+	lookup:		clonefs_lookup,   /* lookup */
 };
 
 
 /* ***************** end of clonefs dir ops *******************  */ 
 /* ***************** begin clonefs file ops *******************  */ 
 
-int clonefs_readpage(struct file *file, struct page *page)
+static int clonefs_readpage(struct file *file, struct page *page)
 {
 	int result = 0;
 	struct inode *cache_inode;
@@ -417,8 +362,7 @@ int clonefs_readpage(struct file *file, struct page *page)
         cache_inode = clonefs_get_inode(file->f_dentry->d_inode); 
 	if (!cache_inode) {
 		make_bad_inode(file->f_dentry->d_inode);
-		EXIT;
-		return -ENOMEM;
+		RETURN(-ENOMEM);
 	}
 
 	clonefs_prepare_snapfile(inode, file, cache_inode, &open_file,
@@ -429,65 +373,28 @@ int clonefs_readpage(struct file *file, struct page *page)
 	/* potemkin case: we are handed a directory inode */
 	down(&cache_inode->i_sem);
         /* XXX - readpage NULL on directories... */
-        if (cache_inode->i_op->readpage == NULL)
-                printk("Yes, Grigori, directories are a problem.\n");
-        else
-	        cache_inode->i_op->readpage(&open_file, page);
+        result = cache_inode->i_mapping->a_ops->readpage(&open_file, page);
+
 	up(&cache_inode->i_sem);
 	clonefs_restore_snapfile(inode, file, cache_inode, &open_file);
 	iput(cache_inode);
-        EXIT;
-	return result;
+	RETURN(result);
 }
 
-
-struct file_operations clonefs_file_file_operations = {
-        NULL,                   /* lseek */
-        generic_file_read,      /* read -- bad */
-        NULL,                   /* write */
-        NULL,                   /* readdir */
-        NULL,                   /* select */
-        NULL,                   /* ioctl */
-        generic_file_mmap,      /* mmap */
-        NULL,                   /* open */
-	NULL,
-        NULL,                   /* release */
-	NULL,                   /* fsync */
-        NULL,                   
-	NULL,
-	NULL
+struct file_operations clonefs_file_file_ops = {
+	read:	generic_file_read,      /* read -- bad */
+	mmap:	generic_file_mmap,      /* mmap */
 };
 
-struct inode_operations clonefs_file_inode_operations =
-{
-	&clonefs_file_file_operations,
-	NULL,	        /* create */
-	NULL,           /* lookup */
-	NULL,	        /* link */
-	NULL,           /* unlink */
-	NULL,	        /* symlink */
-	NULL,	        /* mkdir */
-	NULL,           /* rmdir */
-	NULL,	        /* mknod */
-	NULL,	        /* rename */
-	NULL,           /* readlink */
-	NULL,           /* follow_link */
-	clonefs_readpage, /* readpage */
-	NULL,           /* writepage */
-	NULL,	        /* bmap */
-	NULL,	        /* truncate */
-	NULL,	        /* permission */
-	NULL,           /* smap */
-	NULL,           /* update page */
-        NULL,           /* revalidate */
+struct address_space_operations clonefs_file_address_ops = {
+        readpage:       clonefs_readpage
 };
 
 
-
 /* ***************** end of clonefs file ops *******************  */ 
 /* ***************** begin clonefs symlink ops *******************  */ 
 
-int clonefs_readlink(struct dentry *dentry, char *buf, int len)
+static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 {
 	int res;
 	struct inode * cache_inode;
@@ -501,12 +408,11 @@ int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 
 	if ( ! cache_inode ) {
 		CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-		EXIT;
-		return res;	
+		RETURN(res);	
 	}
 	
 	/* XXX: shall we allocate a new dentry ? 
-		The following is safe for ext2, etc. because ext2_readlink only
+		The following is safe for ext3, etc. because ext2_readlink only
 		use the inode info */
 
 	/* save the old dentry inode */	
@@ -525,26 +431,21 @@ int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 
 	iput(cache_inode);
 
-	EXIT;
-	return res;
+	RETURN(res);
 }
 
-struct dentry * clonefs_follow_link(struct dentry * dentry,
-                                        struct dentry *base,
-                                        unsigned int follow)
+static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 {
-	struct dentry * res;
 	struct inode * cache_inode;
 	struct inode * old_inode;
+	int    res;
 
 	ENTRY;
-	res = ERR_PTR(-ENOENT);
 
 	cache_inode = clonefs_get_inode(dentry->d_inode); 
 	if ( ! cache_inode ) {
 		CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-		EXIT;
-		return res;	
+		RETURN(-ENOENT);	
 	}
 
 	/* XXX: shall we allocate a new dentry ? 
@@ -557,7 +458,7 @@ struct dentry * clonefs_follow_link(struct dentry * dentry,
 	dentry->d_inode = cache_inode;
 
 	if ( cache_inode->i_op->follow_link ) {
-		res = cache_inode->i_op->follow_link(dentry, base, follow); 
+		res = cache_inode->i_op->follow_link(dentry, nd); 
 	}
 
 	/* restore the old inode */
@@ -565,32 +466,16 @@ struct dentry * clonefs_follow_link(struct dentry * dentry,
 
 	iput(cache_inode);
 
-	EXIT;
-	return res;
+	RETURN(res);
 }
 
-struct inode_operations clonefs_symlink_inode_operations =
+struct inode_operations clonefs_symlink_inode_ops =
 {
-	NULL,               /* no file operations */      
-	NULL,	            /* create */                  
-	NULL,               /* lookup */                  
-	NULL,	            /* link */                    
-	NULL,               /* unlink */                  
-	NULL,	            /* symlink */                 
-	NULL,	            /* mkdir */                   
-	NULL,               /* rmdir */                   
-	NULL,	            /* mknod */                   
-	NULL,	            /* rename */                  
-	clonefs_readlink,   /* readlink */              
-	clonefs_follow_link,/* follow_link */             
-	NULL,               /* readpage */                
-	NULL,               /* writepage */               
-	NULL,	            /* bmap */                    
-	NULL,	            /* truncate */                
-	NULL,	            /* permission */              
-	NULL,               /* smap */                    
-	NULL,               /* update page */             
-        NULL,               /* revalidate */          
+	/*FIXME later getxattr, listxattr, 
+	 * other method need to be replaced too 
+	 * */  
+	readlink:	clonefs_readlink,   /* readlink */              
+	follow_link:	clonefs_follow_link,/* follow_link */             
 };
 
 
diff --git a/lustre/snapfs/dcache.c b/lustre/snapfs/dcache.c
index 88ce4bb54c37400d3a8a2a9369eeab3a88ebc342..cf4337d46be4ffd5ffac9bb39a25912c74641284 100644
--- a/lustre/snapfs/dcache.c
+++ b/lustre/snapfs/dcache.c
@@ -2,20 +2,20 @@
  * Directory operations for SnapFS filesystem
  */
 
-#include <linux/types.h>
+#define DEBUG_SUBSYSTEM S_SNAP
+
+#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
 #include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 /* called when a cache lookup succeeds */
 
@@ -45,7 +45,7 @@ static int currentfs_dentry_revalidate(struct dentry *de, int flag)
 		return 0;
 	}
 #else 
-	return 1;
+	RETURN(1);
 #endif
 }
 
diff --git a/lustre/snapfs/dir.c b/lustre/snapfs/dir.c
index 0b83fa147c616d1a464297d2510900ba3268efd6..a1636f2bc32432ceb6c4af50e727848f8e055082 100644
--- a/lustre/snapfs/dir.c
+++ b/lustre/snapfs/dir.c
@@ -1,30 +1,19 @@
 /*
  * dir.c
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#define EXPORT_SYMTAB
-
-
-#define __NO_VERSION__
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
-
-#ifdef CONFIG_SNAPFS_EXT3
-void ext3_orphan_del(handle_t *handle, struct inode *inode);
-#endif
+#include "snapfs_internal.h" 
 
 static ino_t get_parent_ino(struct inode * inode)
 {
@@ -32,7 +21,7 @@ static ino_t get_parent_ino(struct inode * inode)
 	struct dentry * dentry;
 
 	if (list_empty(&inode->i_dentry)) {
-       		printk("snapfs ERROR: no dentry for ino %lu\n", inode->i_ino);
+       		CERROR("No dentry for ino %lu\n", inode->i_ino);
                 return 0;
         }
 
@@ -69,8 +58,7 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
 	cache = snap_find_cache(dir->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return ERR_PTR(-EINVAL);
+		RETURN(ERR_PTR(-EINVAL));
 	}
 
 	if ( dentry->d_name.len == strlen(".snap") &&
@@ -80,30 +68,27 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
 		/* Don't permit .snap in clonefs */
 		if( dentry->d_sb != cache->cache_sb )
-			return ERR_PTR(-ENOENT);
+			RETURN(ERR_PTR(-ENOENT));
 
 		/* Don't permit .snap under .snap */
 		if( currentfs_is_under_dotsnap(dentry) )
-			return ERR_PTR(-ENOENT);
+			RETURN(ERR_PTR(-ENOENT));
 
 		ino = 0xF0000000 | dir->i_ino;
 		snap = iget(dir->i_sb, ino);
 		CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", snap->i_ino, snap->i_mode);
 		d_add(dentry, snap);
-		EXIT;
-		return NULL;
+		RETURN(NULL);
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
 	if (!iops || !iops->lookup) {
-		EXIT;
-		return ERR_PTR(-EINVAL);
+		RETURN(ERR_PTR(-EINVAL));
 	}
 
 	rc = iops->lookup(dir, dentry);
 	if ( rc || !dentry->d_inode) {
-		EXIT;
-		return NULL;
+		RETURN(NULL);
 	}
 	
 	/*
@@ -144,8 +129,7 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 			dentry->d_fsdata = (void*)pri_ino;
 	}
 
-	EXIT;
-	return NULL;
+	RETURN(NULL);
 
 #if 0
 	/* XXX: PJB these need to be set up again. See dcache.c */
@@ -159,70 +143,71 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
 err_out:
 	d_unadd_iput(dentry);
-	EXIT;
-	return ERR_PTR(-EINVAL);
+	RETURN(ERR_PTR(-EINVAL));
 }
 
 static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct snap_cache *cache;
-	int rc;
+	struct snap_cache 	*cache;
 	struct inode_operations *iops;
-	void *handle = NULL;
+	struct snapshot_operations *snapops;	
+	void 			*handle = NULL;
+	int 			rc;
 
 	ENTRY;
 
 	if (currentfs_is_under_dotsnap(dentry)) {
-		EXIT;
-		return -EPERM;
+		RETURN(-EPERM);
 	}
 
 	cache = snap_find_cache(dir->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
+	snapops = filter_c2csnapops(cache->cache_filter);
+	if (!snapops || !snapops->get_generation) 
+		RETURN(-EINVAL);
+
 	handle = snap_trans_start(cache, dir, SNAP_OP_CREATE);
 
 	if ( snap_needs_cow(dir) != -1 ) {
-		printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1);
-		snap_do_cow(dir, get_parent_ino(dir), 0);
+		if (!(snap_do_cow(dir, get_parent_ino(dir), 0))) {
+			CERROR("Do cow error\n");
+			RETURN(-EINVAL);
+		}
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->create) {
-		rc = -EINVAL;
-		goto exit;
+	if (!iops || !iops->create) {
+		RETURN(-EINVAL);
 	}
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 2);
 	rc = iops->create(dir, dentry, mode);
 
 	/* XXX now set the correct snap_{file,dir,sym}_iops */
-        if ( ! dentry->d_inode) {
-                printk("Error in currentfs_create, dentry->d_inode is NULL\n");
-                goto exit;
+        if (!dentry->d_inode) {
+                CERROR("Error in currentfs_create, dentry->d_inode is NULL\n");
+                GOTO(exit, 0);
         }
 
-	if ( S_ISDIR(dentry->d_inode->i_mode) )
+	if (S_ISDIR(dentry->d_inode->i_mode))
                 dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
-        else if ( S_ISREG(dentry->d_inode->i_mode) ) {
-                if ( !filter_c2cfiops(cache->cache_filter) ) {
-                        filter_setup_file_ops(cache->cache_filter,
-                                dentry->d_inode->i_op, &currentfs_file_iops);
+        else if (S_ISREG(dentry->d_inode->i_mode)) {
+                if (!filter_c2cfiops(cache->cache_filter)) {
+                        filter_setup_file_ops(cache->cache_filter, dentry->d_inode,
+                                	      &currentfs_file_iops, &currentfs_file_fops,
+					      &currentfs_file_aops);
                 }
                 dentry->d_inode->i_op = filter_c2ufiops(cache->cache_filter);
         }
-	printk("inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
-
+	CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 3);
-	
-exit:
+	init_filter_data(dentry->d_inode, snapops, 0); exit:
 	snap_trans_commit(cache, handle);
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
@@ -235,27 +220,24 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	ENTRY;
 
 	if (currentfs_is_under_dotsnap(dentry)) {
-		EXIT;
-		return -EPERM;
+		RETURN(-EPERM);
 	}
 
 	cache = snap_find_cache(dir->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	handle = snap_trans_start(cache, dir, SNAP_OP_MKDIR);
 
 	if ( snap_needs_cow(dir) != -1 ) {
-		CDEBUG(D_FILE, "snap_needs_cow for ino %lu \n",dir->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 1);
 		snap_do_cow(dir, get_parent_ino(dir), 0);
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->mkdir) {
+	if (!iops || !iops->mkdir) {
 		rc = -EINVAL;
 		goto exit;
 	}
@@ -269,17 +251,16 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 	/* XXX now set the correct snap_{file,dir,sym}_iops */
         if ( dentry->d_inode) {
                 dentry->d_inode->i_op = filter_c2udiops(cache->cache_filter);
-	        printk("inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
+	        CDEBUG(D_INODE, "inode %lu, i_op %p\n", dentry->d_inode->i_ino, dentry->d_inode->i_op);
         } else {
-                printk("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
+                CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
         }
 
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3);
 	
 exit:
 	snap_trans_commit(cache, handle);
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 static int currentfs_link (struct dentry * old_dentry, struct inode * dir, 
@@ -292,44 +273,37 @@ static int currentfs_link (struct dentry * old_dentry, struct inode * dir,
 
 	ENTRY;
 
-	if (currentfs_is_under_dotsnap(dentry)) {
-		EXIT;
-		return -EPERM;
-	}
+	if (currentfs_is_under_dotsnap(dentry)) 
+		RETURN(-EPERM);
 
 	cache = snap_find_cache(dir->i_dev);
-	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
-	}
+	if ( !cache )  
+		RETURN(-EINVAL);
 
 	handle = snap_trans_start(cache, dir, SNAP_OP_LINK);
 
 	if ( snap_needs_cow(dir) != -1 ) {
-		printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 1);
 		snap_do_cow(dir, get_parent_ino(dir), 0);
 	}
         if ( snap_needs_cow(old_dentry->d_inode) != -1 ) {
-		printk("snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",old_dentry->d_inode->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
 		snap_do_cow(old_dentry->d_inode, dir->i_ino, 0);
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->link) {
-		rc = -EINVAL;
-		goto exit;
-	}
+
+	if (!iops || !iops->link) 
+		GOTO(exit, rc = -EINVAL);
+	
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 2);
 	rc = iops->link(old_dentry,dir, dentry);
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_LINK, 3);
-	
 exit:
 	snap_trans_commit(cache, handle);
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 static int currentfs_symlink(struct inode *dir, struct dentry *dentry, 
@@ -343,33 +317,28 @@ static int currentfs_symlink(struct inode *dir, struct dentry *dentry,
 	ENTRY;
 
 	cache = snap_find_cache(dir->i_dev);
-	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
-	}
+	if (!cache)  
+		RETURN(-EINVAL);
 
 	handle = snap_trans_start(cache, dir, SNAP_OP_SYMLINK);
 
 	if ( snap_needs_cow(dir) != -1 ) {
-		printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 1);
 		snap_do_cow(dir, get_parent_ino(dir), 0);
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->symlink) {
-		rc = -EINVAL;
-		goto exit;
-	}
+	if (!iops || !iops->symlink) 
+		GOTO(exit, rc = -EINVAL);
+
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 2);
 	rc = iops->symlink(dir, dentry, symname);
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3);
 	
 exit:
 	snap_trans_commit(cache, handle);
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode, 
@@ -383,30 +352,26 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 	ENTRY;
 
 	if (currentfs_is_under_dotsnap(dentry)) {
-		EXIT;
-		return -EPERM;
+		RETURN(-EPERM);
 	}
 
 	cache = snap_find_cache(dir->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	handle = snap_trans_start(cache, dir, SNAP_OP_MKNOD);
 
 	if ( snap_needs_cow(dir) != -1 ) {
-		printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 1);
 		snap_do_cow(dir, get_parent_ino(dir), 0);
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->mknod) {
-		rc = -EINVAL;
-		goto exit;
-	}
+	if (!iops || !iops->mknod) 
+		GOTO(exit, rc = -EINVAL);
+
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2);
 	rc = iops->mknod(dir, dentry, mode, rdev);
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3);
@@ -415,8 +380,7 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
 exit:
 	snap_trans_commit(cache, handle);
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
@@ -436,30 +400,25 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
 	ENTRY;
 
 	if (currentfs_is_under_dotsnap(dentry)) {
-		EXIT;
-		return -EPERM;
+		RETURN(-EPERM);
 	}
 
 	cache = snap_find_cache(dir->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	handle = snap_trans_start(cache, dir, SNAP_OP_RMDIR);
 
 	if ( snap_needs_cow(dir) != -1 ) {
-		printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 1);
 		snap_do_cow(dir, get_parent_ino(dir), 0);
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->rmdir) {
-		rc = -EINVAL;
-		goto exit;
-	}
+	if (!iops || !iops->rmdir) 
+		GOTO(exit, rc = -EINVAL);
 
 	/* XXX : there are two cases that we can't remove this inode from disk. 
 		1. the inode needs to be cowed. 
@@ -468,17 +427,12 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
 		will not be deleted after rmdir, will only remove dentry 
 	*/
 
-	if( snap_needs_cow(dentry->d_inode) != -1) {
+	if (snap_needs_cow(dentry->d_inode) != -1 || 
+	    snap_is_redirector(dentry->d_inode)) {
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 2);
-		snap_do_cow (dentry->d_inode, dir->i_ino, 
-				SNAP_DEL_PRI_WITHOUT_IND);
+		snap_do_cow (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI);
 		keep_inode = 1;
 	}
-	else if( snap_is_redirector(dentry->d_inode) ) {
-		snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 3);
-		snap_do_cow(dentry->d_inode, dir->i_ino, SNAP_DEL_PRI_WITH_IND);
-		keep_inode = 1;
-	}	
 #if 0
 	if ( keep_inode ) {	
        		printk("set up dentry ops, before %p\n",dentry->d_op);
@@ -499,8 +453,7 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
 	//	i_ctime = dentry->d_inode->i_ctime;
 		i_nlink = dentry->d_inode->i_nlink;
 		i_size = dentry->d_inode->i_size;
-	
-}
+	}
 
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 4);
 	rc = iops->rmdir(dir, dentry);
@@ -534,7 +487,6 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
 			snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6);
 		}
 	}
-
 exit:
 	snap_trans_commit(cache, handle);
 	EXIT;
@@ -552,27 +504,24 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
 	ENTRY;
 
 	if (currentfs_is_under_dotsnap(dentry)) {
-		EXIT;
-		return -EPERM;
+		RETURN(-EPERM);
 	}
 
 	cache = snap_find_cache(dir->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	handle = snap_trans_start(cache, dir, SNAP_OP_UNLINK);
 
 	if ( snap_needs_cow(dir) != -1 ) {
-		printk("snap_needs_cow for ino %lu \n",dir->i_ino);
+		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 1);
 		snap_do_cow(dir, get_parent_ino(dir), 0);
 	}
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->unlink) {
+	if (!iops || !iops->unlink) {
 		rc = -EINVAL;
 		goto exit;
 	}
@@ -588,18 +537,17 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
 	if( snap_needs_cow (inode) != -1) {
 		/* call snap_do_cow with DEL_WITHOUT_IND option */
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 2);
-		snap_do_cow(inode, dir->i_ino,SNAP_DEL_PRI_WITHOUT_IND);
+		snap_do_cow(inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
 		if( inode->i_nlink == 1 )
 			inode->i_nlink++;
-	}
-	else if( snap_is_redirector (inode) && inode->i_nlink == 1 ) {
+	} else if (snap_is_redirector (inode) && inode->i_nlink == 1) {
 		/* call snap_do_cow with DEL_WITH_IND option 
 		 * just free the blocks of inode, not really delete it
 		 */
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 3);
-		snap_do_cow (inode, dir->i_ino, SNAP_DEL_PRI_WITH_IND);
+		snap_do_cow (inode, dir->i_ino, SNAP_CREATE_IND_DEL_PRI);
 		inode->i_nlink++;
-	}	
+	}
 
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_UNLINK, 4);
 	rc = iops->unlink(dir, dentry);
@@ -607,8 +555,7 @@ static int currentfs_unlink(struct inode *dir, struct dentry *dentry)
 
 exit:
 	snap_trans_commit(cache, handle);
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
@@ -623,26 +570,24 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
 
 	if (currentfs_is_under_dotsnap(old_dentry) ||
 	    currentfs_is_under_dotsnap(new_dentry)) {
-		EXIT;
-		return -EPERM;
+		RETURN(-EPERM);
 	}
 
 	cache = snap_find_cache(old_dir->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	handle = snap_trans_start(cache, old_dir, SNAP_OP_RENAME);
        
         /* Always cow the old dir and old dentry->d_inode */ 
 	if ( snap_needs_cow(old_dir) != -1 ) {
-		printk("rename: needs_cow for old_dir %lu\n",old_dir->i_ino);
+		CDEBUG(D_INODE, "rename: needs_cow for old_dir %lu\n",old_dir->i_ino);
 		snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 1);
 		snap_do_cow(old_dir, get_parent_ino(old_dir), 0);
 	}
 	if( snap_needs_cow (old_dentry->d_inode) != -1) {
-		printk("rename: needs_cow for old_dentry, ino %lu\n",
+		CDEBUG(D_INODE, "rename: needs_cow for old_dentry, ino %lu\n",
                        old_dentry->d_inode->i_ino);
 		snap_debug_device_fail(old_dir->i_dev, SNAP_OP_RENAME, 2);
 		snap_do_cow(old_dentry->d_inode, old_dir->i_ino,0);
@@ -654,10 +599,10 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
          */
 	if(( old_dir != new_dir) ) {
 		if( snap_needs_cow(new_dir) !=-1 ){
-			printk("rename:snap_needs_cow for new_dir %lu\n",
+			CDEBUG(D_INODE, "rename:snap_needs_cow for new_dir %lu\n",
 				new_dir->i_ino);
 			snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,3);
-			snap_do_cow(new_dir, get_parent_ino(new_dir),0);	
+			snap_do_cow(new_dir, get_parent_ino(new_dir), 0);	
 		}
 	}
 
@@ -681,7 +626,7 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
         		/* call snap_do_cow with DEL_WITHOUT_IND option */
 	        	snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
 	                snap_do_cow(new_dentry->d_inode, new_dir->i_ino,
-                                    SNAP_DEL_PRI_WITHOUT_IND);
+                                    SNAP_CREATE_IND_DEL_PRI);
 	                new_dentry->d_inode->i_nlink++;
 	        }
 	        else if( snap_is_redirector (new_dentry->d_inode) ) {
@@ -690,14 +635,13 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
 	        	 */
 		        snap_debug_device_fail(old_dir->i_dev,SNAP_OP_RENAME,4);
 	        	snap_do_cow (new_dentry->d_inode, new_dir->i_ino, 
-                                     SNAP_DEL_PRI_WITH_IND);
+                                     SNAP_CREATE_IND_DEL_PRI);
 	        	new_dentry->d_inode->i_nlink++;
 	       	}	
         }
 
 	iops = filter_c2cdiops(cache->cache_filter); 
-	if (!iops ||
-	    !iops->rename) {
+	if (!iops || !iops->rename) {
 		rc = -EINVAL;
 		goto exit;
 	}
@@ -708,8 +652,7 @@ static int currentfs_rename (struct inode * old_dir, struct dentry *old_dentry,
 
 exit:
 	snap_trans_commit(cache, handle);
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 static int currentfs_readdir(struct file *filp, void *dirent,
@@ -721,19 +664,16 @@ static int currentfs_readdir(struct file *filp, void *dirent,
 	
 	ENTRY;
 	if( !filp || !filp->f_dentry || !filp->f_dentry->d_inode ) {
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 	fops = filter_c2cdfops( cache->cache_filter );
 	if( !fops ) {
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	/*
@@ -745,7 +685,7 @@ static int currentfs_readdir(struct file *filp, void *dirent,
 		if( filp->f_pos == 0 ){
 			if( filldir(dirent, ".snap",
 				    strlen(".snap")+1, filp->f_pos,
-				    0xF0000000|filp->f_dentry->d_inode->i_ino) ){
+				    -1, 0) ){
 				return -EINVAL;
 			}
 			filp->f_pos += strlen(".snap")+1;
@@ -756,7 +696,7 @@ static int currentfs_readdir(struct file *filp, void *dirent,
 	}else
 		rc = fops->readdir(filp, dirent, filldir);
 
-	return rc;
+	RETURN(rc);
 }
 
 struct file_operations currentfs_dir_fops = {
@@ -764,14 +704,13 @@ struct file_operations currentfs_dir_fops = {
 };
 
 struct inode_operations currentfs_dir_iops = { 
-	default_file_ops: &currentfs_dir_fops,
-	create: currentfs_create,
-	mkdir: currentfs_mkdir,
-	link: currentfs_link,
-	symlink: currentfs_symlink,
-	mknod: currentfs_mknod,
-	rmdir: currentfs_rmdir,
-	unlink: currentfs_unlink,
-	rename: currentfs_rename,
-	lookup:	currentfs_lookup
+	create: 	currentfs_create,
+	mkdir: 		currentfs_mkdir,
+	link: 		currentfs_link,
+	symlink: 	currentfs_symlink,
+	mknod: 		currentfs_mknod,
+	rmdir: 		currentfs_rmdir,
+	unlink: 	currentfs_unlink,
+	rename: 	currentfs_rename,
+	lookup:		currentfs_lookup
 };
diff --git a/lustre/snapfs/dotsnap.c b/lustre/snapfs/dotsnap.c
index 19dfc1ca2dc7f02409a6ffca9bbafdc3809150be..62c026de016a8fde3d653a41937b6741ce301fa7 100644
--- a/lustre/snapfs/dotsnap.c
+++ b/lustre/snapfs/dotsnap.c
@@ -2,25 +2,19 @@
  * dotsnap.c - support for .snap directories
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include "snapfs_internal.h" 
 
 struct inode_operations dotsnap_inode_operations;
 struct file_operations dotsnap_file_operations;
@@ -38,8 +32,7 @@ int currentfs_is_under_dotsnap(struct dentry *de)
 		de = de->d_parent;
 	}
 
-	EXIT;
-	return 0;
+	RETURN(0);
 }
 
 void currentfs_dotsnap_read_inode(struct snap_cache *cache, 
@@ -76,41 +69,39 @@ struct dentry *dotsnap_lookup(struct inode *dir,  struct dentry *dentry)
 
 	cache = snap_find_cache(dir->i_dev);
 	if ( !cache ) {
-		printk("dotsnap_readdir: cannot find cache\n");
+		CERROR("dotsnap_readdir: cannot find cache\n");
 		make_bad_inode(dir);
-		EXIT;
-		return ERR_PTR(-EINVAL);
+		RETURN(ERR_PTR(-EINVAL));
 	}
 
 	snapops = filter_c2csnapops(cache->cache_filter);
 	if (!snapops || !snapops->get_indirect_ino) {
-                EXIT;
-                return ERR_PTR(-EINVAL);
+                RETURN(ERR_PTR(-EINVAL));
         }
 
 	tableno = cache->cache_snap_tableno; 
 	table = &snap_tables[tableno];
 
 	if( table->tbl_count <= 1 )
-		return NULL;
+		RETURN(NULL);
 	
-	index = table->tbl_index[0]; 
+	index = table->snap_items[0].index;; 
 	for ( i = 1 ; i < table->tbl_count ; i++ ) {
-		if ( (dentry->d_name.len == strlen(table->tbl_name[i])) &&
-		     (memcmp(dentry->d_name.name, table->tbl_name[i], 
+		if ( (dentry->d_name.len == strlen(table->snap_items[i].name)) &&
+		     (memcmp(&dentry->d_name.name[0], &table->snap_items[i].name[0], 
 			     dentry->d_name.len) == 0) ) {
-			index = table->tbl_index[i]; 
+			index = table->snap_items[i].index; 
 			break;
 		}
 	}
 	
 	if( i >= table->tbl_count )
-		return ERR_PTR(-ENOENT);
+		RETURN(ERR_PTR(-ENOENT));
 
 	inode = iget(dir->i_sb, dir->i_ino & (~0xF0000000));
 
         if ( !inode ) 
-                return ERR_PTR(-EINVAL);
+                RETURN(ERR_PTR(-EINVAL));
 
 	ino =  snapops->get_indirect_ino(inode, index);
 	iput(inode); 
@@ -120,15 +111,15 @@ struct dentry *dotsnap_lookup(struct inode *dir,  struct dentry *dentry)
 	}
 
 	if ( ino == -EINVAL ) {
-		return ERR_PTR(-EINVAL);
+		RETURN(ERR_PTR(-EINVAL));
 	}
-CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
+	CDEBUG(D_INODE, "index %d, ino is %lu\n",index, ino);
 
 	inode = iget(dir->i_sb, ino);
 	d_add(dentry, inode); 
 	dentry->d_fsdata = (void*)index;
 	inode->i_op = dentry->d_parent->d_parent->d_inode->i_op;
-	return NULL;
+	RETURN(NULL);
 }
 
 
@@ -145,55 +136,47 @@ static int dotsnap_readdir(struct file * filp,
 
 	cache = snap_find_cache(filp->f_dentry->d_inode->i_dev);
 	if ( !cache ) {
-		printk("dotsnap_readdir: cannot find cache\n");
+		CDEBUG(D_INODE, "dotsnap_readdir: cannot find cache\n");
 		make_bad_inode(filp->f_dentry->d_inode);
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 
 	snapops = filter_c2csnapops(cache->cache_filter);
 	if (!snapops || !snapops->get_indirect_ino) {
-                EXIT;
-                return -EINVAL;
+                RETURN(-EINVAL);
         }
 
 	tableno = cache->cache_snap_tableno; 
 	table = &snap_tables[tableno];
-	CDEBUG(D_INODE, "\n");	
 	for (i = filp->f_pos ; i < table->tbl_count -1 ; i++) {
 		int index;
 		struct inode *inode;
 		ino_t ino;
 
-		CDEBUG(D_INODE, "%d\n",i);	
 
 		inode = filp->f_dentry->d_inode;
-		index = table->tbl_index[i+1];
+		index = table->snap_items[i+1].index;
 		ino =  snapops->get_indirect_ino 
 			(filp->f_dentry->d_inode, index);
 
-		CDEBUG(D_INODE, "\n");	
-
 		if ( ino == -ENOATTR || ino == 0 ) {
 			ino = filp->f_dentry->d_parent->d_inode->i_ino;
 		}
-
-		CDEBUG(D_INODE, "\n");	
+		
 		if ( ino == -EINVAL ) {
 			return -EINVAL;
 		}
 
-		CDEBUG(D_INODE, "Listing %s\n", table->tbl_name[i+1]);	
-		if (filldir(dirent, table->tbl_name[i+1],
-			    strlen(table->tbl_name[i+1]),
-			    filp->f_pos, ino) < 0){
+		CDEBUG(D_INODE, "Listing %s\n", &table->snap_items[i+1].name[0]);	
+		if (filldir(dirent, &table->snap_items[i+1].name[0],
+			    strlen(&table->snap_items[i+1].name[0]),
+			    filp->f_pos, ino, 0) < 0){
 			CDEBUG(D_INODE, "\n");
 			break;
 		}
 		filp->f_pos++;
 	}
-	EXIT;
-	return 0;
+	RETURN(0);
 }
 
 
@@ -203,6 +186,5 @@ struct file_operations dotsnap_file_operations = {
 
 struct inode_operations dotsnap_inode_operations =
 {
-	default_file_ops: &dotsnap_file_operations,
 	lookup: dotsnap_lookup
 };
diff --git a/lustre/snapfs/file.c b/lustre/snapfs/file.c
index 38c5652c5016e60e1e85bd891b1cd20dd229361c..c6795aa9fe490c8a321af817a5798f7f20efbe71 100644
--- a/lustre/snapfs/file.c
+++ b/lustre/snapfs/file.c
@@ -2,25 +2,19 @@
  * file.c
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include "snapfs_internal.h" 
 
 /* instantiate a file handle to the cache file */
 static void currentfs_prepare_snapfile(struct inode *inode,
@@ -29,17 +23,13 @@ static void currentfs_prepare_snapfile(struct inode *inode,
 				     struct file *cache_file,
 				     struct dentry *cache_dentry)
 {
-	ENTRY;
         cache_file->f_pos = clone_file->f_pos;
         cache_file->f_mode = clone_file->f_mode;
         cache_file->f_flags = clone_file->f_flags;
         cache_file->f_count  = clone_file->f_count;
         cache_file->f_owner  = clone_file->f_owner;
-	cache_file->f_op = cache_inode->i_op->default_file_ops;
 	cache_file->f_dentry = cache_dentry;
         cache_file->f_dentry->d_inode = cache_inode;
-	EXIT;
-        return ;
 }
 
 /* update the currentfs file struct after IO in cache file */
@@ -48,10 +38,7 @@ static void currentfs_restore_snapfile(struct inode *cache_inode,
 				   struct inode *clone_inode,
 				   struct file *clone_file)
 {
-	ENTRY;
         cache_file->f_pos = clone_file->f_pos;
-	EXIT;
-        return;
 }
 
 
@@ -67,41 +54,34 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
 	struct snap_table *table;
 	int slot = 0;
 	int index = 0;
-	struct inode_operations *ciops;
+	struct address_space_operations *aops;
 	struct inode *cache_inode = NULL;
 	struct snapshot_operations *snapops;
   
 	ENTRY;
 
-	if (currentfs_is_under_dotsnap(filp->f_dentry)) {
-		EXIT;
-		return -ENOSPC;
-	}
+	if (currentfs_is_under_dotsnap(filp->f_dentry)) 
+		RETURN(-ENOSPC);
 
         cache = snap_find_cache(inode->i_dev);
-        if ( !cache ) { 
-                EXIT;
-                return -EINVAL;
-        }
+        if ( !cache ) 
+                RETURN(-EINVAL);
 
         if ( snap_needs_cow(inode) != -1 ) {
-                CDEBUG(D_FILE, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
                 snap_do_cow(inode, filp->f_dentry->d_parent->d_inode->i_ino, 0);
 	}
 
         fops = filter_c2cffops(cache->cache_filter); 
-        if (!fops ||
-            !fops->write) {
-                EXIT;
-                return -EINVAL;
-        }
+        if (!fops || !fops->write) 
+                RETURN(-EINVAL);
 
         if (filp->f_flags & O_APPEND)
                 pos = inode->i_size;
         else {
                 pos = *ppos;
                 if (pos != *ppos)
-                        return -EINVAL;
+                        RETURN(-EINVAL);
         }
 
 	/*
@@ -115,41 +95,38 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
 		block[1] = pos >> inode->i_sb->s_blocksize_bits;
 	if( block[0] == block[1] )
 		block[1] = -1;
-
-	ciops = filter_c2cfiops(cache->cache_filter);
+	
+	aops = filter_c2cfaops(cache->cache_filter);
 	snapops = filter_c2csnapops(cache->cache_filter);
 
 	for( i=0; i<2; i++ ){
-		if( block[i]!=-1 && !ciops->bmap(inode, block[i]) ) {
+		if(block[i]!=-1 && aops->bmap(inode->i_mapping, block[i])) {
 			table = &snap_tables[cache->cache_snap_tableno];
-        		for (slot = table->tbl_count ; slot >= 1; slot--)
-        		{
+        		for (slot = table->tbl_count ; slot >= 1; slot--) {
+				struct address_space_operations *c_aops = 
+					cache_inode->i_mapping->a_ops;
 				cache_inode = NULL;
-                		index = table->tbl_index[slot];
+                		index = table->snap_items[slot].index;
 				cache_inode = snap_get_indirect(inode, NULL, index);
 
 				if ( !cache_inode )  continue;
 
-	                	if (cache_inode->i_op->bmap(cache_inode, block[i])) {
-					CDEBUG(D_FILE, "find cache_ino %lu\n",
+	                	if (c_aops->bmap(cache_inode->i_mapping, block[i])) {
+					CDEBUG(D_SNAP, "find cache_ino %lu\n",
 						cache_inode->i_ino);
 					if( snapops && snapops->copy_block) {
-						snapops->copy_block( inode, 
+						snapops->copy_block(inode, 
 								cache_inode, block[i]);
 					}
-
 					iput(cache_inode);
                         		break;
                 		}
-                       		 iput(cache_inode);
+                       		iput(cache_inode);
         		}
 		}
 	}
-
         rc = fops->write(filp, buf, count, ppos);
-        
-        EXIT;
-        return rc;
+        RETURN(rc);
 }
 
 static int currentfs_readpage(struct file *file, struct page *page)
@@ -161,7 +138,7 @@ static int currentfs_readpage(struct file *file, struct page *page)
 	struct inode *cache_inode = NULL;
 	struct file open_file;
 	struct dentry open_dentry ;
-	struct inode_operations *ciops;
+	struct address_space_operations *c_aops;
 	struct snap_cache *cache;
  	long block;
 	struct snap_table *table;
@@ -173,21 +150,19 @@ static int currentfs_readpage(struct file *file, struct page *page)
 
 	cache = snap_find_cache(inode->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
+	
+	c_aops = filter_c2cfaops(cache->cache_filter);
 
-	ciops = filter_c2cfiops(cache->cache_filter);
-
-	block = page->offset >> inode->i_sb->s_blocksize_bits;
+	block = page->index >> inode->i_sb->s_blocksize_bits;
 
 	/* if there is a block in the cache, return the cache readpage */
-	if( inode->i_blocks && ciops->bmap(inode, block) ) {
-		CDEBUG(D_FILE, "block %lu in cache, ino %lu\n", 
+	if( inode->i_blocks && c_aops->bmap(inode->i_mapping, block) ) {
+		CDEBUG(D_SNAP, "block %lu in cache, ino %lu\n", 
 				block, inode->i_ino);
-		result = ciops->readpage(file, page);
-        	EXIT;
-		return result;
+		result = c_aops->readpage(file, page);
+		RETURN(result);
 	}
 
 	/*
@@ -197,7 +172,7 @@ static int currentfs_readpage(struct file *file, struct page *page)
 	if( file->f_dentry->d_fsdata ){
 		pri_inode = iget(inode->i_sb, (unsigned long)file->f_dentry->d_fsdata);
 		if( !pri_inode )
-			return -EINVAL;
+			RETURN(-EINVAL);
 		inode = pri_inode;
 		search_older = 1;
 	}
@@ -206,54 +181,55 @@ static int currentfs_readpage(struct file *file, struct page *page)
 
         for (slot = table->tbl_count ; slot >= 1; slot--)
         {
+		struct address_space_operations *c_aops = 
+					cache_inode->i_mapping->a_ops;
 		cache_inode = NULL;
-                index = table->tbl_index[slot];
+                index = table->snap_items[slot].index;
 		cache_inode = snap_get_indirect(inode, NULL, index);
 
-		if ( !cache_inode )  continue;
+		if (!cache_inode )  continue;
 
 		/* we only want slots between cache_inode to the oldest one */
-		if( search_older && cache_inode->i_ino == ind_ino )
+		if(search_older && cache_inode->i_ino == ind_ino )
 			search_older = 0;
 
-                if ( !search_older && cache_inode->i_op->bmap(cache_inode, block)) {
+                if (!search_older && c_aops->bmap(cache_inode->i_mapping, block)) 
                         break;
-                }
                 iput(cache_inode);
         }
 	if( pri_inode )
 		iput(pri_inode);
 
-	if ( !cache_inode ) { 
-		EXIT;
-		return -EINVAL;
-	}
+	if ( !cache_inode )  
+		RETURN(-EINVAL);
 
 	currentfs_prepare_snapfile(inode, file, cache_inode, &open_file,
 			      &open_dentry);
 
 	down(&cache_inode->i_sem);
 
-	if( ciops->readpage ) {
-		CDEBUG(D_FILE, "block %lu NOT in cache, use redirected ino %lu\n", block, cache_inode->i_ino );
-		result = ciops->readpage(&open_file, page);
+	if( c_aops->readpage ) {
+		CDEBUG(D_SNAP, "block %lu NOT in cache, use redirected ino %lu\n", 
+		       block, cache_inode->i_ino );
+		result = c_aops->readpage(&open_file, page);
 	}else {
-		CDEBUG(D_FILE, "cache ino %lu, readpage is NULL\n", 
-				cache_inode->i_ino);
+		CDEBUG(D_SNAP, "cache ino %lu, readpage is NULL\n", 
+		       cache_inode->i_ino);
 	}
-
 	up(&cache_inode->i_sem);
 	currentfs_restore_snapfile(inode, file, cache_inode, &open_file);
 	iput(cache_inode);
-        EXIT;
-	return result;
+	RETURN(result);
 }
-
+struct address_space_operations currentfs_file_aops = {
+	readpage:       currentfs_readpage,
+};
+                                                                                                                                                                                                     
 struct file_operations currentfs_file_fops = {
-	write:currentfs_write,
+	write:          currentfs_write,
 };
-
+                                                                                                                                                                                                     
 struct inode_operations currentfs_file_iops = {
-	default_file_ops: &currentfs_file_fops,
-	readpage: currentfs_readpage,
+	revalidate:     NULL,
 };
+
diff --git a/lustre/snapfs/filter.c b/lustre/snapfs/filter.c
index c63caac5cd1d7ab9b5f4fa758e9653a0a31933b1..263029c8881ce40aeb553835d98ceb14ad93ac5a 100644
--- a/lustre/snapfs/filter.c
+++ b/lustre/snapfs/filter.c
@@ -1,37 +1,21 @@
 /*
- *
- *
- *  Copyright (C) 2000 Stelias Computing, Inc.
- *  Copyright (C) 2000 Red Hat, Inc.
- *  Copyright (C) 2000 Mountain View Data, Inc.
- *
- *
+ * filter.c
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#define __NO_VERSION__
 #include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
 
-int filter_print_entry = 1;
-int filter_debug = 0xfffffff;
 /*
  * The function in this file are responsible for setting up the 
  * correct methods layered file systems like InterMezzo and SnapFS
@@ -71,6 +55,11 @@ inline struct file_operations *filter_c2uffops(struct filter_fs *cache)
 	return &cache->o_fops.filter_file_fops;
 }
 
+inline struct address_space_operations *filter_c2ufaops(struct filter_fs *cache)
+{
+	return &cache->o_fops.filter_file_aops;
+}
+
 inline struct file_operations *filter_c2usfops(struct filter_fs *cache)
 {
 	return &cache->o_fops.filter_sym_fops;
@@ -97,6 +86,11 @@ inline struct inode_operations *filter_c2cfiops(struct filter_fs *cache)
 	return cache->o_caops.cache_file_iops;
 }
 
+inline struct address_space_operations *filter_c2cfaops(struct filter_fs *cache)
+{
+	return cache->o_caops.cache_file_aops;
+}
+
 inline struct inode_operations *filter_c2csiops(struct filter_fs *cache)
 {
 	return cache->o_caops.cache_sym_iops;
@@ -131,50 +125,51 @@ inline struct snapshot_operations *filter_c2csnapops(struct filter_fs *cache)
 struct filter_fs *filter_get_filter_fs(const char *cache_type)
 {
 	struct filter_fs *ops = NULL;
-	FENTRY;
+	ENTRY;
 
 	if ( strlen(cache_type) == strlen("ext2") &&
 	     memcmp(cache_type, "ext2", strlen("ext2")) == 0 ) {
 		ops = &filter_oppar[FILTER_FS_EXT2];
-		FDEBUG(D_SUPER, "ops at %p\n", ops);
+		CDEBUG(D_SUPER, "ops at %p\n", ops);
 	}
 
 	if ( strlen(cache_type) == strlen("ext3") &&
 	     memcmp(cache_type, "ext3", strlen("ext3")) == 0 ) {
 		ops = &filter_oppar[FILTER_FS_EXT3];
-		FDEBUG(D_SUPER, "ops at %p\n", ops);
+		CDEBUG(D_SUPER, "ops at %p\n", ops);
 	}
 	if ( strlen(cache_type) == strlen("reiser") &&
 	     memcmp(cache_type, "reiser", strlen("reiser")) == 0 ) {
 		ops = &filter_oppar[FILTER_FS_REISER];
-		FDEBUG(D_SUPER, "ops at %p\n", ops);
+		CDEBUG(D_SUPER, "ops at %p\n", ops);
 	}
 
 	if (ops == NULL) {
-		printk("prepare to die: unrecognized cache type for Filter\n");
+		CERROR("prepare to die: unrecognized cache type for Filter\n");
 	}
-	FEXIT;
+	EXIT;
 	return ops;
 }
 
-
 /*
  *  Frobnicate the InterMezzo/SnapFS operations
  *    this establishes the link between the InterMezzo/SnapFS file system
  *    and the underlying file system used for the cache.
  */
 
-void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *cache_sops, struct super_operations *filter_sops)
+void filter_setup_super_ops(struct filter_fs *cache, 
+		            struct super_operations *cache_sops, 
+			    struct super_operations *filter_sops)
 {
         /* Get ptr to the shared struct snapfs_ops structure. */
 	struct filter_ops *uops = &cache->o_fops;
         /* Get ptr to the shared struct cache_ops structure. */
 	struct cache_ops *caops = &cache->o_caops;
 
-	FENTRY;
+	ENTRY;
 
 	if ( cache->o_flags & FILTER_DID_SUPER_OPS ) {
-		FEXIT;
+		EXIT;
 		return;
 	}
 	cache->o_flags |= FILTER_DID_SUPER_OPS;
@@ -182,7 +177,6 @@ void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *ca
         /* Set the cache superblock operations to point to the
 	   superblock operations of the underlying file system.  */
 	caops->cache_sops = cache_sops;
-
         /*
          * Copy the cache (real fs) superblock ops to the "filter"
          * superblock ops as defaults. Some will be changed below
@@ -195,189 +189,163 @@ void filter_setup_super_ops(struct filter_fs *cache, struct super_operations *ca
 	}
 	if (cache_sops->read_inode && uops->filter_sops.read_inode) {
 		uops->filter_sops.read_inode = filter_sops->read_inode;
-		FDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
+		CDEBUG(D_INODE, "setting filter_read_inode, cache_ops %p, cache %p, ri at %p\n",
 		      cache, cache, uops->filter_sops.read_inode);
 	}
-	if (cache_sops->notify_change && uops->filter_sops.notify_change) 
-		uops->filter_sops.notify_change = filter_sops->notify_change;
-	if (cache_sops->remount_fs && uops->filter_sops.remount_fs)
-		uops->filter_sops.remount_fs = filter_sops->remount_fs;
-	FEXIT;
+	uops->filter_sops.clear_inode = filter_sops->clear_inode;
+	
+	EXIT;
 }
 
-
-void filter_setup_dir_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
+void filter_setup_dir_ops(struct filter_fs *cache, 
+			  struct inode	   *inode,
+			  struct inode_operations *filter_iops, 
+			  struct file_operations *filter_fops)
 {
 	struct inode_operations *u_iops;
-	struct file_operations *u_fops, *c_fops, *f_fops;
-	FENTRY;
+	struct file_operations *u_fops;
+	
+	ENTRY;
 
-	if ( cache->o_flags & FILTER_DID_DIR_OPS ) {
-		FEXIT;
+	if (cache->o_flags & FILTER_DID_DIR_OPS) {
+		EXIT;
 		return;
 	}
-	FDEBUG(D_SUPER, "\n");
 	cache->o_flags |= FILTER_DID_DIR_OPS;
 
 	/* steal the old ops */
-	cache->o_caops.cache_dir_iops = cache_iops;
-	cache->o_caops.cache_dir_fops = 
-		cache_iops->default_file_ops;
-
-	FDEBUG(D_SUPER, "\n");
-	/* abbreviate */
-	u_iops = &cache->o_fops.filter_dir_iops;
-
-	/* setup our dir iops: copy and modify */
-	memcpy(u_iops, cache_iops, sizeof(*cache_iops));
-	FDEBUG(D_SUPER, "\n");
+	cache->o_caops.cache_dir_iops = inode->i_op;
+	cache->o_caops.cache_dir_fops = inode->i_fop;
+	
+	u_iops = filter_c2udiops(cache);
+	u_fops = filter_c2udfops(cache); 
+	
+	/* setup our dir iops and fops: copy and modify */
+	memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
+	memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
 
 	/* methods that filter if cache filesystem has these ops */
-	if ( cache_iops->lookup && filter_iops->lookup ) {
-	FDEBUG(D_SUPER, "\n");
-		u_iops->lookup = filter_iops->lookup;
-		FDEBUG(D_SUPER, "lookup at %p\n", &filter_iops->lookup);
+	if (filter_iops) {
+		struct inode_operations *cache_iops = inode->i_op;
+		
+		if (cache_iops->lookup && filter_iops->lookup) 
+			u_iops->lookup = filter_iops->lookup;
+		if (cache_iops->create && filter_iops->create)
+			u_iops->create = filter_iops->create;
+		if (cache_iops->link && filter_iops->link)
+			u_iops->link = filter_iops->link;
+		if (cache_iops->unlink && filter_iops->unlink)
+			u_iops->unlink = filter_iops->unlink;
+		if (cache_iops->mkdir && filter_iops->mkdir)
+			u_iops->mkdir = filter_iops->mkdir;
+		if (cache_iops->rmdir && filter_iops->rmdir)
+			u_iops->rmdir = filter_iops->rmdir;
+		if (cache_iops->symlink && filter_iops->symlink)
+			u_iops->symlink = filter_iops->symlink;
+		if (cache_iops->rename && filter_iops->rename)
+			u_iops->rename = filter_iops->rename;
+		if (cache_iops->mknod && filter_iops->mknod)
+			u_iops->mknod = filter_iops->mknod;
+		if (cache_iops->permission && filter_iops->permission)
+			u_iops->permission = filter_iops->permission;
 	}
-	if (cache_iops->create && filter_iops->create)
-		u_iops->create = filter_iops->create;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->link && filter_iops->link)
-		u_iops->link = filter_iops->link;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->unlink && filter_iops->unlink)
-		u_iops->unlink = filter_iops->unlink;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->mkdir && filter_iops->mkdir)
-		u_iops->mkdir = filter_iops->mkdir;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->rmdir && filter_iops->rmdir)
-		u_iops->rmdir = filter_iops->rmdir;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->symlink && filter_iops->symlink)
-		u_iops->symlink = filter_iops->symlink;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->rename && filter_iops->rename)
-		u_iops->rename = filter_iops->rename;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->mknod && filter_iops->mknod)
-		u_iops->mknod = filter_iops->mknod;
-	FDEBUG(D_SUPER, "\n");
-	if (cache_iops->permission && filter_iops->permission)
-		u_iops->permission = filter_iops->permission;
-
 	/* copy dir fops */
-	FDEBUG(D_SUPER, "\n");
-	u_fops = &cache->o_fops.filter_dir_fops;
-	c_fops = cache_iops->default_file_ops;
-	f_fops = filter_iops->default_file_ops;
-
-        memcpy(u_fops, c_fops, sizeof(*c_fops));
-
-	if( c_fops->readdir && f_fops->readdir )
-		u_fops->readdir = f_fops->readdir;
-
-	/* assign */
-	FDEBUG(D_SUPER, "\n");
-	filter_c2udiops(cache)->default_file_ops = filter_c2udfops(cache);
-	FDEBUG(D_SUPER, "\n");
-
-	/* unconditional filtering operations */
-	if ( filter_iops->default_file_ops && 
-	     filter_iops->default_file_ops->open ) 
-		filter_c2udfops(cache)->open = 
-			filter_iops->default_file_ops->open;
-
-	FEXIT;
+	
+	if (filter_fops) {
+		struct file_operations *cache_fops = inode->i_fop;
+		
+		if(cache_fops->readdir && filter_fops->readdir)
+			u_fops->readdir = filter_fops->readdir;
+	}
+	EXIT;
 }
 
-
-void filter_setup_file_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
+void filter_setup_file_ops(struct filter_fs 	   *cache, 
+			   struct inode		   *inode,
+			   struct inode_operations *filter_iops,
+			   struct file_operations  *filter_fops,
+			   struct address_space_operations *filter_aops)
 {
 	struct inode_operations *u_iops;
-	FENTRY;
+	struct file_operations *u_fops;
+	struct address_space_operations *u_aops;
+	ENTRY;
 
-	if ( cache->o_flags & FILTER_DID_FILE_OPS ) {
-		FEXIT;
+	if (cache->o_flags & FILTER_DID_FILE_OPS || !inode ) { 
+		EXIT;
 		return;
 	}
+
 	cache->o_flags |= FILTER_DID_FILE_OPS;
 
 	/* steal the old ops */
-	cache->o_caops.cache_file_iops = cache_iops;
-	cache->o_caops.cache_file_fops = 
-		cache_iops->default_file_ops;
+	cache->o_caops.cache_file_iops = inode->i_op; 
+	cache->o_caops.cache_file_fops = inode->i_fop;
 
 	/* abbreviate */
 	u_iops = filter_c2ufiops(cache); 
-
+	u_fops = filter_c2uffops(cache); 
+	u_aops = filter_c2ufaops(cache); 
+		
 	/* setup our dir iops: copy and modify */
-	memcpy(u_iops, cache_iops, sizeof(*cache_iops));
+	memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
+	memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
 
-	/* copy dir fops */
-        memcpy(filter_c2uffops(cache), cache_iops->default_file_ops, 
-	       sizeof(*cache_iops->default_file_ops));
-	/* assign */
-	filter_c2ufiops(cache)->default_file_ops = filter_c2uffops(cache);
-
-	/* unconditional filtering operations */
-	if (filter_iops->default_file_ops &&
-	    filter_iops->default_file_ops->open ) 
-		filter_c2uffops(cache)->open = 
-			filter_iops->default_file_ops->open;
-	if (filter_iops->default_file_ops &&
-	    filter_iops->default_file_ops->release ) 
-		filter_c2uffops(cache)->release = 
-			filter_iops->default_file_ops->release;
-	if (filter_iops->default_file_ops &&
-	    filter_iops->default_file_ops->write ) 
-		filter_c2uffops(cache)->write = 
-			filter_iops->default_file_ops->write;
-
-	/* set up readpage */
-	if (filter_iops->readpage) 
-		filter_c2ufiops(cache)->readpage = filter_iops->readpage;
-
-	FEXIT;
+	if (inode->i_mapping && inode->i_mapping->a_ops) {
+		cache->o_caops.cache_file_aops = inode->i_mapping->a_ops; 
+		memcpy(u_aops, inode->i_mapping->a_ops, 
+		       sizeof(struct address_space_operations));
+	}
+	if (filter_iops) {
+		if (filter_iops->revalidate)
+			u_iops->revalidate = filter_iops->revalidate;
+	}
+	if (filter_fops) {
+		if (filter_fops->read)
+			u_fops->read = filter_fops->read;
+	}
+	if (filter_aops) {
+		if (filter_aops->readpage)
+			u_aops->readpage = filter_aops->readpage;
+	}
+	EXIT;
 }
 
-/* XXX in 2.3 there are "fast" and "slow" symlink ops for ext2 XXX */
-void filter_setup_symlink_ops(struct filter_fs *cache, struct inode_operations *cache_iops, struct inode_operations *filter_iops)
+void filter_setup_symlink_ops(struct filter_fs *cache, 
+			      struct inode *inode,
+		              struct inode_operations *filter_iops, 
+			      struct file_operations *filter_fops)
 {
 	struct inode_operations *u_iops;
-	FENTRY;
+	struct file_operations *u_fops;
+	
+	ENTRY;
 
-	if ( cache->o_flags & FILTER_DID_SYMLINK_OPS ) {
-		FEXIT;
+	if (cache->o_flags & FILTER_DID_SYMLINK_OPS || !inode ) {
+		EXIT;
 		return;
 	}
 	cache->o_flags |= FILTER_DID_SYMLINK_OPS;
 
 	/* steal the old ops */
-	cache->o_caops.cache_sym_iops = cache_iops;
-	cache->o_caops.cache_sym_fops = 
-		cache_iops->default_file_ops;
+	cache->o_caops.cache_sym_iops = inode->i_op;
+	cache->o_caops.cache_sym_fops = inode->i_fop; 
 
 	/* abbreviate */
 	u_iops = filter_c2usiops(cache); 
+	u_fops = filter_c2usfops(cache); 
 
 	/* setup our dir iops: copy and modify */
-	memcpy(u_iops, cache_iops, sizeof(*cache_iops));
-
-	/* copy fops - careful for symlinks they might be NULL */
-	if ( cache_iops->default_file_ops ) { 
-		memcpy(filter_c2usfops(cache), cache_iops->default_file_ops, 
-		       sizeof(*cache_iops->default_file_ops));
+	memcpy(u_iops, inode->i_op, sizeof(struct inode_operations));
+	memcpy(u_fops, inode->i_fop, sizeof(struct file_operations));
+	if (filter_iops) {
+		struct inode_operations *cache_iops = inode->i_op; 
+		if (cache_iops->readlink && filter_iops->readlink) 
+			u_iops->readlink = filter_iops->readlink;
+		if (cache_iops->follow_link && filter_iops->follow_link)
+			u_iops->follow_link = filter_iops->follow_link;
 	}
-
-	/* assign */
-	filter_c2usiops(cache)->default_file_ops = filter_c2usfops(cache);
-
-	if (cache_iops->readlink && filter_iops->readlink) 
-		u_iops->readlink = filter_iops->readlink;
-	if (cache_iops->follow_link && filter_iops->follow_link)
-		u_iops->follow_link = filter_iops->follow_link;
-
-	FEXIT;
+	EXIT;
 }
 
 void filter_setup_dentry_ops(struct filter_fs *cache,
@@ -385,7 +353,7 @@ void filter_setup_dentry_ops(struct filter_fs *cache,
 			     struct dentry_operations *filter_dop)
 {
 	if ( cache->o_flags & FILTER_DID_DENTRY_OPS ) {
-		FEXIT;
+		EXIT;
 		return;
 	}
 	cache->o_flags |= FILTER_DID_DENTRY_OPS;
@@ -395,39 +363,40 @@ void filter_setup_dentry_ops(struct filter_fs *cache,
 	       filter_dop, sizeof(*filter_dop));
 	
 	if (cache_dop &&  cache_dop != filter_dop && cache_dop->d_revalidate){
-		printk("WARNING: filter overriding revalidation!\n");
+		CWARN("filter overriding revalidation!\n");
 	}
+	EXIT;
 	return;
 }
 /* snapfs : for snapshot operations */
 void filter_setup_snapshot_ops (struct filter_fs *cache, 
 				struct snapshot_operations *cache_snapops)
 {
-	FENTRY;
+	ENTRY;
 
 	if ( cache->o_flags & FILTER_DID_SNAPSHOT_OPS ) {
-		FEXIT;
+		EXIT;
 		return;
 	}
 	cache->o_flags |= FILTER_DID_SNAPSHOT_OPS;
 
 	cache->o_snapops = cache_snapops;
 
-	FEXIT;
+	EXIT;
 }
 
 void filter_setup_journal_ops (struct filter_fs *cache,
 			       struct journal_ops *cache_journal_ops)
 {
-	FENTRY;
+	ENTRY;
 
 	if( cache->o_flags & FILTER_DID_JOURNAL_OPS ){
-		FEXIT;
+		EXIT;
 		return;
 	}
 	cache->o_flags |= FILTER_DID_JOURNAL_OPS;
 
 	cache->o_trops = cache_journal_ops;
 
-	FEXIT;
+	EXIT;
 }
diff --git a/lustre/snapfs/inode.c b/lustre/snapfs/inode.c
index d6434f35402f7ea5d556f2854ec0d252dbb60cd9..9f43d0de868899107c4922250e61d52df40ad329 100644
--- a/lustre/snapfs/inode.c
+++ b/lustre/snapfs/inode.c
@@ -5,32 +5,17 @@
  *
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-#ifdef CONFIG_SNAPFS_EXT2
-#include <linux/ext2_fs.h>
-#endif
-#ifdef CONFIG_SNAPFS_EXT3
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/jbd.h>
 #include <linux/ext3_fs.h>
-#endif
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include <linux/string.h>
+#include <linux/snap.h>
+#include "snapfs_internal.h" 
 
 
 extern int currentfs_remount(struct super_block * sb, int *flags, char *data);
@@ -43,104 +28,100 @@ extern int currentfs_remount(struct super_block * sb, int *flags, char *data);
  
 extern void currentfs_dotsnap_read_inode(struct snap_cache *, struct inode *);
 
+static kmem_cache_t *filter_info_cache = NULL;
+
+void cleanup_filter_info_cache()
+{
+	kmem_cache_destroy(filter_info_cache);
+}
+
+int init_filter_info_cache()
+{
+	filter_info_cache = kmem_cache_create("snapfs_filter_info",
+					       sizeof(struct filter_inode_info), 
+					    0, 0, NULL, NULL);
+        if (!filter_info_cache) {
+                CERROR("unable to create snap_inode info cache\n");
+		return -ENOMEM;
+        }
+        return 0;
+}
+
+
+void init_filter_data(struct inode *inode, 
+			     struct snapshot_operations *snapops, 
+			     int flag)
+{
+	struct filter_inode_info *i;
+
+	if (inode->i_filterdata){
+                return;
+        }
+	inode->i_filterdata = (struct filter_inode_info *) \
+			      kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
+	i = inode->i_filterdata;
+	i -> generation = snapops->get_generation(inode);
+	i -> flags      = flag;
+}
 /* Superblock operations. */
 static void currentfs_read_inode(struct inode *inode)
 {
         struct snap_cache *cache;
+	struct snapshot_operations *snapops;	
 	ENTRY;
 
 	if( !inode ) 
-	{
-		EXIT;
 		return;
-	}
 
 	CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
 
 	cache = snap_find_cache(inode->i_dev);
-	if ( !cache ) {
-		printk("currentfs_read_inode: cannot find cache\n");
+	if (!cache) {
+		CERROR("currentfs_read_inode: cannot find cache\n");
 		make_bad_inode(inode);
-		EXIT;
-		return ;
+		return;
 	}
 
-	if ( inode->i_ino & 0xF0000000 ) { 
-		CDEBUG(D_INODE, "\n");
+	if (inode->i_ino & 0xF0000000) { 
 		currentfs_dotsnap_read_inode(cache, inode);
-		EXIT;
-		return ;
+		return;
 	}
+	snapops = filter_c2csnapops(cache->cache_filter);
+	
+	if (!snapops || !snapops->get_indirect) 
+		return;
 
-	if( filter_c2csops(cache->cache_filter) )
+	if(filter_c2csops(cache->cache_filter))
 		filter_c2csops(cache->cache_filter)->read_inode(inode);
 
 	/* XXX now set the correct snap_{file,dir,sym}_iops */
-	if ( S_ISDIR(inode->i_mode) ) 
+	if (S_ISDIR(inode->i_mode)) 
 		inode->i_op = filter_c2udiops(cache->cache_filter);
-	else if ( S_ISREG(inode->i_mode) ) {
+	else if (S_ISREG(inode->i_mode)) {
 		if ( !filter_c2cfiops(cache->cache_filter) ) {
-			filter_setup_file_ops(cache->cache_filter,
-				inode->i_op, &currentfs_file_iops);
+			filter_setup_file_ops(cache->cache_filter, inode, 
+					      &currentfs_file_iops, 
+					      &currentfs_file_fops, 
+					      &currentfs_file_aops);
 		}
-		inode->i_op = filter_c2ufiops(cache->cache_filter);
-		printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op);
+		CDEBUG(D_INODE, "inode %lu, i_op at %p\n", 
+		       inode->i_ino, inode->i_op);
 	}
-	else if ( S_ISLNK(inode->i_mode) ) {
+	else if (S_ISLNK(inode->i_mode)) {
 		if ( !filter_c2csiops(cache->cache_filter) ) {
-			filter_setup_symlink_ops(cache->cache_filter,
-				inode->i_op, &currentfs_sym_iops);
+			filter_setup_symlink_ops(cache->cache_filter, inode,
+				&currentfs_sym_iops, &currentfs_sym_fops);
 		}
 		inode->i_op = filter_c2usiops(cache->cache_filter);
-		printk("inode %lu, i_op at %p\n", inode->i_ino, inode->i_op);
+		CDEBUG(D_INODE, "inode %lu, i_op at %p\n", 
+		       inode->i_ino, inode->i_op);
 	}
-
-	EXIT;
+	/*init filter_data struct 
+	 * FIXME flag should be set future*/
+	init_filter_data(inode, snapops, 0); 
 	return; 
 }
 
-
-static int currentfs_notify_change(struct dentry *dentry, struct iattr *iattr)
-{
-	struct snap_cache *cache;
-	int rc;
-	struct super_operations *sops;
-
-	ENTRY;
-
-	if (currentfs_is_under_dotsnap(dentry)) {
-		EXIT;
-		return -EPERM;
-	}
-
-	cache = snap_find_cache(dentry->d_inode->i_dev);
-	if ( !cache ) { 
-		EXIT;
-		return -EINVAL;
-	}
-
-	/* XXX better alloc a new dentry */
-
-	if ( snap_needs_cow(dentry->d_inode) != -1 ) {
-		printk("notify_change:snap_needs_cow for ino %lu \n",
-			dentry->d_inode->i_ino);
-		snap_do_cow(dentry->d_inode, 
-			dentry->d_parent->d_inode->i_ino, 0);
-	}
-
-	sops = filter_c2csops(cache->cache_filter); 
-	if (!sops ||
-	    !sops->notify_change) {
-		EXIT;
-		return -EINVAL;
-	}
-	rc = sops->notify_change(dentry, iattr);
-	
-	EXIT;
-	return rc;
-}
-
-
 static void currentfs_put_super(struct super_block *sb)
 {
 
@@ -150,10 +131,10 @@ static void currentfs_put_super(struct super_block *sb)
 	CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) sb->u.generic_sbp);
 	cache = snap_find_cache(sb->s_dev);
-	if (!cache) {
-		EXIT;
-		goto exit;
-	}
+
+	if (!cache) 
+		GOTO(exit, 0);	
+	
 	/* handle COMPAT_FEATUREs */
 #ifdef CONFIG_SNAPFS_EXT2
 	else if( cache->cache_type == FILTER_FS_EXT2 ){
@@ -182,7 +163,7 @@ static void currentfs_put_super(struct super_block *sb)
 	}
 	
 	if (!list_empty(&cache->cache_clone_list)) {
-		printk("Warning: snap_put_super: clones exist!\n");
+		CWARN("snap_put_super: clones exist!\n");
 	}
 
 	list_del(&cache->cache_chain);
@@ -191,21 +172,32 @@ static void currentfs_put_super(struct super_block *sb)
 	CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) sb->u.generic_sbp);
 exit:
-	CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
-	MOD_DEC_USE_COUNT;
 	EXIT;
-	return ;
+	return;
+}
+static void currentfs_clear_inode(struct inode *inode)
+{
+	struct snap_cache *cache;
+        struct super_operations *sops;
+	ENTRY;			                                                                                                                                                                                                     
+        cache = snap_find_cache(inode->i_dev);
+        if (!cache) {
+                CDEBUG(D_INODE, "inode has invalid dev\n");
+                return;
+        }
+	
+	if (inode->i_filterdata) {
+		kmem_cache_free(filter_info_cache, inode->i_filterdata);
+		inode->i_filterdata = NULL;
+	}
+
+	sops = filter_c2csops(cache->cache_filter);
+        if (sops && sops->clear_inode)
+                sops->clear_inode(inode);
 }
 
 struct super_operations currentfs_super_ops = {
-	currentfs_read_inode,
-	NULL, /* write inode */
-	NULL, /* put inode */
-	NULL, /* delete inode */
-	currentfs_notify_change,
-	currentfs_put_super,
-	NULL, /* write super */
-	NULL,
-	NULL, /* remount */
+	read_inode:	currentfs_read_inode,
+	put_super:	currentfs_put_super,
+	clear_inode:	currentfs_clear_inode,
 };
diff --git a/lustre/snapfs/journal_ext3.c b/lustre/snapfs/journal_ext3.c
index 8171842e530299faf72ec753a64a01458a528d8b..7a4fa7ec578107083edf5121fe23a8ce7a535876 100644
--- a/lustre/snapfs/journal_ext3.c
+++ b/lustre/snapfs/journal_ext3.c
@@ -3,26 +3,21 @@
  * Snapfs. (C) 2000 Peter J. Braam
  */
 
-#include <linux/types.h>
+#define DEBUG_SUBSYSTEM S_SNAP
+
+#include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/stat.h>
-#include <linux/errno.h>
-#include <linux/locks.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
 #include <linux/string.h>
-#ifdef CONFIG_SNAPFS_EXT3
-#include <linux/ext3_jfs.h>
-#endif
-#include "linux/filter.h"
-#include "linux/snapfs.h"
-#include "linux/snapsupport.h"
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
+#include <linux/jbd.h>
+#include <linux/ext3_jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#ifdef CONFIG_SNAPFS_EXT3
 
 #define EXT3_EA_TRANS_BLOCKS EXT3_DATA_TRANS_BLOCKS
 
@@ -63,17 +58,17 @@ static void *snap_e3_trans_start(struct inode *inode, int op)
 		jblocks = 4 * COW_CREDITS + 2 * EXT3_DATA_TRANS_BLOCKS + 2;
 		break;
 	default:
-		CDEBUG(D_JOURNAL, "invalid operation %d for journal\n", op);
+		CDEBUG(D_INODE, "invalid operation %d for journal\n", op);
 		return NULL;
 	}
 
-	CDEBUG(D_JOURNAL, "creating journal handle (%d blocks)\n", jblocks);
-	return journal_start(EXT3_JOURNAL(inode), jblocks);
+	CDEBUG(D_INODE, "creating journal handle (%d blocks)\n", jblocks);
+	return ext3_journal_start(inode, jblocks);
 }
 
 static void snap_e3_trans_commit(void *handle)
 {
-	journal_stop(current->j_handle);
+	journal_stop(handle);
 }
 
 struct journal_ops snap_ext3_journal_ops = {
@@ -81,4 +76,3 @@ struct journal_ops snap_ext3_journal_ops = {
 	snap_e3_trans_commit
 };
 
-#endif /* CONFIG_EXT3_FS */
diff --git a/lustre/snapfs/psdev.c b/lustre/snapfs/psdev.c
index 424d32557daa66688636ffc9febfd140ac795dce..764adcc291b5946fb0ea501b684961ba60c34e50 100644
--- a/lustre/snapfs/psdev.c
+++ b/lustre/snapfs/psdev.c
@@ -12,46 +12,28 @@
 
 #define EXPORT_SYMTAB
 
-#include <linux/config.h> /* for CONFIG_PROC_FS */
+
+#define DEBUG_SUBSYSTEM S_SNAP
+
 #include <linux/module.h>
-#include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/major.h>
-/* #include <linux/kmod.h>    for request_module() */
-#include <linux/sched.h>
-#include <linux/lp.h>
-#include <linux/malloc.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <asm/io.h>
-#include <asm/segment.h>
-#include <asm/system.h>
-#include <asm/poll.h>
-#include <asm/uaccess.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/unistd.h>
 #include <linux/miscdevice.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
-#if 1 /* XXX - enable for debug messages */
 int snap_print_entry = 1;
-int snap_debug_level = ~D_INFO;
-#else
-int snap_print_entry = 0;
 int snap_debug_level = 0;
-#endif
 int snap_inodes = 0;
-long snap_memory = 0;
-
+long snap_kmemory = 0;
+int snap_stack = 0;
 struct snap_control_device snap_dev;
 
 extern int snap_ioctl (struct inode * inode, struct file * filp, 
@@ -64,14 +46,12 @@ static int snap_psdev_open(struct inode * inode, struct file * file)
         ENTRY;
 
 	if (!inode)
-		return -EINVAL;
+		RETURN(-EINVAL);
 	dev = MINOR(inode->i_rdev);
 	if (dev != SNAP_PSDEV_MINOR)
-		return -ENODEV;
+		RETURN(-ENODEV);
 
-        MOD_INC_USE_COUNT;
-        EXIT;
-        return 0;
+        RETURN(0);
 }
 
 /* called when closing /dev/device */
@@ -81,15 +61,12 @@ static int snap_psdev_release(struct inode * inode, struct file * file)
         ENTRY;
 
 	if (!inode)
-		return -EINVAL;
+		RETURN(-EINVAL);
 	dev = MINOR(inode->i_rdev);
 	if (dev != SNAP_PSDEV_MINOR)
-		return -ENODEV;
-
-        MOD_DEC_USE_COUNT;
+		RETURN(-ENODEV);
 
-        EXIT;
-        return 0;
+        RETURN(0);
 }
 
 /* XXX need ioctls here to do snap_delete and snap_restore, snap_backup */
@@ -97,19 +74,9 @@ static int snap_psdev_release(struct inode * inode, struct file * file)
 
 /* declare character device */
 static struct file_operations snapcontrol_fops = {
-	NULL,                  /* llseek */
-	NULL,                  /* read */
-	NULL,                  /* write */
-	NULL,		       /* presto_psdev_readdir */
-        NULL,                  /* poll */
-	snap_ioctl,            /* ioctl */
-	NULL,		       /* presto_psdev_mmap */
-	snap_psdev_open,       /* open */
-	NULL,
-	snap_psdev_release,    /* release */
-	NULL,                  /* fsync */
-	NULL,                  /* fasync */
-	NULL                   /* lock */
+	ioctl:		snap_ioctl,            /* ioctl */
+	open:		snap_psdev_open,       /* open */
+	release:	snap_psdev_release,    /* release */
 };
 
 
@@ -117,14 +84,14 @@ static struct file_operations snapcontrol_fops = {
 #define SNAPFS_MINOR 240
 
 static struct miscdevice snapcontrol_dev = {
-	SNAPFS_MINOR,
-	"snapcontrol",
-	&snapcontrol_fops
+	minor:	SNAPFS_MINOR,
+	name:	"snapcontrol",
+	fops:	&snapcontrol_fops
 };
 
 int init_snap_psdev(void)
 {
-	printk(KERN_INFO "SNAP psdev driver  v0.01, braam@mountainviewdata.com\n");
+	printk(KERN_INFO "SNAP psdev driver  v0.01, braam@clusterfs.com\n");
 	
 	misc_register( &snapcontrol_dev );
 
@@ -138,7 +105,6 @@ void snap_cleanup_psdev(void)
 	EXIT;
 }
 
-#ifdef MODULE
 MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>");
 MODULE_DESCRIPTION("Snapfs file system filters v0.01");
 
@@ -147,7 +113,7 @@ extern int cleanup_snapfs(void);
 extern int init_clonefs(void);
 extern int init_snap_sysctl(void); 
 
-int init_module(void)
+static int __init snapfs_init(void)
 {
 	int err;
 	if ( (err = init_snap_psdev()) ) {
@@ -164,17 +130,18 @@ int init_module(void)
 		printk("Error initializing snapfs proc sys, %d\n", err);
 		return -EINVAL;
 	}
-
-
+	
 	return 0;
 }
 
-void cleanup_module(void)
+static void __exit snapfs_cleanup(void)
 {
 
 	cleanup_snapfs();
 	snap_cleanup_psdev();
 	
 }
-#endif
+module_init(snapfs_init);
+module_exit(snapfs_cleanup);
+                                                                                                                                                                                                     
 
diff --git a/lustre/snapfs/snap.c b/lustre/snapfs/snap.c
index 463e0faae729bd2b004abd8e928eb1ae28d901d5..a5032a6ff8584db6909d00791aba8696cad37051 100644
--- a/lustre/snapfs/snap.c
+++ b/lustre/snapfs/snap.c
@@ -6,25 +6,15 @@
  *
  */
 
-#define EXPORT_SYMTAB
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
-
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include <linux/snap.h>
+#include "snapfs_internal.h" 
 
 /*
  * Return true if the inode is a redirector inode.
@@ -36,12 +26,10 @@ int snap_is_redirector(struct inode *cache_inode)
 
 	cache = snap_find_cache(cache_inode->i_dev);
 	if (!cache) {
-		EXIT;
 		return 0;
 	}
         snapops = filter_c2csnapops(cache->cache_filter);
         if (!snapops || !snapops->is_redirector) {
-                EXIT;
                 return 0;
         }
 
@@ -68,13 +56,11 @@ struct inode *snap_redirect(struct inode *cache_inode,
 
         cache = snap_find_cache(cache_inode->i_dev);
         if (!cache) {
-                EXIT;
-                return NULL;
+                RETURN(NULL);
         }
         snapops = filter_c2csnapops(cache->cache_filter);
         if (!snapops || !snapops->get_indirect) {
-                EXIT;
-                return NULL;
+                RETURN(NULL);
         }
 
 	CDEBUG(D_SNAP, "cache ino %ld\n", cache_inode->i_ino);
@@ -87,22 +73,19 @@ struct inode *snap_redirect(struct inode *cache_inode,
 					clone_info->clone_index);
 	/* if not found, get the FIRST index after this and before NOW */
  	/* XXX fix this later, now use tbl_count, not NOW */
-	if(!redirected) {
+	if (!redirected) {
+		int index;
 		clone_slot = snap_index2slot(table, clone_info->clone_index);
-		for(slot = table->tbl_count; slot >= clone_slot; slot --)
-		{
-			my_table[slot-clone_slot+1] = table->tbl_index[slot];
+		for (slot = table->tbl_count; slot >= clone_slot; slot --) {
+			my_table[slot-clone_slot+1] = table->snap_items[slot].index;
 		}
-		redirected = snapops->get_indirect 
-		(cache_inode, my_table, table->tbl_count - clone_slot + 1);
+		index = table->tbl_count - clone_slot + 1;
+		redirected = snapops->get_indirect(cache_inode, my_table, index);
 	}
-        /* old version
-	redirected = snapops->get_indirect 
-			(cache_inode, table->tbl_index,
-		 	snap_index2slot(table, clone_info->clone_index));
-	*/
-	if(redirected) CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino);
-	EXIT;
+
+	if (redirected) 
+		CDEBUG(D_SNAP,"redirected ino %ld\n",redirected->i_ino);
+
 	return redirected;
 }
 
@@ -122,23 +105,19 @@ int snap_do_cow(struct inode *inode, ino_t parent_ino, int del)
 
 	cache = snap_find_cache(inode->i_dev);
 	if (!cache) {
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
 	snapops = filter_c2csnapops(cache->cache_filter);
 	if (!snapops || !snapops->create_indirect) {
-		EXIT;
-		return -EINVAL;
+		RETURN(-EINVAL);
 	}
+
 	snap_last(cache, &snap);
-	ind = snapops->create_indirect(inode, parent_ino, snap.index, del);
-	EXIT;
-	if(ind)	{
-		iput(ind);
-		return	0;
-	}
-	else
-		return -EINVAL;
+	ind = snapops->create_indirect(inode, snap.index, 0, parent_ino, del);
+	if(!ind)
+		RETURN(-EINVAL);		
+	iput(ind);
+	RETURN(0);
 }
 
 int snap_iterate(struct super_block *sb,
@@ -153,16 +132,13 @@ int snap_iterate(struct super_block *sb,
 
         cache = snap_find_cache(inode->i_dev);
         if (!cache) {
-                EXIT;
-                return 0;
+                RETURN(0);
         }
         snapops = filter_c2csnapops(cache->cache_filter);
         if (!snapops || !snapops->iterate) {
-                EXIT;
-                return 0;
+                RETURN(0);
         }
 
-	EXIT;
 	return snapops->iterate(sb, repeat, start, priv, flag);
 }
 
@@ -173,17 +149,12 @@ int snap_destroy_indirect(struct inode *pri, int index, struct inode *next_ind )
 
 	ENTRY;
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return 0;
-        }
+        if (!cache) 
+        	RETURN(0);
         snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->destroy_indirect) {
-                EXIT;
-                return 0;
-        }
+        if (!snapops || !snapops->destroy_indirect) 
+                RETURN(0);
 
-	EXIT;
 	return snapops->destroy_indirect(pri, index, next_ind);
 }
 
@@ -195,17 +166,13 @@ int snap_restore_indirect(struct inode *pri, int index )
 	ENTRY;
 
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return 0;
-        }
+        if (!cache) 
+                RETURN(0);
+
         snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->restore_indirect) {
-                EXIT;
-                return 0;
-        }
+        if (!snapops || !snapops->restore_indirect) 
+                RETURN(0);
 
-	EXIT;
 	return snapops->restore_indirect(pri, index);
 }
 
@@ -217,42 +184,16 @@ struct inode *snap_get_indirect(struct inode *pri, int *table, int slot)
 	ENTRY;
 
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return NULL;
-        }
+        if (!cache) 
+                RETURN(NULL);
+        
         snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->get_indirect) {
-                EXIT;
-                return NULL;
-        }
+        if (!snapops || !snapops->get_indirect) 
+                RETURN(NULL);
 
-	EXIT;
 	return snapops->get_indirect(pri, table, slot);
 }
 
-int snap_migrate_data(struct inode *dst, struct inode *src)
-{
-	struct snap_cache *cache;
-        struct snapshot_operations *snapops;
-
-	ENTRY;
-
-        cache = snap_find_cache(src->i_dev);
-        if (!cache) {
-                EXIT;
-                return 0;
-        }
-        snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->migrate_data) {
-                EXIT;
-                return 0;
-        }
-
-	EXIT;
-	return snapops->migrate_data(dst, src);
-}
-
 int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_ino)
 {
 	struct snap_cache *cache;
@@ -261,15 +202,12 @@ int snap_set_indirect(struct inode *pri, ino_t ind_ino, int index, ino_t parent_
 	ENTRY;
 
         cache = snap_find_cache(pri->i_dev);
-        if (!cache) {
-                EXIT;
-                return -EINVAL;
-        }
-        snapops = filter_c2csnapops(cache->cache_filter);
-        if (!snapops || !snapops->set_indirect) {
-                EXIT;
-                return -EINVAL;
-        }
+        if (!cache) 
+                RETURN(-EINVAL);
+        
+	snapops = filter_c2csnapops(cache->cache_filter);
+        if (!snapops || !snapops->set_indirect) 
+                RETURN(-EINVAL);
 
 	EXIT;
 	return snapops->set_indirect(pri, ind_ino, index, parent_ino);
diff --git a/lustre/snapfs/snaptable.c b/lustre/snapfs/snaptable.c
index 058164b3491a187f306d02571c478f1b7ebf05a5..ac5b712fd2488034ce4664bc4aa9796e5c183df2 100644
--- a/lustre/snapfs/snaptable.c
+++ b/lustre/snapfs/snaptable.c
@@ -6,28 +6,18 @@
  *
  */
 
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/malloc.h>
-#include <linux/locks.h>
-#include <linux/errno.h>
-#include <linux/swap.h>
-#include <linux/smp_lock.h>
-#include <linux/vmalloc.h>
-#include <linux/blkdev.h>
-#include <linux/sysrq.h>
-#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/quotaops.h>
+#define DEBUG_SUBSYSTEM S_SNAP
 
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/snap.h>
 #include <asm/uaccess.h>
-#include <asm/io.h>
-#include <asm/bitops.h>
-#include <asm/mmu_context.h>
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapsupport.h>
-#include <linux/snapfs.h>
 
 struct snap_table snap_tables[SNAP_MAX_TABLES];
 
@@ -52,7 +42,7 @@ int snap_index2slot(struct snap_table *snap_table, int snap_index)
 	int slot;
 
 	for ( slot=0 ; slot<snap_table->tbl_count ; slot++ )
-		if ( snap_table->tbl_index[slot] == snap_index )
+		if ( snap_table->snap_items[slot].index == snap_index )
 			return slot;
 	return -1;
 }
@@ -63,7 +53,8 @@ int snap_index2slot(struct snap_table *snap_table, int snap_index)
    -  the index of the latest snapshot before NOW
    -  hence it returns 0 in case all the volume snapshots lie in the future
    -  this is the index where a COW will land (will be created) 
- */
+*/
+
 void snap_last(struct snap_cache *info, struct snap *snap)
 {
 	int i ;
@@ -73,9 +64,10 @@ void snap_last(struct snap_cache *info, struct snap *snap)
 
 	ENTRY;
 	if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid table no %d\n", tableno);
+		CERROR("invalid table no %d\n", tableno);
 		snap->index = -1;
 	}
+	
 	table = &snap_tables[tableno];
 
 	/* start at the highest index in the superblock 
@@ -83,16 +75,11 @@ void snap_last(struct snap_cache *info, struct snap *snap)
 	i = table->tbl_count - 1;
 
 	/* NOTE: i>0 is an unnecessary check */
-	while ( table->tbl_times[i] > now && i > 0) {
-		CDEBUG(D_SNAP, "time: %ld, i: %d\n", table->tbl_times[i], i);
-		i--;
-	}
-
-	snap->index = table->tbl_index[i];
-	snap->time = table->tbl_times[i];
+	snap->index = table->snap_items[i].index;
+	snap->time = table->snap_items[i].time;
+	snap->gen = table->snap_items[i].gen;
 	CDEBUG(D_SNAP, "index: %d, time[i]: %ld, now: %ld\n",
 	       snap->index, snap->time, now);
-	EXIT;
 	return;
 }
 
@@ -104,117 +91,30 @@ int snap_needs_cow(struct inode *inode)
 {
 	struct snap snap;
 	struct snap_cache *cache;
+	struct filter_inode_info   *filter_info; 
 	int index = -1;
 	ENTRY;
 
 	cache = snap_find_cache(inode->i_dev);
 	if ( !cache ) {
-		EXIT;
-		return -1;
+		RETURN(index);
 	}
-
+	filter_info = (struct filter_inode_info *) inode->i_filterdata;
 	/* here we find the time of the last snap to compare with */
-	snap_last(cache, &snap);
 
+	snap_last(cache, &snap);
 	/* decision .... if the snapshot is more recent than the object,
 	 * then any change to the object should cause a COW.
 	 */
-	if (inode->i_mtime <= snap.time && inode->i_ctime <= snap.time) {
+	if (filter_info && filter_info->generation < snap.gen ) {
 		index = snap.index;
 	}
-	printk("snap_needs_cow, ino %lu , get index %d\n",inode->i_ino, index);
 
-	EXIT;
-	return index;
-} /* snap_needs_cow */
+	CDEBUG(D_SNAP, "snap_needs_cow, ino %lu , get index %d\n",
+	       inode->i_ino, index);
 
-#if 0
-int  snap_obd2snap(struct snap_clone_info *info, struct snap *snap)
-{
-	struct snap_table *table;
-	int tableno = info->clone_cache->cache_snap_tableno;
-	int index =  info->clone_index;
-	int slot;
-
-	ENTRY;
-	if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid table no %d\n", tableno);
-		snap->index = -1;
-	}
-	table = &snap_tables[tableno];
-	slot = snap_index2slot(table, index);
-
-	snap->index = index;
-	snap->time = table->tbl_times[slot];
-	EXIT;
-	return slot;
-}
-#endif
-
-/* at what index is the current snapshot located */
-int snap_current(struct snap_cache *cache)
-{
-	int tableno = cache->cache_snap_tableno;
-
-	return snap_tables[tableno].tbl_index[0];
-}
-
-int snap_is_used(int table_no, int snap_index) 
-
-{
-	/* ENTRY; */
-	if ( snap_index < 0 || snap_index >= SNAP_MAX ) {
-		printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-		       snap_index, table_no);
-		EXIT;
-		return -1;
-	}
-	if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-		       snap_index, table_no);
-		EXIT;
-		return -1;
-	}
-
-	/* EXIT; */
-	return snap_tables[table_no].tbl_used & (1<<snap_index);
-}
-
-void snap_use(int table_no, int snap_index) 
-{
-	if ( snap_index < 0 || snap_index >= SNAP_MAX ) {
-		printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-		       snap_index, table_no);
-		return;
-	}
-	if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-		       snap_index, table_no);
-		return;
-	}
-	if ( snap_index2slot(&snap_tables[table_no], snap_index) < 0 ) 
-		return;
-
-	snap_tables[table_no].tbl_used |=  (1<<snap_index);
-}
-
-void snap_unuse(int table_no, int snap_index) 
-{
-	if ( snap_index < 0 || snap_index >= SNAP_MAX ) {
-		printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-		       snap_index, table_no);
-		return;
-	}
-	if ( table_no < 0 || table_no > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid snapno %d,table %d\n",
-		       snap_index, table_no);
-		return;
-	}
-	if ( snap_index2slot(&snap_tables[table_no], snap_index) < 0 ) 
-		return;
-
-	snap_tables[table_no].tbl_used &=  ~(1<<snap_index);
-}
+	RETURN(index);
+} /* snap_needs_cow */
 
 static int nprint_buf(char *buf, int buflen, char *fmt, ...)
 {
@@ -247,20 +147,18 @@ int snap_print_table(struct snap_table_data *data, char *buf, int *buflen)
 	int nprint = 0;
 
 	if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid table number %d\n", tableno);
-		EXIT;
-		return -EINVAL;
+		CERROR("invalid table number %d\n", tableno);
+		RETURN(-EINVAL);
 	}
 
 	table = &snap_tables[tableno];
 
 	printk("------- snap table %d\n", tableno);
 	printk("     -- snap count %d\n", table->tbl_count);
-	printk("     -- snap used  0x%x\n", table->tbl_used);
 	for ( i = 0 ; i < SNAP_MAX ; i++ ) {
 		printk("     -- slot %d, idx %d, time %ld, name %s\n",
-		       i, table->tbl_index[i], table->tbl_times[i], 
-			table->tbl_name[i]);
+		       i, table->snap_items[i].index, table->snap_items[i].time, 
+			&table->snap_items[i].name[0]);
 	}
 
 	buf_ptr = buf;
@@ -272,15 +170,14 @@ int snap_print_table(struct snap_table_data *data, char *buf, int *buflen)
 	nleft -= nprint;
 	if( nleft > 0 )  buf_ptr += nprint;
 	else goto exit;
-	nprint = nprint_buf(buf_ptr, nleft, "     -- snap used  0x%x\n", table->tbl_used);
-	nleft -= nprint;
+
 	if( nleft > 0 )  buf_ptr += nprint;
 	else goto exit;
 	for ( i = 0 ; i < SNAP_MAX ; i++ ) {
 		nprint = nprint_buf( buf_ptr, nleft,
 			"     -- slot %d, idx %d, time %ld, name %s\n",
-		       i, table->tbl_index[i], table->tbl_times[i], 
-			table->tbl_name[i]);
+		       i, table->snap_items[i].index, table->snap_items[i].time, 
+			&table->snap_items[i].name[0]);
 		nleft -= nprint;
 		if( nleft > 0 )  buf_ptr += nprint;
 		else goto exit;
@@ -291,153 +188,301 @@ exit:
 
 	return 0;
 }
-
-int snap_install_table(int len, struct snap_table_data *data)
+static int inline get_index_of_item(struct snap_table *table)
 {
+	int count = table->tbl_count;
 	int i, j;
-	int tableno = data->tblcmd_no;
-//	int found_current;
-	struct snap_table *table;
 
+	for (i = 0; i < SNAP_MAX; i ++) {
+		for (j = 1; j < count; j++) {
+			if (table->snap_items[j].index == i)
+				break;
+                }
+		if (j >= count) 
+			return i;
+	}
+	return -EINVAL;
+}
+/* This function will write one item(a snapshot) to snaptable  
+ * and will also write to disk.
+ */
+int snaptable_add_item(struct snap_table_data *data)
+{
+	struct snap_table 		*table;
+	struct snap_disk_table 		*disk_snap_table;
+	struct snapshot_operations 	*snapops;
+	struct snap_cache 		*cache;
+	int 				tableno , index, i, count, rc;
+	
+	if (!(cache = snap_find_cache((kdev_t)data->dev)))
+		RETURN(-ENODEV);
+
+	snapops = filter_c2csnapops(cache->cache_filter);
+	if (!snapops || !snapops->set_meta_attr)
+		RETURN(-EINVAL);
+
+	tableno = data->tblcmd_no;
 	if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid table number %d\n", tableno);
-		EXIT;
-		return -EINVAL;
+		CERROR("invalid table number %d\n", tableno);
+		RETURN(-EINVAL);
 	}
 	table = &snap_tables[tableno];	
+	count = table->tbl_count;
+
+	/* XXX Is down this sema necessary*/
+	down_interruptible(&table->tbl_sema);
+
+	/*add item in snap_table*/
+	table->snap_items[count+1].gen = table->generation;
+	table->snap_items[count+1].time = CURRENT_TIME;
+	/* find table index */
+	index = get_index_of_item(table);
+	if (index < 0)
+		RETURN(-EINVAL);
+
+	table->snap_items[count+1].index = index;
+	table->snap_items[count+1].flags = 0;
+	memcpy(&table->snap_items[count + 1].name[0], 
+	       &data->tblcmd_snaps[0].name[0], SNAP_MAX_NAMELEN);
+	/* we will write the whole snap_table to disk */
+	SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
+	if (!disk_snap_table)
+		RETURN(-ENOMEM);
+	disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
+	disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count);
+	disk_snap_table->generation = cpu_to_le32((__u32)table->generation);
+	memset(&disk_snap_table->snap_items[0], 0, 
+	       SNAP_MAX * sizeof(struct snap_disk));
+	for (i = 1; i <= count; i++) {
+		struct snap *item = &table->snap_items[i];
+		disk_snap_table->snap_items[i].time = cpu_to_le64((__u64)item->time);
+		disk_snap_table->snap_items[i].gen = cpu_to_le32((__u32)item->gen);
+		disk_snap_table->snap_items[i].flags = cpu_to_le32((__u32)item->flags);
+		disk_snap_table->snap_items[i].index = cpu_to_le32((__u32)item->index);
+		memcpy(&disk_snap_table->snap_items[i].name , item->name, SNAP_MAX_NAMELEN);
+	}
+	rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
+				    (char*)disk_snap_table, sizeof(struct snap_disk_table));
+
+	SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
+	table->tbl_count++;
+	table->generation++;
+	
+	up(&table->tbl_sema);
+	
+	return 0;
+}
 
-	/* for each index that is used by the current table
-	   we need to make sure that the new table we are about
-	   to put in contains that index too 
-	*/
-	for ( i = 0; i < SNAP_MAX ; i++ ) {
-		int foundit;
-		int err;
-
-		if ((err = snap_is_used(tableno, i)) < 0 ) {
-			printk(__FUNCTION__  ": table %d not used\n", tableno);
-			EXIT;
-			return -EINVAL;
-		} else if (err == 0) {
-			continue;
-		}
+static int delete_inode(struct inode *primary, void *param)
+{
+	struct snap_iterdata * data;
+	int tableno = 0;
+	int index = 0;
+	int rc = 0;
 
-		foundit = 0;
-		for (j = 0 ; j<= data->tblcmd_count ; j++) {
-			if ( i == data->tblcmd_snaps[j].index ) {
-				foundit = 1;
-				break;
-			}
-		}
-		if ( !foundit ) {
-			printk(__FUNCTION__ ": index %d not in table %d\n", 
-			       i, tableno);
-			return -EINVAL;
-		}
-	}
+	struct inode *redirect;
+	ino_t old_ind = 0;
+	struct snap_table *table;
+	int slot;
+	int delete_slot;
+	int this_index;
+	struct inode *next_ind = NULL;
+	int my_table[SNAP_MAX];
 
-	/* we must have:
-           - valid indices 
-	   - a current snapshot in the table 
-	   - increasing snapshot times 
-	*/
-//	found_current = 0;
-	CDEBUG(D_SNAP, "snaplist: tblcmd_count %d\n", data->tblcmd_count);
-	for (i = 0 ; i < data->tblcmd_count ; i++) {
-
-		if ( (data->tblcmd_snaps[i].index < 0) ||
-		     (data->tblcmd_snaps[i].index >= SNAP_MAX) ) {
-			printk(__FUNCTION__ ": snap_index out of range!\n");
-			return -EINVAL;
-		}
+	if(!primary) return 0;
 
-		if (i>0 && data->tblcmd_snaps[i].time <= 
-		    data->tblcmd_snaps[i-1].time) {
-			printk(__FUNCTION__ ": times not increasing\n");
-			return -EINVAL;
-		}
+	data = (struct snap_iterdata*) param;
 
-//		if ( 0 == data->tblcmd_snaps[i].time ) {
-//			found_current = 1;
-//			break;
-//		}
+	if(data) {
+		index = data->index;
+		tableno = data->tableno;
 	}
-//	if ( !found_current ) {
-//		printk(__FUNCTION__ "no current snapshot in table\n");
-//		return -EINVAL;
-//	}
-
-	/* ready to go: over write the table */
-/*	
-	for (i = 0 ; i < data->tblcmd_count ; i++) {
-
-		table->tbl_times[i] = data->tblcmd_snaps[i].time;
-		table->tbl_index[i] = data->tblcmd_snaps[i].index;
-		memcpy(table->tbl_name[i], data->tblcmd_snaps[i].name, 
-			SNAP_MAX_NAMELEN);
-		table->tbl_name[i][SNAP_MAX_NAMELEN - 1] = '\0';
 
-		CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n",
-		       i, table->tbl_times[i], table->tbl_index[i], 
-			table->tbl_name[i]);
-	}
-*/
-	/* below : new, we don't need current snapshot for data
-	 * current snapshot always has slot 0, index 0, name "current" 
-	 */
-	table->tbl_times[0] = 0;
-	table->tbl_index[0] = 0;
-	strcpy(table->tbl_name[0], "current");
+	CDEBUG(D_INODE, "delete_inode ino %lu, index %d\n", primary->i_ino, index);
 
-	i=0;	
-	CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n",
-	       i, table->tbl_times[i], table->tbl_index[i], 
-		table->tbl_name[i]);
+	table = &snap_tables[tableno];
 
-	for (i = 0 ; i < data->tblcmd_count ; i++) {
+	redirect = snap_get_indirect(primary, NULL, index);
 
-		table->tbl_times[i+1] = data->tblcmd_snaps[i].time;
-		table->tbl_index[i+1] = data->tblcmd_snaps[i].index;
-		memcpy(table->tbl_name[i+1], data->tblcmd_snaps[i].name, 
-			SNAP_MAX_NAMELEN);
-		table->tbl_name[i+1][SNAP_MAX_NAMELEN - 1] = '\0';
+	if(!redirect)	
+		return 0;
 
-		CDEBUG(D_SNAP, "snaplist: i %d, time %ld, idx %d, name %s\n",
-		       i+1, table->tbl_times[i+1], table->tbl_index[i+1], 
-			table->tbl_name[i+1]);
+	old_ind = redirect->i_ino;
+	iput(redirect);
+	slot = snap_index2slot(table, index) - 1;
+	if( slot > 0 ) {
+		this_index = table->snap_items[slot].index;
+		redirect = snap_get_indirect(primary, NULL, this_index);
+		if(redirect)	
+			iput(redirect);
+		else  {
+			snap_set_indirect(primary, old_ind, this_index, 0);
+			snap_set_indirect(primary, 0, index, 0);
+			return 0;
+		}
+	}
+
+	/* get the FIRST index after this and before NOW */
+	/* used for destroy_indirect and block level cow */
+ 	/* XXX fix this later, now use tbl_count, not NOW */
+	delete_slot = snap_index2slot(table, index);
+	for(slot = table->tbl_count; slot > delete_slot; slot --)
+	{
+		my_table[slot - delete_slot] = table->snap_items[slot].index;
+	}
+	next_ind = snap_get_indirect 
+		(primary, my_table, table->tbl_count - delete_slot );
+	if( next_ind && (next_ind->i_ino == primary->i_ino) ) {
+		iput(next_ind);
+		next_ind = NULL;
 	}
 
-	for ( i = data->tblcmd_count + 1 ; i < SNAP_MAX ; i++ ) {
-		table->tbl_times[i] = 0;
-		table->tbl_index[i] = 0;
-		memset(table->tbl_name[i], 0, SNAP_MAX_NAMELEN);
+	if( next_ind && (next_ind->i_ino == old_ind) ) {
+		iput(next_ind);
+		next_ind = NULL;
 	}
 
-	/* set the table count */
-//	table->tbl_count = data->tblcmd_count;
-	table->tbl_count = data->tblcmd_count + 1;
+	rc = snap_destroy_indirect(primary, index, next_ind);
+
+	if(next_ind)	iput(next_ind);
+
+	if(rc != 0)	
+		CERROR("snap_destroy_indirect(ino %lu,index %d),ret %d\n",
+			primary->i_ino, index, rc);
 	return 0;
 }
 
+static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
+{
+	CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
+		data->dev, data->tableno, data->index, data->time );
 
-int snap_table_attach(int tableno, int snap_index) 
+	snap_iterate(sb, &delete_inode, NULL, data, SNAP_ITERATE_COWED_INODE);
+	
+	return 0;
+}
+
+/* This function will delete one item(a snapshot) in the snaptable  
+ * and will also delete the item in the disk.
+ */
+int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
 {
-	struct snap_table *table;
+	struct snap_table 		*table;
+	struct snap_disk_table 		*disk_snap_table;
+	struct snapshot_operations 	*snapops;
+	struct snap_cache 		*cache;
+	int 				tableno = data->tableno, index, i, slot, rc, count;
+	
+	if (!(cache = snap_find_cache((kdev_t)data->dev)))
+		RETURN(-ENODEV);
+
+	snapops = filter_c2csnapops(cache->cache_filter);
+	if (!snapops || !snapops->set_meta_attr)
+		RETURN(-EINVAL);
+
+	if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
+		CERROR("invalid table number %d\n", tableno);
+		RETURN(-EINVAL);
+	}
+	/*first delete the snapshot
+	 * FIXME if snap delete error, how to handle this error*/
+	rc = snap_delete(sb, data);
+	if (rc) 
+		RETURN(-EINVAL);
+	/*delete item in snaptable */
+	table = &snap_tables[tableno];
+	index = data->index;
 
-	if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid table number %d\n", tableno);
-		EXIT;
-		return -EINVAL;
+	slot = snap_index2slot(table, index);
+	if (slot < 0)
+		RETURN(-EINVAL);
+
+	down_interruptible(&table->tbl_sema);
+	while(slot < table->tbl_count) {
+		struct snap *item = &table->snap_items[slot];
+		item->time = table->snap_items[slot + 1].time;
+		item->flags = table->snap_items[slot + 1].flags;
+		item->gen = table->snap_items[slot + 1].gen;
+		item->index = table->snap_items[slot + 1].index;
+		memcpy(&item->name[0], &table->snap_items[slot + 1].name[0],
+			SNAP_MAX_NAMELEN);
 	}
-	table = &snap_tables[tableno];	
+
+	table->tbl_count --;
 	
-	if ( snap_index2slot(table, snap_index) < 0 ) {
-		printk(__FUNCTION__ ": snap index %d not present in table %d\n",
-		       snap_index, tableno);
-		return -EINVAL;
+	SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
+
+	if (!disk_snap_table)
+		RETURN(-ENOMEM);
+	/* we will delete the item  snap_table to disk */
+	
+	disk_snap_table->magic = cpu_to_le32((__u32)DISK_SNAP_TABLE_MAGIC);
+	disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count);
+	disk_snap_table->generation = cpu_to_le32((__u32)table->generation);
+	memset(&disk_snap_table->snap_items[0], 0, 
+	       SNAP_MAX * sizeof(struct snap_disk));
+
+	count = table->tbl_count;
+
+	for (i = 1; i <= count; i++) {
+		struct snap *item = &table->snap_items[i];
+		disk_snap_table->snap_items[i].time = cpu_to_le64((__u64)item->time);
+		disk_snap_table->snap_items[i].gen = cpu_to_le32((__u32)item->gen);
+		disk_snap_table->snap_items[i].flags = cpu_to_le32((__u32)item->flags);
+		disk_snap_table->snap_items[i].index = cpu_to_le32((__u32)item->index);
+		memcpy(&disk_snap_table->snap_items[i].name , item->name, SNAP_MAX_NAMELEN);
+	}
+	rc = snapops->set_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
+				    (char*)disk_snap_table, sizeof(struct snap_disk_table));
+
+	SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
+	
+	up(&table->tbl_sema);
+	
+	RETURN(0);
+}
+
+int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
+{
+	struct snap_table 		*table;
+	struct snap_disk_table 		*disk_snap_table;
+	struct snapshot_operations 	*snapops;
+	int 				i, rc;
+	int				size = 0;
+
+	
+	snapops = filter_c2csnapops(cache->cache_filter);
+	if (!snapops || !snapops->get_meta_attr)
+		RETURN(-EINVAL);
+	
+	SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
+
+	size = sizeof(struct snap_disk_table);
+
+	rc = snapops->get_meta_attr(cache->cache_sb, DISK_SNAPTABLE_ATTR,
+			       (char*)disk_snap_table, &size);
+	if (rc < 0) {
+		SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
+		RETURN(rc);
 	}
+	table = &snap_tables[tableno];
 
-	snap_use(tableno, snap_index);
+	if (le32_to_cpu(disk_snap_table->magic) != DISK_SNAP_TABLE_MAGIC) {
+		CERROR("On disk snaptable is not right \n");
+		RETURN(rc);
+	}
+	table->generation = le32_to_cpu(disk_snap_table->generation);
+	table->tbl_count = le32_to_cpu(disk_snap_table->count);
+	for ( i = 0; i < disk_snap_table->count; i++) {
+		struct snap *item = &table->snap_items[i + 1];
+		item->time = le64_to_cpu(disk_snap_table->snap_items[i].time);
+		item->gen = le32_to_cpu(disk_snap_table->snap_items[i].gen);
+		item->flags = le32_to_cpu(disk_snap_table->snap_items[i].flags);
+		item->index = le32_to_cpu(disk_snap_table->snap_items[i].index);
+		memcpy(&item->name[0], &disk_snap_table->snap_items[i].name[0],
+		       SNAP_MAX_NAMELEN);
+	}
+	SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
 	return 0;
 }
 
@@ -450,16 +495,16 @@ static int getdata(int len, void **data)
 		return 0;
 	}
 
-	SNAP_ALLOC(tmp, void *, len);
+	SNAP_ALLOC(tmp, len);
 	if ( !tmp )
 		return -ENOMEM;
 
-	CDEBUG(D_MALLOC, "snap_alloc:len %d, add %p\n", len, tmp);
+	CDEBUG(D_SNAP, "snap_alloc:len %d, add %p\n", len, tmp);
 
 	memset(tmp, 0, len);
 	if ( copy_from_user(tmp, *data, len)) {
 		SNAP_FREE(tmp, len);
-		CDEBUG(D_MALLOC, "snap_free:len %d, add %p\n", len, tmp);
+		CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, tmp);
 		return -EFAULT;
 	}
 	*data = tmp;
@@ -469,7 +514,7 @@ static int getdata(int len, void **data)
 
 static void freedata(void *data, int len) {
 	SNAP_FREE(data, len);
-	CDEBUG(D_MALLOC, "snap_free:len %d, add %p\n", len, data);
+	CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, data);
 }
 
 static int get_next_inode(struct inode *pri, void *ino)
@@ -527,7 +572,7 @@ static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino
 	*parent_ino = 0;
 	inode = iget (cache->cache_sb, *found_ino);
 	if (list_empty(&inode->i_dentry)) {
-		printk("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino);
+		CERROR("No dentry for ino %lu, Error(XXX)! \n", inode->i_ino);
 		iput(inode);	
        		return 0;
 	}
@@ -544,35 +589,6 @@ static int snap_get_next_inode(struct snap_ino_list_data *data, ino_t *found_ino
 
 	return 0;
 }
-/*
-static int snap_get_inode_info(struct snap_ino_list_data *data,  int index)
-{
-	kdev_t dev = data->dev;
-	ino_t pri = data->ino; 
-	int index = data->index;
-
-	struct snap_cache *cache;
-
-	struct inode *pri;
-	struct inode *ind;
-	ino_t ind_ino = 0;
-
-	ENTRY;
-
-	cache = snap_find_cache(dev); 
-	if ( !cache ) {
-                EXIT;
-                return -EINVAL;
-        }
-	pri = iget(cache->cache->sb, pri_ino);
-	ind = snap_get_indirect(pri, NULL, index);
-	if(ind)	{
-		ind_ino = ind->i_ino;	
-		iput(ind);
-	}
-	return ind_ino;
-}
-*/
 
 static int print_inode(struct inode *pri,void *param)
 {
@@ -586,94 +602,6 @@ static int snap_print(struct super_block *sb, void *data)
 	return 0;
 }
 
-static int delete_inode(struct inode *primary, void *param)
-{
-	struct snap_iterdata * data;
-	int tableno = 0;
-	int index = 0;
-	int rc = 0;
-
-	struct inode *redirect;
-	ino_t old_ind = 0;
-	struct snap_table *table;
-	int slot;
-	int delete_slot;
-	int this_index;
-	struct inode *next_ind = NULL;
-	int my_table[SNAP_MAX];
-
-	if(!primary) return 0;
-
-	data = (struct snap_iterdata*) param;
-
-	if(data) {
-		index = data->index;
-		tableno = data->tableno;
-	}
-
-	printk("delete_inode ino %lu, index %d\n", primary->i_ino, index);
-
-	table = &snap_tables[tableno];
-
-	redirect = snap_get_indirect(primary, NULL, index);
-
-	if(!redirect)	
-		return 0;
-
-	old_ind = redirect->i_ino;
-	iput(redirect);
-	slot = snap_index2slot(table, index) - 1;
-	if( slot > 0 ) {
-		this_index = table->tbl_index[slot];
-		redirect = snap_get_indirect(primary, NULL, this_index);
-		if(redirect)	
-			iput(redirect);
-		else  {
-			snap_set_indirect(primary, old_ind, this_index, 0);
-			snap_set_indirect(primary, 0, index, 0);
-			return 0;
-		}
-	}
-
-	/* get the FIRST index after this and before NOW */
-	/* used for destroy_indirect and block level cow */
- 	/* XXX fix this later, now use tbl_count, not NOW */
-	delete_slot = snap_index2slot(table, index);
-	for(slot = table->tbl_count; slot > delete_slot; slot --)
-	{
-		my_table[slot - delete_slot] = table->tbl_index[slot];
-	}
-	next_ind = snap_get_indirect 
-		(primary, my_table, table->tbl_count - delete_slot );
-	if( next_ind && (next_ind->i_ino == primary->i_ino) ) {
-		iput(next_ind);
-		next_ind = NULL;
-	}
-
-	if( next_ind && (next_ind->i_ino == old_ind) ) {
-		iput(next_ind);
-		next_ind = NULL;
-	}
-
-	rc = snap_destroy_indirect(primary, index, next_ind);
-
-	if(next_ind)	iput(next_ind);
-
-	if(rc != 0)	
-		printk("ERROR:snap_destroy_indirect(ino %lu,index %d),ret %d\n", 			primary->i_ino, index, rc);
-	return 0;
-}
-
-static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
-//static int snap_delete(struct super_block *sb, void *data)
-{
-	CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
-		data->dev, data->tableno, data->index, data->time );
-
-	snap_iterate(sb,&delete_inode,NULL, data, SNAP_ITERATE_COWED_INODE);
-	return 0;
-}
-
 static int delete_new_inode(struct inode *pri, void *param)
 {
 	struct snap_iterdata * data;
@@ -706,7 +634,6 @@ static int delete_new_inode(struct inode *pri, void *param)
 
 		CDEBUG(D_SNAP, "snap_restore ino %lu is newer, delete \n",pri->i_ino);
 		for( pos = head->next; pos != head; pos = pos->next ){
-//			d_invalidate( list_entry(pos, struct dentry, d_alias) );
 			d_drop( list_entry(pos, struct dentry, d_alias) );
 		}
 		pri->i_nlink = 0;
@@ -728,7 +655,6 @@ static int restore_inode(struct inode *pri, void *param)
 	int slot;
 	int restore_slot;
 	struct snap_table *table;
-//	int my_table[SNAP_MAX];
 	int restore_index;
 	
 	ENTRY; 
@@ -760,33 +686,18 @@ static int restore_inode(struct inode *pri, void *param)
 			for(slot = restore_slot; slot <= table->tbl_count; 
 			    slot++) {
 				ind = snap_get_indirect (pri, NULL, 
-					table->tbl_index[slot]);
+					table->snap_items[slot].index);
 				if(ind)	{
-					restore_index = table->tbl_index[slot];
+					restore_index = table->snap_items[slot].index;
 					break;
 				}
 			}
-/*			for(slot = table->tbl_count; slot >= restore_slot; 
-				slot --)
-			{
-				my_table[slot - restore_slot + 1] = 
-					table->tbl_index[slot];
-			}
-			ind = snap_get_indirect (pri, my_table, 
-					table->tbl_count - restore_slot + 1);
-
-			if( ind && (ind->i_ino == pri->i_ino) )	{
-				iput(ind);
-				ind =  NULL;
-			}
-*/
 		}
 
 		if(ind) {
 			CDEBUG(D_SNAP, "restore ino %lu with index %d\n",
 					pri->i_ino, restore_index);
 			iput(ind);
-//			snap_restore_indirect(pri, index);
 			snap_restore_indirect(pri, restore_index);
 			/* XXX */
 			//delete_inode(pri, param);
@@ -797,7 +708,7 @@ static int restore_inode(struct inode *pri, void *param)
 		}
 	}
 	else {
-		printk("ino %lu is older, don't restore\n",pri->i_ino);
+		CDEBUG(D_SNAP, "ino %lu is older, don't restore\n", pri->i_ino);
 	}
 	EXIT;
 	return 0;
@@ -821,21 +732,16 @@ int snap_get_index_from_name(int tableno, char *name)
 	int slot;
 
 	if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-		printk(__FUNCTION__ ": invalid table number %d\n", tableno);
+		CDEBUG(D_SNAP, ": invalid table number %d\n", tableno);
 		return -EINVAL;
 	}
 
 	table = &snap_tables[tableno];
 
 	for ( slot = 0 ; slot < SNAP_MAX ; slot++ ) {
-/*		if(memcmp (table->tbl_name[slot], name, 
-			strlen(table->tbl_name[slot]) ) == 0 ) {
-			return table->tbl_index[slot];
-		}
-*/
-		if(strncmp (table->tbl_name[slot], name, 
+		if(strncmp (&table->snap_items[slot].name[0], name, 
 			SNAP_MAX_NAMELEN) == 0 ) {
-			return table->tbl_index[slot];
+			return table->snap_items[slot].index;
 		}
 	}
 	return -EINVAL;
@@ -844,27 +750,20 @@ int snap_get_index_from_name(int tableno, char *name)
 int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd)
 {
 	struct snap_iterdata data;
-
-	kdev_t dev ;
-	char name[SNAP_MAX_NAMELEN];
-
-	int index ;
-	int tableno; 
-	int name_len;
-	int slot;
-
 	struct super_block *sb;
 	struct snap_cache *cache;
 	struct snap_table *table;
+	char name[SNAP_MAX_NAMELEN];
+	int index, tableno, name_len, slot, rc;
+	
+	kdev_t dev ;
 
 	ENTRY;
 
 	dev = ioc_data->dev;
 	cache = snap_find_cache(dev); 
-	if ( !cache ) {
-                EXIT;
-                return -EINVAL;
-        }
+	if ( !cache ) 
+                RETURN(-EINVAL);
 
 	sb = cache->cache_sb;
 	tableno = cache->cache_snap_tableno;
@@ -877,41 +776,37 @@ int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd)
 	if(name_len < 0 ) 
 		name_len = 0;
 	memcpy(name, ioc_data->name, name_len);
-	if ( (index = snap_get_index_from_name (tableno, name)) < 0 ) {
-		EXIT;
-		return -EINVAL;
-	}
+	
+	if ((index = snap_get_index_from_name (tableno, name)) < 0) 
+		RETURN(-EINVAL);
 	
 	data.dev = dev;
 	data.index = index;
 	data.tableno = tableno;
 	slot = snap_index2slot (table, index);
-	if( slot < 0 ) {
-		EXIT;
-		return -EINVAL;
-	}
-	data.time = table->tbl_times[slot];
-
+	if( slot < 0 ) 
+		RETURN(-EINVAL);
+	
+	data.time = table->snap_items[slot].time;
 	CDEBUG(D_SNAP, "dev %d, tableno %d, index %d, time %lu\n",
 		data.dev, data.tableno, data.index, data.time );
 
 	switch (cmd) {
 		case IOC_SNAP_DEBUG:
-			snap_print(sb, &data);	
+			rc = snap_print(sb, &data);	
 			break;
 		case IOC_SNAP_DELETE:
-			snap_delete(sb, &data);	
+			rc = snaptable_delete_item(sb, &data);	
 			break;
 		case IOC_SNAP_RESTORE:
-			snap_restore(sb, &data);	
+			rc = snap_restore(sb, &data);	
 			break;
 		default:
-			return -EINVAL;
+			CERROR("unrecognized cmd %d \n", cmd);
+			rc = -EINVAL;
+			break;
 	}
-	
-	EXIT;
-
-	return 0;
+	RETURN(0);
 }
 
 int snap_ioctl (struct inode * inode, struct file * filp, 
@@ -941,10 +836,12 @@ int snap_ioctl (struct inode * inode, struct file * filp,
         if ( _IOC_TYPE(cmd) != IOC_SNAP_TYPE || 
              _IOC_NR(cmd) < IOC_SNAP_MIN_NR  || 
              _IOC_NR(cmd) > IOC_SNAP_MAX_NR ) {
-                CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
+                /*FIXME: Sometimes Gettimeof the day will come here
+		 * Do not know the reason*/
+		CDEBUG(D_IOCTL, "invalid ioctl ( type %d, nr %d, size %d )\n",
                                 _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd));
                 EXIT;
-                return -EINVAL;
+                return 0;
         }
 
 	/* get data structures */
@@ -964,8 +861,8 @@ int snap_ioctl (struct inode * inode, struct file * filp,
 	}
 	
 	switch (cmd) {
-	case IOC_SNAP_SETTABLE:
-		rc = snap_install_table(len, karg);
+	case IOC_SNAP_ADD:
+		rc = snaptable_add_item(karg);
 		break;
 	case IOC_SNAP_PRINTTABLE: {
 		struct output_data{
@@ -1064,9 +961,11 @@ int snap_ioctl (struct inode * inode, struct file * filp,
 	case IOC_SNAP_DEBUG:
 		rc = snap_iterate_func(len, karg, cmd);
 		break;
+#ifdef SNAP_DEBUG
 	case IOC_SNAP_DEVFAIL:
 		snap_debug_failcode = (unsigned int)arg;
 		break;
+#endif
 	case IOC_SNAP_SHOW_DOTSNAP: {
 		struct ioc_show_info{
 			kdev_t dev;
diff --git a/lustre/snapfs/super.c b/lustre/snapfs/super.c
index f1019771a87a67f086ab38d6b08e6c01858057e2..e4b4ef8b9a66ca62408fa48b3c92937d4c813a11 100644
--- a/lustre/snapfs/super.c
+++ b/lustre/snapfs/super.c
@@ -8,43 +8,22 @@
  *
  *  Author: Peter J. Braam <braam@mountainviewdata.com>
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-
-#include <stdarg.h>
-
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/dcache.h>
-
-#ifdef CONFIG_SNAPFS_EXT2
-#include <linux/ext2_fs.h>
-#endif
-#ifdef CONFIG_SNAPFS_EXT3
-#include <linux/ext3_fs.h>
-#endif
-
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/blkdev.h>
-#include <linux/init.h>
-#define __NO_VERSION__
-#include <linux/module.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+#include <linux/errno.h>
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 #ifdef SNAP_DEBUG
-long snap_vmemory = 0;
-long snap_kmemory = 0;
 unsigned int snap_debug_failcode = 0;
 #endif
 
@@ -54,15 +33,16 @@ extern inline void snap_init_cache_hash(void);
 
 extern int snap_get_index_from_name (int tableno, char *name);
 
-#ifdef CONFIG_SNAPFS_EXT2
-extern struct snapshot_operations ext2_snap_operations;
-extern struct journal_ops snap_ext2_journal_ops;
-#endif
 
-#ifdef CONFIG_SNAPFS_EXT3
 extern struct snapshot_operations ext3_snap_operations;
 extern struct journal_ops snap_ext3_journal_ops;
-#endif
+                                                                                                                                                                                                     
+static void put_filesystem(struct file_system_type *fs)
+{
+	if (fs->owner)
+		__MOD_DEC_USE_COUNT(fs->owner);
+}
+
 
 /* returns an allocated string, copied out from data if opt is found */
 static char *read_opt(const char *opt, char *data)
@@ -78,9 +58,9 @@ static char *read_opt(const char *opt, char *data)
 		return NULL;
 
 	value++;
-	SNAP_ALLOC(retval, char *, strlen(value) + 1);
+	SNAP_ALLOC(retval, strlen(value) + 1);
 	if ( !retval ) {
-		printk("snapfs: Out of memory!\n");
+		CERROR("snapfs: Out of memory!\n");
 		return NULL;
 	}
 
@@ -114,15 +94,15 @@ static char *snapfs_options(char *options, char *cache_data,
 
 	/* set the defaults here */
 	if (cache_type && !*cache_type) {
-		SNAP_ALLOC(*cache_type, char *, strlen("ext2") + 1);
-		strcpy(*cache_type, "ext2");
+		SNAP_ALLOC(*cache_type, strlen("ext3") + 1);
+		strcpy(*cache_type, "ext3");
 	}
 	if (cow_type && !*cow_type) {
-		SNAP_ALLOC(*cow_type, char *, strlen("block") + 1);
+		SNAP_ALLOC(*cow_type, strlen("block") + 1);
 		strcpy(*cow_type, "block");
 	}
 	if (snaptable && !*snaptable) {
-		SNAP_ALLOC(*snaptable, char *, strlen("-1")+1);
+		SNAP_ALLOC(*snaptable, strlen("-1")+1);
 		strcpy(*snaptable, "-1");
 	}
 
@@ -167,25 +147,18 @@ int snapfs_remount(struct super_block * sb, int *flags, char *data)
 	int err = 0;
 
 	ENTRY;
-	CDEBUG(D_MALLOC, "before remount: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
 	CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)");
 	if (data) {
 		/* reserve space for the cache's data */
-		SNAP_ALLOC(cache_data, void *, PAGE_SIZE);
-		if ( !cache_data ) {
-			err = -ENOMEM;
-			EXIT;
-			goto out_err;
-		}
+		SNAP_ALLOC(cache_data, PAGE_SIZE);
+		if ( !cache_data ) 
+			GOTO(out_err, err = -ENOMEM);
 	}
 
 	cache = snap_find_cache(sb->s_dev);
 	if (!cache) {
-		printk(__FUNCTION__ ": cannot find cache on remount\n");
-		err = -ENODEV;
-		EXIT;
-		goto out_err;
+		CERROR("cannot find cache on remount\n");
+		GOTO(out_err, err = -ENODEV);
 	}
 
 	/* If an option has not yet been set, we allow it to be set on
@@ -211,8 +184,6 @@ int snapfs_remount(struct super_block * sb, int *flags, char *data)
 		err = sops->remount_fs(sb, flags, cache_data);
 	}
 
-	CDEBUG(D_MALLOC, "after remount: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
 	EXIT;
 out_err:
 	if (cache_data)
@@ -251,15 +222,12 @@ snapfs_read_super (
 	int tableno;
 
 	ENTRY;
-	CDEBUG(D_MALLOC, "before parsing: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
 
 	/* reserve space for the cache's data */
-	SNAP_ALLOC(cache_data, void *, PAGE_SIZE);
+	SNAP_ALLOC(cache_data, PAGE_SIZE);
 	if ( !cache_data ) {
-		printk("snapfs_read_super: Cannot allocate data page.\n");
-		EXIT;
-		goto out_err;
+		CERROR("snapfs_read_super: Cannot allocate data page.\n");
+		GOTO(out_err, 0);
 	}
 
 	CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
@@ -281,20 +249,21 @@ snapfs_read_super (
 	/* set up the cache */
 	cache = snap_init_cache();
 	if ( !cache ) {
-		printk("snapfs_read_super: failure allocating cache.\n");
-		EXIT;
-		goto out_err;
+		CERROR("snapfs_read_super: failure allocating cache.\n");
+		GOTO(out_err, 0);
 	}
 
 	fstype = get_fs_type(cache_type);
 	if ( !fstype || !fstype->read_super) {
-		EXIT;
-		goto out_err;
+		GOTO(out_err, 0);
 	}
 	
 	cache->cache_filter = filter_get_filter_fs((const char *)cache_type); 
-	/* XXX if cache->cache_filter==NULL?although it's rare ***/
-
+	
+	if (!cache->cache_filter) {
+		CERROR("Unrecognized cache type %s \n", cache_type);
+		GOTO(out_err, 0);
+	}
 
 	/*
          * Read the underlying file system superblock - ext2, ext3, reiser.
@@ -303,20 +272,12 @@ snapfs_read_super (
          *
          * Note: It's assumed that sb is always returned.
          */
-	CDEBUG(D_SUPER, "\n");
 	if (fstype->read_super(sb, cache_data, silent) != sb) {
-		printk("snapfs: cache mount failure.\n");
-		EXIT;
-		goto out_err;
+		CERROR("snapfs: cache mount failure.\n");
+		GOTO(out_err, 0);
         }
 
-	/* XXX now look at the flags in the superblock and determine if this 
-	       is a block cow file system or a file cow fs.  Then assign the 
-	       snap operations accordingly.  This goes in the sections for ext2/ext3/xfs etc
-        */ 
-
 	/* this might have been freed above */
-	CDEBUG(D_SUPER, "\n");
 	if (cache_data) {
 		SNAP_FREE(cache_data, PAGE_SIZE);
 		cache_data = NULL;
@@ -329,14 +290,13 @@ snapfs_read_super (
          * 'cache' is the struct snap_cache allocated for this
          * snapfs mount.
          */
-	CDEBUG(D_SUPER, "\n");
 	snap_cache_add(cache, sb->s_dev);
 
 	tableno  =  simple_strtoul(snapno, &endptr, 0);
 	cache->cache_snap_tableno = tableno;
 
-	CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
 
+	CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
 	/*
          * make sure we have our own super operations
          *
@@ -344,10 +304,8 @@ snapfs_read_super (
          * struct snap_ops structure set based on the underlying
          * file system type.
          */
-	CDEBUG(D_SUPER, "\n");
 	filter_setup_super_ops(cache->cache_filter, sb->s_op,
 			       &currentfs_super_ops);
-	CDEBUG(D_SUPER, "\n");
 	sb->s_op = filter_c2usops(cache->cache_filter); 
         /*
          * Save pointers in the snap_cache structure to the
@@ -358,25 +316,6 @@ snapfs_read_super (
 	/* set up snapshot ops, handle COMPAT_FEATUREs */
 	if( 0 ){
 	}
-#ifdef CONFIG_SNAPFS_EXT2
-	else if ( strcmp (cache_type,"ext2") == 0 ){
-		cache->cache_type = FILTER_FS_EXT2;
-		filter_setup_snapshot_ops(cache->cache_filter, 
-					&ext2_snap_operations);
-		filter_setup_journal_ops(cache->cache_filter,
-					&snap_ext2_journal_ops);
-		if( !EXT2_HAS_COMPAT_FEATURE(sb, EXT2_FEATURE_COMPAT_SNAPFS) ){
-			if( strcmp(cow_type, "block")==0 ){
-				sb->u.ext2_sb.s_feature_compat |=
-					EXT2_FEATURE_COMPAT_BLOCKCOW;
-				sb->u.ext2_sb.s_es->s_feature_compat |=
-					cpu_to_le32(EXT2_FEATURE_COMPAT_BLOCKCOW);
-			}
-		}
-                sb->u.ext2_sb.s_last_cowed_ino = 0;
-	}
-#endif
-#ifdef CONFIG_SNAPFS_EXT3
 	else if ( strcmp (cache_type,"ext3") == 0 ){
 		cache->cache_type = FILTER_FS_EXT3;
 		filter_setup_snapshot_ops(cache->cache_filter,
@@ -389,37 +328,32 @@ snapfs_read_super (
 					cpu_to_le32(EXT3_FEATURE_COMPAT_BLOCKCOW);
 			}
 		}
-		sb->u.ext3_sb.s_last_cowed_ino = 0;
+		sb->u.ext3_sb.s_last_cowed_pri_ino = 0;
+		sb->u.ext3_sb.s_first_cowed_pri_ino = 0;
 	}
-#endif
-
-	CDEBUG(D_SUPER, "\n");
 	/* now get our own directory operations */
 	if ( sb->s_root && sb->s_root->d_inode ) {
-		CDEBUG(D_SUPER, "\n");
 		filter_setup_dir_ops(cache->cache_filter, 
-				     sb->s_root->d_inode->i_op,
-				     &currentfs_dir_iops);
-		CDEBUG(D_SUPER, "\n");
+				     sb->s_root->d_inode,
+				     &currentfs_dir_iops, &currentfs_dir_fops);
 		sb->s_root->d_inode->i_op =filter_c2udiops(cache->cache_filter);
-//	CDEBUG(D_SUPER, "\n");
-//		sb->s_root->d_inode->i_snapop = ext2_snapops();
 
 		CDEBUG(D_SUPER, "lookup at %p\n", 
 		       sb->s_root->d_inode->i_op->lookup);
-#if 0
-		/* XXX is this needed ?? */
+		/* XXX is this needed ?? ext3 do not have dentry operations*/
 		filter_setup_dentry_ops(cache->cache_filter, 
 					sb->s_root->d_op, 
 					&currentfs_dentry_ops);
 		sb->s_root->d_op = filter_c2udops(cache->cache_filter);
-#endif
 	}
         /*
          * Save a pointer to the snap_cache structure in the
          * "snap_current" superblock.
          */
         (struct snap_cache *) sb->u.generic_sbp = cache;
+
+	snapfs_read_snaptable(cache, tableno);
+	
 	CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) sb->u.generic_sbp);
 
@@ -436,12 +370,10 @@ snapfs_read_super (
 		SNAP_FREE(cow_type, strlen(cow_type) + 1);
 		cow_type = NULL;
 	}
+	/* Inc in get_fs_type, Dec in put_fs_type*/
 
-	CDEBUG(D_MALLOC, "after mounting: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
-
-	MOD_INC_USE_COUNT;
-	EXIT;
+	put_filesystem(fstype);
+	
 	return sb;
 
  out_err:
@@ -456,19 +388,13 @@ snapfs_read_super (
 		SNAP_FREE(cache_type, strlen(cache_type) + 1);
 	if (cow_type)
 		SNAP_FREE(cow_type, strlen(cow_type) + 1);
+	if (fstype)
+		put_filesystem(fstype);
 
-	CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
 	return NULL;
 }
 
-
-struct file_system_type snapfs_current_type = {
-	"snap_current",
-	FS_REQUIRES_DEV, /* can use Ibaskets when ext2 does */
-	snapfs_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(snapfs_current_type, "snap_current", snapfs_read_super);
 
 
 /* Find the options for the clone. These consist of a cache device
@@ -510,19 +436,26 @@ static char *clonefs_options(char *options, char *cache_data,
 static int snapfs_path2dev(char *dev_path, kdev_t *dev)
 {
 	struct dentry *dentry;
+	struct nameidata nd;
+	int error = 0;
+	
+	if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
+		error = path_walk(dev_path, &nd);
+		if (error)
+			return error;
+	} else
+		return -EINVAL;
 
-	dentry = lookup_dentry(dev_path, NULL, 0);
-	if (IS_ERR(dentry))
-		return PTR_ERR(dentry);
+	dentry = nd.dentry;
 
-	if (!dentry->d_inode)
-		return -ENODEV;
-
-	if (!S_ISBLK(dentry->d_inode->i_mode))
+	if (!dentry->d_inode || !S_ISBLK(dentry->d_inode->i_mode) || 
+	    is_bad_inode(dentry->d_inode) ) {
+		path_release(&nd);
 		return -ENODEV;
+	}
 
 	*dev = dentry->d_inode->i_rdev;
-
+	path_release(&nd);
 	return 0;
 }
 
@@ -554,15 +487,12 @@ clone_read_super(
 
 	ENTRY;
 
-	CDEBUG(D_MALLOC, "before parsing: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
 
 	/* reserve space for the cache's data */
-	SNAP_ALLOC(cache_data, void *, PAGE_SIZE);
+	SNAP_ALLOC(cache_data, PAGE_SIZE);
 	if ( !cache_data ) {
-		printk("clone_read_super: Cannot allocate data page.\n");
-		EXIT;
-		goto out_err;
+		CERROR("clone_read_super: Cannot allocate data page.\n");
+		GOTO(out_err, 0);
 	}
 
 	CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
@@ -575,29 +505,25 @@ clone_read_super(
 		SNAP_FREE(cache_data, PAGE_SIZE);
 		cache_data = NULL;
 	} else {
-		printk("clonefs: invalid mount option %s\n", cache_data);
-		EXIT;
-		goto out_err;
+		CERROR("clonefs: invalid mount option %s\n", cache_data);
+		GOTO(out_err, 0);
 	}
 
 	if (!namestr || !devstr) {
-		printk("snapfs: mount options name and dev mandatory\n");
-		EXIT;
-		goto out_err;
+		CERROR("snapfs: mount options name and dev mandatory\n");
+		GOTO(out_err, 0);
 	}
 
 	err = snapfs_path2dev(devstr, &dev);
 	if ( err ) {
-		printk("snap: incorrect device option %s\n", devstr);
-		EXIT;
-		goto out_err;
+		CERROR("snap: incorrect device option %s\n", devstr);
+		GOTO(out_err, 0);
 	}
 	
 	snap_cache = snap_find_cache(dev);
 	if ( !snap_cache ) {
-		printk("snap: incorrect device option %s\n", devstr);
-		EXIT;
-		goto out_err;
+		CERROR("snap: incorrect device option %s\n", devstr);
+		GOTO(out_err, 0);
 	}
 
 	/*index =  simple_strtoul(indexstr, &endptr, 0);
@@ -614,9 +540,8 @@ clone_read_super(
 			snap_cache->cache_snap_tableno, namestr, index);
 
 	if(index < 0 ) {
-		printk("No valid index for name %s passed to mount\n",namestr); 
-		EXIT;
-		goto out_err;
+		CERROR("No valid index for name %s passed to mount\n",namestr); 
+		GOTO(out_err, 0);
 	}
 
         /*
@@ -640,13 +565,13 @@ clone_read_super(
 	CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
 	       sb->s_op->read_inode, root_ino, root_inode);
 
-	sb->s_root = d_alloc_root(root_inode, NULL);
+	sb->s_root = d_alloc_root(root_inode);
 	if (!sb->s_root) {
 		list_del(&clone_sb->clone_list_entry);
 		sb = NULL;
 	}
 
-	dget( snap_cache->cache_sb->s_root );
+	dget(snap_cache->cache_sb->s_root);
 
 	if (cache_data)
 		SNAP_FREE(cache_data, PAGE_SIZE);
@@ -656,39 +581,29 @@ clone_read_super(
 		SNAP_FREE(namestr, strlen(namestr) + 1);
 	CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
                 (ulong) sb, (ulong) &sb->u.generic_sbp);
-
-	MOD_INC_USE_COUNT;
-	EXIT;
 	return sb;
  out_err:
-	CDEBUG(D_MALLOC, "mount error exit: kmem %ld, vmem %ld\n",
-	       snap_kmemory, snap_vmemory);
 	return NULL;
 }
 
-
-struct file_system_type snapfs_clone_type = {
-	"snap_clone",
-	0,
-	clone_read_super,
-	NULL
-};
-
+static DECLARE_FSTYPE(snapfs_clone_type, "snap_clone", clone_read_super, 0);
 
 int init_snapfs(void)
 {
 	int status;
 
 	snap_init_cache_hash();
+	init_filter_info_cache();
 
-	status = register_filesystem(&snapfs_current_type);
-	if (status) {
-		printk("snapfs: failed in register current filesystem!\n");
-	}
 	status = register_filesystem(&snapfs_clone_type);
 	if (status) {
 		unregister_filesystem(&snapfs_current_type);
-		printk("snapfs: failed in register clone filesystem!\n");
+		CERROR("snapfs: failed in register clone filesystem!\n");
+	}
+
+	status = register_filesystem(&snapfs_current_type);
+	if (status) {
+		CERROR("snapfs: failed in register current filesystem!\n");
 	}
 	return status;
 }
@@ -701,14 +616,14 @@ int cleanup_snapfs(void)
 
 	ENTRY;
 
+	cleanup_filter_info_cache();
 	err = unregister_filesystem(&snapfs_clone_type);
 	if ( err ) {
-		printk("snapfs: failed to unregister clone filesystem\n");
+		CERROR("snapfs: failed to unregister clone filesystem\n");
 	}
 	err = unregister_filesystem(&snapfs_current_type);
 	if ( err ) {
-		printk("snapfs: failed to unregister filesystem\n");
+		CERROR("snapfs: failed to unregister filesystem\n");
 	}
-
 	return 0;
 }
diff --git a/lustre/snapfs/symlink.c b/lustre/snapfs/symlink.c
index 41efbd1935f839cc67b1862c1d77dc9c8e45810b..cf4c99cbb174117a6040a98852b057b3694356f6 100644
--- a/lustre/snapfs/symlink.c
+++ b/lustre/snapfs/symlink.c
@@ -4,26 +4,19 @@
  *  A snap shot file system.
  *
  */
+#define DEBUG_SUBSYSTEM S_SNAP
 
-#define EXPORT_SYMTAB
-
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <linux/sched.h>
-#include <linux/stat.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
 #include <linux/string.h>
-#include <linux/locks.h>
-#include <linux/quotaops.h>
-#include <linux/list.h>
-#include <linux/file.h>
-#include <asm/bitops.h>
-#include <asm/byteorder.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
+
+#include "snapfs_internal.h" 
 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
 
 static inline int inode_has_ea(struct inode *inode)
 {               
@@ -92,19 +85,17 @@ static int cat_str_ahead(char *buf, int pos, const char* str)
  * (1) we are not lies in .snap
  * (2) we are already in the root's .snap
  */
-static struct dentry * dotsnap_follow_link(struct dentry *base,
-					   struct dentry *dentry,
-					   int follow)
+static int dotsnap_follow_link(struct dentry *dentry,
+					   struct nameidata *nd)
 {
 	struct super_block *sb = dentry->d_inode->i_sb;
-	struct dentry *rc = NULL;
 	struct dentry *de = dentry, *de_save1=NULL, *de_save2=NULL;
 	char *buf = NULL;
-	int pos = D_MAXLEN;
+	int pos = D_MAXLEN, rc;
 
-	SNAP_ALLOC(buf, char*, D_MAXLEN);
+	SNAP_ALLOC(buf, D_MAXLEN);
 	if( !buf )
-		return ERR_PTR(-ENOMEM);
+		RETURN(-ENOMEM);
 
 	/*
 	 * iterate upward to construct the path
@@ -139,49 +130,50 @@ lookup:
 
 	pos = cat_str_ahead(buf, pos, ".snap");
 	buf[D_MAXLEN-1] = 0;
-	CDEBUG(D_FILE, "constructed path: %s\n", &buf[pos]);
+	CDEBUG(D_SNAP, "constructed path: %s\n", &buf[pos]);
 
 	/* FIXME lookup_dentry will never return NULL ?? */
+#if 0
 	rc = lookup_dentry(&buf[pos], dget(sb->s_root), follow);
 	if( !rc ){
 		rc = ERR_PTR(-ENOENT);
-		CDEBUG(D_FILE, "lookup_dentry return NULL~!@#$^&*\n");
+		CDEBUG(D_SNAP, "lookup_dentry return NULL~!@#$^&*\n");
 	}
-	dput(base);
-
+#else
+	if (path_init(&buf[pos], LOOKUP_FOLLOW, nd)) {
+		rc = path_walk(&buf[pos], nd);
+		if (rc)
+			GOTO(exit, rc);
+	} 
+#endif
 exit:
 	SNAP_FREE(buf, D_MAXLEN);
 	return rc;
 }
 
-static struct dentry * currentfs_follow_link (	struct dentry *dentry, 
-						struct dentry *base,
-						unsigned int follow)
+static int currentfs_follow_link (struct dentry *dentry, struct nameidata *nd)
 {
 	struct snap_cache *cache;
-	struct dentry * rc;
 	struct inode_operations *iops;
 	struct inode * inode = dentry->d_inode;
 	int bpib = inode->i_sb->s_blocksize >> 9;
 	__u32 save_i_blocks;
-
+	int	rc;
 	ENTRY;
 
 	cache = snap_find_cache(inode->i_dev);
 	if ( !cache ) { 
-		EXIT;
-		return ERR_PTR(-EINVAL);
+		RETURN(-EINVAL);
 	}
 
 	iops = filter_c2csiops(cache->cache_filter); 
 	if (!iops ||
 	    !iops->follow_link) {
-		rc = ERR_PTR(-EINVAL);
-		goto exit;
+		GOTO(exit, rc = -EINVAL);
 	}
 
 	if( currentfs_is_under_dotsnap(dentry) ){
-		rc = dotsnap_follow_link( base, dentry, follow );
+		rc = dotsnap_follow_link(dentry, nd);
 		if( rc )
 			goto exit;
 	}
@@ -193,7 +185,7 @@ static struct dentry * currentfs_follow_link (	struct dentry *dentry,
 	if( inode_has_ea(inode) && inode->i_blocks == bpib ) {
 		inode->i_blocks = 0; 
 	}
-	rc = iops->follow_link(dentry, base, follow);
+	rc = iops->follow_link(dentry, nd);
 	
 	if( inode->i_blocks != save_i_blocks ){
 		inode->i_blocks = save_i_blocks;
@@ -201,13 +193,14 @@ static struct dentry * currentfs_follow_link (	struct dentry *dentry,
 	}
 	
 exit:
-	EXIT;
-	return rc;
+	RETURN(rc);
 }
 
 struct inode_operations currentfs_sym_iops = {
 	readlink:	currentfs_readlink,
-	follow_link:	currentfs_follow_link
+	follow_link:	currentfs_follow_link,
 };
 
-struct file_operations currentfs_sym_fops;
+struct file_operations currentfs_sym_fops = {
+	ioctl:		NULL,
+};
diff --git a/lustre/snapfs/sysctl.c b/lustre/snapfs/sysctl.c
index f7f88a6700a9efec406f8fe1e5d245c3562082a7..1969081dd17dd34d961d4eb7fb12665b7867b06f 100644
--- a/lustre/snapfs/sysctl.c
+++ b/lustre/snapfs/sysctl.c
@@ -2,53 +2,27 @@
  *  Sysctrl entries for Snapfs
  */
 
-#define __NO_VERSION__
-#include <linux/config.h> /* for CONFIG_PROC_FS */
+/* /proc entries */
+
+#define DEBUG_SUBSYSTEM S_SNAP
+
 #include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/sysctl.h>
-#include <linux/swapctl.h>
 #include <linux/proc_fs.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <linux/init.h>
-#include <asm/bitops.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/utsname.h>
-#include <linux/blk.h>
- 
-#include <linux/filter.h>
-#include <linux/snapfs.h>
-#include <linux/snapsupport.h>
+#include <linux/jbd.h>
+#include <linux/ext3_fs.h>
+#include <linux/snap.h>
 
+#include "snapfs_internal.h" 
 
-/* /proc entries */
 
 #ifdef CONFIG_PROC_FS
-
-
-static void snapfs_proc_modcount(struct inode *inode, int fill)
-{
-	if (fill)
-		MOD_INC_USE_COUNT;
-	else
-		MOD_DEC_USE_COUNT;
-}
-
-struct proc_dir_entry proc_fs_snapfs = {
-	0, 10, "snapfs",
-	S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-	0, &proc_dir_inode_operations,
-	NULL, NULL,
-	NULL,
-	NULL, NULL
-};
-
-
+static struct proc_dir_entry *proc_snapfs_root;
 #endif
 
 
@@ -67,9 +41,11 @@ static struct ctl_table_header *snapfs_table_header = NULL;
 #define ENTRY_CNT 3
 
 /* XXX - doesn't seem to be working in 2.2.15 */
-static struct ctl_table snapfs_ctltable[ENTRY_CNT] =
+static struct ctl_table snapfs_ctltable[] =
 {
+#ifdef SNAP_DEBUG
 	{PSDEV_DEBUG, "debug", &snap_debug_level, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
 	{PSDEV_TRACE, "trace", &snap_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
 	{0}
 };
@@ -80,31 +56,35 @@ static ctl_table snapfs_table[2] = {
 };
 
 
-int /* __init */ init_snapfs_proc_sys(void)
+int  __init  init_snapfs_proc_sys(void)
 {
+#ifdef CONFIG_PROC_FS
+	proc_snapfs_root = proc_mkdir("snapfs", proc_root_fs);
+	if (!proc_snapfs_root) {
+		printk(KERN_ERR "SNAPFS: error registering /proc/fs/snapfs\n");
+		RETURN(-ENOMEM);
+	}
+	proc_snapfs_root->owner = THIS_MODULE;
+#endif
 
 #ifdef CONFIG_SYSCTL
 	if ( !snapfs_table_header )
 		snapfs_table_header =
 			register_sysctl_table(snapfs_table, 0);
-#endif
-#ifdef CONFIG_PROC_FS
-	proc_register(&proc_root_fs, &proc_fs_snapfs);
-	proc_fs_snapfs.fill_inode = &snapfs_proc_modcount;
 #endif
 	return 0;
 }
 
-void cleanup_snapfs_proc_sys(void) {
-
+void cleanup_snapfs_proc_sys(void) 
+{
 #ifdef CONFIG_SYSCTL
 	if ( snapfs_table_header )
 		unregister_sysctl_table(snapfs_table_header);
 	snapfs_table_header = NULL;
 #endif
-
 #if CONFIG_PROC_FS
-	proc_unregister(&proc_root_fs, proc_fs_snapfs.low_ino);
+	remove_proc_entry("snapfs", proc_root_fs);
 #endif
+
 }