diff --git a/lustre/snapfs/cache.c b/lustre/snapfs/cache.c
index 68efe982772fa9667103a46f6035ed5164c02313..62cb15ba92d0a8000d1d9daedbf85f32f4c288f3 100644
--- a/lustre/snapfs/cache.c
+++ b/lustre/snapfs/cache.c
@@ -58,7 +58,7 @@ struct snap_cache *snap_find_cache(kdev_t dev)
 
 	lh = &(snap_caches[snap_cache_hash(dev)]);
         list_for_each_entry(cache, lh, cache_chain) { 
-		if ( cache->cache_dev == dev )
+		if (cache->cache_dev == dev)
 			return cache;
 	}
 	return NULL;
diff --git a/lustre/snapfs/clonefs.c b/lustre/snapfs/clonefs.c
index b4f136ca9f97f5f59f1a31734e82ec1cf689779f..2292c495d8277342602ec8656e7e2f2f967ac29c 100644
--- a/lustre/snapfs/clonefs.c
+++ b/lustre/snapfs/clonefs.c
@@ -422,19 +422,17 @@ struct address_space_operations clonefs_file_address_ops = {
 
 static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 {
-	int res;
 	struct inode * cache_inode;
 	struct inode * old_inode;
+	int rc = -ENOENT;
 
 	ENTRY;
 
 	cache_inode = clonefs_get_inode(dentry->d_inode); 
 
-	res = -ENOENT;
-
-	if ( ! cache_inode ) {
+	if (!cache_inode) {
 		CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-		RETURN(res);	
+		RETURN(rc);	
 	}
 	
 	/* XXX: shall we allocate a new dentry ? 
@@ -446,8 +444,8 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 	/* set dentry inode to cache inode */
 	dentry->d_inode = cache_inode;
 
-	if ( cache_inode->i_op->readlink ) {
-		res = cache_inode->i_op->readlink(dentry, buf, len); 
+	if (cache_inode->i_op->readlink) {
+		rc = cache_inode->i_op->readlink(dentry, buf, len); 
 	}else {
 		CDEBUG(D_INODE,"NO readlink for ino %lu\n", cache_inode->i_ino);
 	}
@@ -457,21 +455,21 @@ static int clonefs_readlink(struct dentry *dentry, char *buf, int len)
 
 	iput(cache_inode);
 
-	RETURN(res);
+	RETURN(rc);
 }
 
 static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 {
 	struct inode * cache_inode;
 	struct inode * old_inode;
-	int    res;
+	int    rc = -ENOENT;
 
 	ENTRY;
 
 	cache_inode = clonefs_get_inode(dentry->d_inode); 
-	if ( ! cache_inode ) {
+	if (!cache_inode) {
 		CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
-		RETURN(-ENOENT);	
+		RETURN(rc);	
 	}
 
 	/* XXX: shall we allocate a new dentry ? 
@@ -483,8 +481,8 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 	/* set dentry inode to cache inode */
 	dentry->d_inode = cache_inode;
 
-	if ( cache_inode->i_op->follow_link ) {
-		res = cache_inode->i_op->follow_link(dentry, nd); 
+	if (cache_inode->i_op->follow_link) {
+		rc = cache_inode->i_op->follow_link(dentry, nd); 
 	}
 
 	/* restore the old inode */
@@ -492,16 +490,103 @@ static int clonefs_follow_link(struct dentry * dentry, struct nameidata *nd)
 
 	iput(cache_inode);
 
-	RETURN(res);
+	RETURN(rc);
 }
+static ssize_t
+clonefs_getxattr(struct dentry *dentry, const char *name,
+                 void *buffer, size_t size)
+{
+	struct inode * cache_inode;
+	struct inode * old_inode;
+	int    rc = -ENOENT;
+
+	ENTRY;
+
+	cache_inode = clonefs_get_inode(dentry->d_inode); 
+	if (!cache_inode) {
+		CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+		RETURN(rc);	
+	}
+
+	/* XXX: shall we allocate a new dentry ? 
+		The following is safe for ext2, etc. because ext2_follow_link 
+		only use the inode info */
 
+	/* save the old dentry inode */	
+	old_inode = dentry->d_inode;
+	/* set dentry inode to cache inode */
+	dentry->d_inode = cache_inode;
+
+	if (cache_inode->i_op->getxattr) {
+		rc = cache_inode->i_op->getxattr(dentry, name, buffer, size); 
+	}
+
+	/* restore the old inode */
+	dentry->d_inode = old_inode;
+
+	iput(cache_inode);
+
+	RETURN(rc);
+}
+static ssize_t
+clonefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	struct inode * cache_inode;
+	struct inode * old_inode;
+	int    rc = -ENOENT;
+
+	ENTRY;
+
+	cache_inode = clonefs_get_inode(dentry->d_inode); 
+	if (!cache_inode) {
+		CDEBUG(D_INODE, "clonefs_get_inode failed, NULL\n");
+		RETURN(rc);	
+	}
+
+	/* XXX: shall we allocate a new dentry ? 
+		The following is safe for ext2, etc. because ext2_follow_link 
+		only use the inode info */
+
+	/* save the old dentry inode */	
+	old_inode = dentry->d_inode;
+	/* set dentry inode to cache inode */
+	dentry->d_inode = cache_inode;
+
+	if (cache_inode->i_op->listxattr) {
+		rc = cache_inode->i_op->listxattr(dentry, buffer, size); 
+	}
+
+	/* restore the old inode */
+	dentry->d_inode = old_inode;
+
+	iput(cache_inode);
+
+	RETURN(rc);
+
+}
 struct inode_operations clonefs_symlink_inode_ops =
 {
 	/*FIXME later getxattr, listxattr, 
 	 * other method need to be replaced too 
 	 * */  
-	readlink:	clonefs_readlink,   /* readlink */              
-	follow_link:	clonefs_follow_link,/* follow_link */             
+	readlink:	clonefs_readlink,   	/* readlink */              
+	follow_link:	clonefs_follow_link,	/* follow_link */             
+   	getxattr:       clonefs_getxattr,       /* get xattr */
+        listxattr:      clonefs_listxattr,      /* list xattr */
 };
 
 
+int clonefs_mounted(struct snap_cache *cache, int index)
+{
+	struct snap_clone_info *clone_sb;
+	struct list_head *list, *end;
+
+	end = list = &cache->cache_clone_list;
+	
+	list_for_each_entry(clone_sb, list, clone_list_entry) {
+		if (clone_sb->clone_index == index)
+			return 1;	
+	} 	
+	return 0;	
+}
+
diff --git a/lustre/snapfs/dir.c b/lustre/snapfs/dir.c
index 4db0908bbfad85ff86dddf264fad91970825bb97..d139d209f718c6dc6c0309ce7d3a8e0251634283 100644
--- a/lustre/snapfs/dir.c
+++ b/lustre/snapfs/dir.c
@@ -37,10 +37,13 @@ static ino_t get_parent_ino(struct inode * inode)
 
 static void d_unadd_iput(struct dentry *dentry)
 {
+	spin_lock(&dcache_lock);
 	list_del(&dentry->d_alias);
 	INIT_LIST_HEAD(&dentry->d_alias);
 	list_del(&dentry->d_hash);
 	INIT_LIST_HEAD(&dentry->d_hash);
+	spin_unlock(&dcache_lock);
+	
 	iput(dentry->d_inode);
 	dentry->d_inode = NULL;
 }
@@ -76,7 +79,8 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 
 		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);
+		CDEBUG(D_INODE, ".snap inode ino %ld, mode %o\n", 
+		       snap->i_ino, snap->i_mode);
 		d_add(dentry, snap);
 		RETURN(NULL);
 	}
@@ -87,10 +91,14 @@ static struct dentry *currentfs_lookup(struct inode * dir,struct dentry *dentry)
 	}
 
 	rc = iops->lookup(dir, dentry);
-	if ( rc || !dentry->d_inode) {
+	if (rc || !dentry->d_inode || 
+            is_bad_inode(dentry->d_inode) ||
+	    IS_ERR(dentry->d_inode)) {
 		RETURN(NULL);
 	}
-	
+
+	CDEBUG(D_INODE, "cache inode ino %lu, mode %o\n", 
+	       dentry->d_inode->i_ino, dentry->d_inode->i_mode);
 	/*
 	 * If we are under dotsnap, we need save extra data into
 	 * dentry->d_fsdata:  For dir, we only need _this_ snapshot's index; 
@@ -160,13 +168,13 @@ static int currentfs_create(struct inode *dir, struct dentry *dentry, int mode)
 	}
 
 	cache = snap_find_cache(dir->i_dev);
-	if ( !cache ) { 
+	if (!cache) { 
 		RETURN(-EINVAL);
 	}
 
 	handle = snap_trans_start(cache, dir, SNAP_OP_CREATE);
 
-	if ( snap_needs_cow(dir) != -1 ) {
+	if (snap_needs_cow(dir) != -1) {
 		CDEBUG(D_INODE, "snap_needs_cow for ino %lu \n",dir->i_ino);
 		snap_debug_device_fail(dir->i_dev, SNAP_OP_CREATE, 1);
 		if ((snap_do_cow(dir, get_parent_ino(dir), 0))) {
@@ -242,7 +250,12 @@ static int currentfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
                 CERROR("Error in currentfs_mkdir, dentry->d_inode is NULL\n");
         }
 
-	snap_debug_device_fail(dir->i_dev, SNAP_OP_MKDIR, 3);
+	set_filter_ops(cache, dentry->d_inode);
+	init_filter_data(dentry->d_inode, 0); 
+	
+	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:
 	snap_trans_commit(cache, handle);
@@ -320,8 +333,11 @@ static int currentfs_symlink(struct inode *dir, struct dentry *dentry,
 
 	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);
 	
+	set_filter_ops(cache, dentry->d_inode);
+	init_filter_data(dentry->d_inode, 0); 
+	
+	snap_debug_device_fail(dir->i_dev, SNAP_OP_SYMLINK, 3);
 exit:
 	snap_trans_commit(cache, handle);
 	RETURN(rc);
@@ -360,6 +376,9 @@ static int currentfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 2);
 	rc = iops->mknod(dir, dentry, mode, rdev);
+	
+	set_filter_ops(cache, dentry->d_inode);
+	init_filter_data(dentry->d_inode, 0); 
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_MKNOD, 3);
 	
 	/* XXX do we need to set the correct snap_{*}_iops */
@@ -380,7 +399,6 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
 	off_t	i_size = 0;
 	ino_t ino = 0;
 	int keep_inode = 0;
-//	struct dentry_operations *save_dop = NULL;
 	void *handle = NULL;
 
 	ENTRY;
@@ -416,23 +434,10 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
 	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 (dir, get_parent_ino(dir), SNAP_CREATE_IND_DEL_PRI);
+		snap_do_cow (dentry->d_inode, get_parent_ino(dentry->d_inode), 
+			     SNAP_CREATE_IND_DEL_PRI);
 		keep_inode = 1;
 	}
-#if 0
-	if ( keep_inode ) {	
-       		printk("set up dentry ops, before %p\n",dentry->d_op);
-		save_dop = dentry->d_op;
-
-     		filter_setup_dentry_ops(cache->cache_filter,
-                                dentry->d_op, &currentfs_dentry_ops);
-        	dentry->d_op = filter_c2udops(cache->cache_filter);
-
-       		printk("set up dentry ops, after %p\n",dentry->d_op);
-
-	}
-
-#endif
 
 	if( keep_inode && dentry->d_inode ) {
 		ino = dentry->d_inode->i_ino;
@@ -445,31 +450,20 @@ static int currentfs_rmdir(struct inode *dir, struct dentry *dentry)
 	rc = iops->rmdir(dir, dentry);
 	snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 5);
 
-	/* XXX : check this */
-#if 0
-	if ( keep_inode ) {
-		dentry->d_op = save_dop;
-		printk("restore dentry ops, now at %p\n",dentry->d_op);
-	}
-
-#endif
-
 	if( keep_inode && ino) {
-		inode = iget ( dir->i_sb, ino);
+		inode = iget (dir->i_sb, ino);
 		if( inode) {
 //			inode->i_ctime = i_ctime;
 			inode->i_nlink = i_nlink;
 			inode->i_size = i_size;
 			mark_inode_dirty(inode);
 			iput( inode);
-#ifdef CONFIG_SNAPFS_EXT3
 			/*
 			 * In Ext3, rmdir() will put this inode into
 			 * orphan list, we must remove it out. It's ugly!!
 			 */
 			if( cache->cache_type == FILTER_FS_EXT3 )
 				ext3_orphan_del(handle, inode);
-#endif
 			snap_debug_device_fail(dir->i_dev, SNAP_OP_RMDIR, 6);
 		}
 	}
@@ -698,5 +692,8 @@ struct inode_operations currentfs_dir_iops = {
 	rmdir: 		currentfs_rmdir,
 	unlink: 	currentfs_unlink,
 	rename: 	currentfs_rename,
-	lookup:		currentfs_lookup
+	lookup:		currentfs_lookup,
+	removexattr:	currentfs_removexattr,
+	setattr:	currentfs_setattr,
+	setxattr:	currentfs_setxattr,
 };
diff --git a/lustre/snapfs/file.c b/lustre/snapfs/file.c
index 25eea668a9b7d8ede68c647db801c7d60dde6a4d..a8a88607565411a50a319abe2432f3f514bc5031 100644
--- a/lustre/snapfs/file.c
+++ b/lustre/snapfs/file.c
@@ -43,7 +43,7 @@ static int copy_back_page(struct inode *dst,
 	char *kaddr_src, *kaddr_dst;
         struct snap_cache *cache;
 	struct address_space_operations *c_aops;
-	struct page *src_page, *dst_page;
+	struct page *src_page = NULL, *dst_page = NULL;
 	unsigned long index, offset, bytes;
 	int    err = 0;
 	ENTRY;
@@ -96,6 +96,8 @@ static int copy_back_page(struct inode *dst,
 	flush_dcache_page(dst_page);
 
 	err = c_aops->commit_write(NULL, dst_page, offset, offset + bytes);
+	CDEBUG(D_SNAP, "copy back pages %p index %lu src %lu dst %lu \n",
+	       dst_page, dst_page->index, src->i_ino, dst->i_ino); 
 	if (err) 
 		goto unlock_dst_page; 
 	err = 1;
@@ -132,28 +134,36 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
         if ( !cache ) 
                 RETURN(-EINVAL);
 
+	down(&inode->i_sem);
+
         if ( snap_needs_cow(inode) != -1 ) {
                 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) 
-                RETURN(-EINVAL);
-
+        if (!fops || !fops->write) { 
+                up(&inode->i_sem); 
+		RETURN(-EINVAL);
+	}
         if (filp->f_flags & O_APPEND)
                 pos = inode->i_size;
         else {
                 pos = *ppos;
-                if (pos != *ppos)
+                if (pos != *ppos){
+                	up(&inode->i_sem); 
                         RETURN(-EINVAL);
+		}
         }
-	if (pos & PAGE_CACHE_MASK) {
+	
+	CDEBUG(D_SNAP, "write offset %lld count %u \n", pos, count);
+	
+	if (pos & (PAGE_CACHE_SIZE - 1)) {
 		start[0] = pos & PAGE_CACHE_MASK;
 		end[0] = pos;
 	}
 	pos += count - 1;
-	if ((pos+1) & PAGE_CACHE_MASK) {
+	if ((pos+1) & (PAGE_CACHE_SIZE - 1)) {
 		start[1] = pos;  
 		end[1] = PAGE_CACHE_ALIGN(pos);
 	}
@@ -161,7 +171,9 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
 	if (((start[0] >> PAGE_CACHE_SHIFT) == (start[1] >> PAGE_CACHE_SHIFT)) ||
 	    pos > inode->i_size) 
 		start[1] = -1;
-	
+
+	CDEBUG(D_SNAP, "copy back start[0] %ld end[0] %ld start[1] %ld end[1] %ld \n",
+	       start[0], end[0], start[1], end[1]);	
 	for (i = 0; i < 2; i++) {
 		if (start[i] == -1) 
 			continue;
@@ -189,11 +201,14 @@ static ssize_t currentfs_write (struct file *filp, const char *buf,
 			if (result < 0) {
 				iput(cache_inode);
 				rc = result;
+				up(&inode->i_sem);
 				goto exit;
 			}
                		iput(cache_inode);
         	}
 	}
+	
+        up(&inode->i_sem); 
 	rc = fops->write(filp, buf, count, ppos);
 exit:
         RETURN(rc);
@@ -246,7 +261,6 @@ static int currentfs_readpage(struct file *file, struct page *page)
 	table = &snap_tables[cache->cache_snap_tableno];
 
         for (slot = table->tbl_count - 1; slot >= 1; slot--) {
-		cache_inode = NULL;
                 index = table->snap_items[slot].index;
 		cache_inode = snap_get_indirect(inode, NULL, index);
 
@@ -259,12 +273,19 @@ static int currentfs_readpage(struct file *file, struct page *page)
                 if (!search_older && c_aops->bmap(cache_inode->i_mapping, block)) 
                         break;
                 iput(cache_inode);
+		cache_inode = NULL;
         }
 	if (pri_inode) iput(pri_inode);
 
-	if (!cache_inode )  
-		RETURN(-EINVAL);
-
+	if (!cache_inode) {
+		CDEBUG(D_SNAP, "block %lu is a hole of inode %lu \n", 
+		       block, inode->i_ino);
+		memset(kmap(page), 0, PAGE_CACHE_SIZE);
+		flush_dcache_page(page);
+		GOTO(exit, rc = 0);
+	}
+	CDEBUG(D_INODE, "readpage ino %lu icount %d \n", cache_inode->i_ino, 
+	       atomic_read(&cache_inode->i_count));
 	down(&cache_inode->i_sem);
 
 	/*Here we have changed a file to read,
@@ -284,13 +305,14 @@ static int currentfs_readpage(struct file *file, struct page *page)
 		GOTO(exit_release, rc = -EIO);
 
 	memcpy(kmap(page), kmap(cache_page), PAGE_CACHE_SIZE);
+	flush_dcache_page(page);
 
 	kunmap(cache_page);
 	page_cache_release(cache_page);
 
 	up(&cache_inode->i_sem);
 	iput(cache_inode);
-	
+exit:	
 	kunmap(page);
 	SetPageUptodate(page);
 	UnlockPage(page);
@@ -315,6 +337,8 @@ struct file_operations currentfs_file_fops = {
 };
                                                                                                                                                                                                      
 struct inode_operations currentfs_file_iops = {
-	revalidate:     NULL,
+	setattr:	currentfs_setattr,
+	setxattr:	currentfs_setxattr,
+	removexattr:	currentfs_removexattr,	
 };
 
diff --git a/lustre/snapfs/filter.c b/lustre/snapfs/filter.c
index c17a4997cb64737448d3dbed8c9deed2b5e63689..f7d6f6f1c0488f0e007319126d82c9071a24b5e4 100644
--- a/lustre/snapfs/filter.c
+++ b/lustre/snapfs/filter.c
@@ -239,6 +239,13 @@ void filter_setup_dir_ops(struct filter_fs *cache,
 			u_iops->mknod = filter_iops->mknod;
 		if (cache_iops->permission && filter_iops->permission)
 			u_iops->permission = filter_iops->permission;
+		if (cache_iops->setattr && filter_iops->setattr)
+			u_iops->setattr = filter_iops->setattr;
+		if (cache_iops->setxattr && filter_iops->setxattr)
+			u_iops->setxattr = filter_iops->setxattr;
+		if (cache_iops->removexattr && filter_iops->removexattr)
+			u_iops->removexattr = filter_iops->removexattr;
+
 	}
 	/* copy dir fops */
 	
@@ -290,6 +297,12 @@ void filter_setup_file_ops(struct filter_fs 	   *cache,
 	if (filter_iops) {
 		if (filter_iops->revalidate)
 			u_iops->revalidate = filter_iops->revalidate;
+		if (filter_iops->removexattr)
+			u_iops->removexattr = filter_iops->removexattr;
+		if (filter_iops->setxattr)
+			u_iops->setxattr = filter_iops->setxattr;
+		if (filter_iops->setattr)
+			u_iops->setattr = filter_iops->setattr;
 	}
 	if (filter_fops) {
 		if (filter_fops->read)
@@ -337,6 +350,11 @@ void filter_setup_symlink_ops(struct filter_fs *cache,
 			u_iops->readlink = filter_iops->readlink;
 		if (cache_iops->follow_link && filter_iops->follow_link)
 			u_iops->follow_link = filter_iops->follow_link;
+		if (cache_iops->getxattr && filter_iops->getxattr) 
+			u_iops->getxattr = filter_iops->getxattr;
+		if (cache_iops->listxattr && filter_iops->listxattr)
+			u_iops->listxattr = filter_iops->listxattr;
+
 	}
 	EXIT;
 }
diff --git a/lustre/snapfs/inode.c b/lustre/snapfs/inode.c
index 25619a87f5f224f1d4c47af9b6c1b80e9d33e287..97bfd464200be9c1b0dc110451c28fb1d5a79174 100644
--- a/lustre/snapfs/inode.c
+++ b/lustre/snapfs/inode.c
@@ -64,6 +64,8 @@ void init_filter_data(struct inode *inode,
 		return;
 	}
 	snapops = filter_c2csnapops(cache->cache_filter);
+
+	if (inode->i_filterdata) return;
 	
 	inode->i_filterdata = (struct filter_inode_info *) \
 			      kmem_cache_alloc(filter_info_cache, SLAB_KERNEL);
@@ -104,7 +106,95 @@ void set_filter_ops(struct snap_cache *cache, struct inode *inode)
 		       inode->i_ino, inode->i_op);
 	}
 }
+int currentfs_setxattr(struct dentry *dentry, const char *name, 
+		       const void *value, size_t size, int flags)
+{
+        struct snap_cache 	*cache;
+	struct inode	  	*inode = dentry->d_inode;
+	struct inode_operations *iops;
+	int    rc;
+
+	ENTRY;
+ 
+	cache = snap_find_cache(inode->i_dev);
+	if (!cache) {
+		CERROR("currentfs_setxattr: cannot find cache\n");
+		RETURN(-EINVAL);
+	}
+
+	iops = filter_c2cfiops(cache->cache_filter);
+ 
+	if (!iops || !iops->setxattr) {
+		RETURN(-EINVAL);		
+	}
+        if ( snap_needs_cow(inode) != -1 ) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+	}
+
+	rc = iops->setxattr(dentry, name, value, size, flags);
+
+	RETURN(rc);
+}
+int currentfs_removexattr(struct dentry *dentry, const char *name)
+{
+        struct snap_cache 	*cache;
+	struct inode	  	*inode = dentry->d_inode;
+	struct inode_operations *iops;
+	int    rc;
+
+	ENTRY;
+ 
+	cache = snap_find_cache(inode->i_dev);
+	if (!cache) {
+		CERROR("currentfs_setxattr: cannot find cache\n");
+		RETURN(-EINVAL);
+	}
+
+	iops = filter_c2cfiops(cache->cache_filter);
+ 
+	if (!iops || !iops->removexattr) {
+		RETURN(-EINVAL);		
+	}
+        
+	if (snap_needs_cow(inode) != -1) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+	}
+	rc = iops->removexattr(dentry, name);
+
+	RETURN(rc);
+}
+
+int currentfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+        struct snap_cache 	*cache;
+	struct inode	  	*inode = dentry->d_inode;
+	struct inode_operations *iops;
+	int    rc;
+
+	ENTRY;
+ 
+	cache = snap_find_cache(inode->i_dev);
+	if (!cache) {
+		CERROR("currentfs_setxattr: cannot find cache\n");
+		RETURN(-EINVAL);
+	}
 
+	iops = filter_c2cfiops(cache->cache_filter);
+ 
+	if (!iops || !iops->setattr) {
+		RETURN(-EINVAL);		
+	}
+        if ( snap_needs_cow(inode) != -1 ) {
+                CDEBUG(D_SNAP, "snap_needs_cow for ino %lu \n",inode->i_ino);
+                snap_do_cow(inode, dentry->d_parent->d_inode->i_ino, 0);
+	}
+
+	rc = iops->setattr(dentry, attr);
+
+	RETURN(rc);
+}
 /* Superblock operations. */
 static void currentfs_read_inode(struct inode *inode)
 {
@@ -113,7 +203,6 @@ static void currentfs_read_inode(struct inode *inode)
 
 	if( !inode ) 
 		return;
-
 	CDEBUG(D_INODE, "read_inode ino %lu\n", inode->i_ino);
 
 	cache = snap_find_cache(inode->i_dev);
@@ -131,10 +220,14 @@ static void currentfs_read_inode(struct inode *inode)
 	if(filter_c2csops(cache->cache_filter))
 		filter_c2csops(cache->cache_filter)->read_inode(inode);
 
+	CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", 
+	       inode->i_ino, atomic_read(&inode->i_count));
 	set_filter_ops(cache, inode);
 	/*init filter_data struct 
 	 * FIXME flag should be set future*/
 	init_filter_data(inode, 0); 
+	CDEBUG(D_INODE, "read_inode ino %lu icount %d \n", 
+	       inode->i_ino, atomic_read(&inode->i_count));
 	return; 
 }
 
@@ -217,3 +310,8 @@ struct super_operations currentfs_super_ops = {
 	put_super:	currentfs_put_super,
 	clear_inode:	currentfs_clear_inode,
 };
+
+
+
+
+
diff --git a/lustre/snapfs/snapfs_internal.h b/lustre/snapfs/snapfs_internal.h
index 6ce3e3eb3fcbe7a0ddf83ea2ab76cf5aa56cb7f3..da9d9927acca20db092152a37f26c1e3c3732dde 100644
--- a/lustre/snapfs/snapfs_internal.h
+++ b/lustre/snapfs/snapfs_internal.h
@@ -209,7 +209,7 @@ struct snap_obd_data {
 	unsigned int snap_index;/* which snapshot is ours */
 	unsigned int snap_table;/* which table do we use */
 };
-#define DISK_SNAPTABLE_ATTR     "Snaptable"
+#define DISK_SNAPTABLE_ATTR     "Snaptable12"
 #define DISK_SNAP_TABLE_MAGIC	0x1976
 struct snap_disk_table {
 	unsigned int    	magic;
@@ -287,6 +287,10 @@ void cleanup_filter_info_cache(void);
 int init_filter_info_cache(void);
 extern void init_filter_data(struct inode *inode, int flag);
 extern void set_filter_ops(struct snap_cache *cache, struct inode *inode);
+extern int currentfs_setxattr(struct dentry *dentry, const char *name, 
+		       const void *value, size_t size, int flags);
+extern int currentfs_removexattr(struct dentry *dentry, const char *name);
+extern int currentfs_setattr(struct dentry *dentry, struct iattr *attr);
 /* dir.c */
 extern struct inode_operations currentfs_dir_iops;
 extern struct file_operations currentfs_dir_fops;
@@ -306,6 +310,8 @@ extern struct dentry_operations currentfs_dentry_ops;
 extern int init_option(char *data);
 extern void cleanup_option(void);
 extern int get_opt(struct option **opt, char **pos);
+/* clonefs.c */
+int clonefs_mounted(struct snap_cache *cache, int index);
 
 #define FILTER_DID_SUPER_OPS 	0x1
 #define FILTER_DID_INODE_OPS 	0x2
diff --git a/lustre/snapfs/snaptable.c b/lustre/snapfs/snaptable.c
index 0af46c3b6bd78d5f0db4274213613ffdcadeedf2..5759058f7db72af33e557ba62f3193ea5f68131f 100644
--- a/lustre/snapfs/snaptable.c
+++ b/lustre/snapfs/snaptable.c
@@ -22,22 +22,6 @@
 
 struct snap_table snap_tables[SNAP_MAX_TABLES];
 
-#if 0
-static void snap_lock_table(int table_no)
-{
-
-	spin_lock(snap_tables[table_no].tbl_lock);
-
-}
-
-static void snap_unlock_table(int table_no)
-{
-
-	spin_unlock(snap_tables[table_no].tbl_lock);
-
-}
-#endif
-
 int snap_index2slot(struct snap_table *snap_table, int snap_index)
 {
 	int slot;
@@ -210,8 +194,10 @@ static int snaptable_add_item(struct ioc_snap_tbl_data *data)
 	table->snap_items[count].time = CURRENT_TIME;
 	/* find table index */
 	index = get_index_of_item(table, data->snaps[0].name);
-	if (index < 0)
+	if (index < 0) {
+		CERROR("snaptable full Or Duplicate name in snaptable\n");
 		GOTO(exit, rc = -EINVAL);
+	}
 	
 	table->snap_items[count].index = index;
 	table->snap_items[count].flags = 0;
@@ -285,6 +271,9 @@ static int delete_inode(struct inode *primary, void *param)
 	}
 	old_ind = redirect->i_ino;
 	iput(redirect);
+
+	/* In destroy indirect inode, we lock the primary inode here */
+	down(&primary->i_sem);	
 	slot = snap_index2slot(table, index) - 1;
 	if (slot > 0) {
 		this_index = table->snap_items[slot].index;
@@ -294,33 +283,29 @@ static int delete_inode(struct inode *primary, void *param)
 		} else {
 			snap_set_indirect(primary, old_ind, this_index, 0);
 			snap_set_indirect(primary, 0, index, 0);
+			up(&primary->i_sem);		
 			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 --) {
+	for (slot = table->tbl_count - 1; 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;
-	}
+	
+	this_index = table->tbl_count - delete_slot - 1;
+	next_ind = snap_get_indirect(primary, my_table, this_index);
 
-	if (next_ind && (next_ind->i_ino == old_ind)) {
+	if (next_ind && (next_ind->i_ino == primary->i_ino)) {
 		iput(next_ind);
 		next_ind = NULL;
 	}
-
 	rc = snap_destroy_indirect(primary, index, next_ind);
 
+	up(&primary->i_sem);
+	
 	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);
@@ -339,6 +324,7 @@ static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
 
 /* This function will delete one item(a snapshot) in the snaptable  
  * and will also delete the item in the disk.
+ * FIXME later, this should be in a transaction.
  */
 int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
 {
@@ -346,19 +332,26 @@ int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
 	struct snap_disk_table 		*disk_snap_table;
 	struct snapshot_operations 	*snapops;
 	struct snap_cache 		*cache;
-	int 				tableno = data->tableno, index, i, slot, rc, count;
+	int 				tableno = data->tableno; 
+	int				index, i, del_slot, 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);
-
 	if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
 		CERROR("invalid table number %d\n", tableno);
 		RETURN(-EINVAL);
 	}
+
+	snapops = filter_c2csnapops(cache->cache_filter);
+	if (!snapops || !snapops->set_meta_attr)
+		RETURN(-EINVAL);
+	
+	index = data->index;
+	if (clonefs_mounted(cache, index)) {
+		CERROR("Please first umount this clonefs \n");
+		RETURN(-EBUSY);		
+	}	
 	/*first delete the snapshot
 	 * FIXME if snap delete error, how to handle this error*/
 	rc = snap_delete(sb, data);
@@ -366,55 +359,63 @@ int snaptable_delete_item(struct super_block *sb, struct snap_iterdata *data)
 		RETURN(-EINVAL);
 	/*delete item in snaptable */
 	table = &snap_tables[tableno];
-	index = data->index;
 
-	slot = snap_index2slot(table, index);
-	if (slot < 0)
+	del_slot = snap_index2slot(table, index);
+	if (del_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->tbl_count --;
 	
 	SNAP_ALLOC(disk_snap_table, sizeof(struct snap_disk_table));
 
-	if (!disk_snap_table)
+	if (!disk_snap_table) {
+		up(&table->tbl_sema);
 		RETURN(-ENOMEM);
+	}
+
 	/* we will delete the item  snap_table to disk */
-	
+
+	index = del_slot;
+	/*Move the items after the delete slot forward one step*/
+	memset(&table->snap_items[index], 0, sizeof(struct snap));
+	while(index < table->tbl_count - 1) {
+		struct snap *item = &table->snap_items[index];
+			
+		item->time = table->snap_items[index + 1].time;
+		item->flags = table->snap_items[index + 1].flags;
+		item->gen = table->snap_items[index + 1].gen;
+		item->index = table->snap_items[index + 1].index;
+		memcpy(&item->name[0], &table->snap_items[index + 1].name[0],
+		       SNAP_MAX_NAMELEN);
+		index ++;
+	}
+
+	table->tbl_count --;
+		
 	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);
+	disk_snap_table->count = cpu_to_le32((__u32)table->tbl_count - 1);
+	disk_snap_table->generation = cpu_to_le32((__u32)table->generation + 1);
 	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);
+	for (i = 0; i < table->tbl_count - 1; i++) {
+		struct snap_disk *disk_item = &disk_snap_table->snap_items[i];
+		struct snap *item = &table->snap_items[i+1];
+		
+		disk_item[i].time = cpu_to_le64((__u64)item->time);
+		disk_item[i].gen = cpu_to_le32((__u32)item->gen);
+		disk_item[i].flags = cpu_to_le32((__u32)item->flags);
+		disk_item[i].index = cpu_to_le32((__u32)item->index);
+		memcpy(&disk_item[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);
+	RETURN(rc);
 }
 
 int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
@@ -592,13 +593,12 @@ static int delete_new_inode(struct inode *pri, void *param)
 
 	ENTRY; 
 
-	if(!pri) return 0;
-
-	if(snap_is_redirector(pri)){
-		EXIT;
-		return 0;
-	}
+	if(!pri) 
+		RETURN(0);
 
+	if(snap_is_redirector(pri))
+		RETURN(0);
+	
 	data = (struct snap_iterdata*) param;
 
 	if(data) {
@@ -619,14 +619,12 @@ static int delete_new_inode(struct inode *pri, void *param)
 		}
 		pri->i_nlink = 0;
 	}
-	return 0;
-
+	RETURN(0);
 }
 
 static int restore_inode(struct inode *pri, void *param)
 {
 	struct snap_iterdata * data;
-//	struct snap_cache *cache;
 	int tableno = 0;
 
 	int index = 1;
@@ -640,7 +638,7 @@ static int restore_inode(struct inode *pri, void *param)
 	
 	ENTRY; 
 
-	if(!pri) return 0;
+	if(!pri) RETURN(0);
 
 	data = (struct snap_iterdata*) param;
 
@@ -690,8 +688,7 @@ static int restore_inode(struct inode *pri, void *param)
 	else {
 		CDEBUG(D_SNAP, "ino %lu is older, don't restore\n", pri->i_ino);
 	}
-	EXIT;
-	return 0;
+	RETURN(0);
 }
 
 //int snap_restore(struct super_block *sb, void *data)
@@ -718,7 +715,7 @@ int snap_get_index_from_name(int tableno, char *name)
 
 	table = &snap_tables[tableno];
 
-	for ( slot = 0 ; slot < SNAP_MAX ; slot++ ) {
+	for ( slot = 0 ; slot < table->tbl_count; slot++) {
 		if (!strcmp(&table->snap_items[slot].name[0], name)) {
 			return table->snap_items[slot].index;
 		}
@@ -754,9 +751,11 @@ int snap_iterate_func( struct ioc_snap_tbl_data *data, unsigned int cmd)
 	table = &snap_tables[tableno];
 	
 	index = snap_get_index_from_name(tableno, data->snaps[0].name);
-	if (index < 0)
+	if (index < 0) {
+		CERROR("Could not find %s in snaptable\n", 
+		       data->snaps[0].name);
 		RETURN(-EINVAL);
-	
+	}
 	iterate_data.dev = (kdev_t)data->dev;
 	iterate_data.index = index;
 	iterate_data.tableno = tableno;
@@ -784,7 +783,7 @@ int snap_iterate_func( struct ioc_snap_tbl_data *data, unsigned int cmd)
 			rc = -EINVAL;
 			break;
 	}
-	RETURN(0);
+	RETURN(rc);
 }
 
 #define BUF_SIZE 1024
@@ -873,7 +872,8 @@ int snap_ioctl (struct inode * inode, struct file * filp,
 		}
 		*/
 		memcpy(name, data->name, name_len);
-		printk("dev %d , len %d, name_len %d, find name is [%s]\n", dev, input.ioc_inlen, name_len, name);
+		printk("dev %d , len %d, name_len %d, find name is [%s]\n", 
+			dev, input.ioc_inlen, name_len, name);
 		cache = snap_find_cache(dev); 
 		if ( !cache ) {
         	        EXIT;
diff --git a/lustre/snapfs/utils/snapctl.c b/lustre/snapfs/utils/snapctl.c
index 78415ccaf4d7d63b5f5e7b5fad43c967dff9892d..f11bb05c5de37ff3fb756dd0a8c54dde893cc9d0 100644
--- a/lustre/snapfs/utils/snapctl.c
+++ b/lustre/snapfs/utils/snapctl.c
@@ -174,23 +174,13 @@ static int open_device(char *name, unsigned int dev)
 	}
 	return 0;
 }
-
-int snap_dev_open(int argc, char **argv)
+static  int open_snap_device(char *name)
 {
 	struct snap_mnt *snaplist;
-	char *dev_name;
-	int rc;
-
-	if (argc != 2) { 
-		fprintf(stderr, "The argument count is not right \n");
-		return CMD_HELP;
-	}
-	
-	dev_name = argv[1];
-
+	int rc;	
 	get_snaplist();
 	list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
-		if (!strcmp(&snaplist->device.name[0], dev_name)) {
+		if (!strcmp(&snaplist->device.name[0], name)) {
 			rc = open_device(&snaplist->device.name[0], 
 				    snaplist->device.dev);
 			release_snap_list();	
@@ -198,9 +188,25 @@ int snap_dev_open(int argc, char **argv)
 		}
 	}
 	release_snap_list();	
-	fprintf(stderr, "%s are not snapdevice\n", dev_name);
+	fprintf(stderr, "%s are not snapdevice\n", name);
 	return (-EINVAL);
 }
+int snap_dev_open(int argc, char **argv)
+{
+	char *dev_name;
+	int rc;
+
+	if (argc != 2) { 
+		fprintf(stderr, "The argument count is not right \n");
+		return CMD_HELP;
+	}
+	
+	dev_name = argv[1];
+	rc = open_snap_device(dev_name);
+	if (rc)
+		fprintf(stderr, "%s are not snapdevice\n", dev_name);
+	return (rc);
+}
 int snap_dev_list(int argc, char **argv)
 {
 	struct snap_mnt *snaplist;
@@ -244,6 +250,7 @@ static inline void print_snap_table(void * buf)
 }
 int snap_snap_list(int argc, char **argv)
 {
+	char *dev_name = NULL;
 	int i, rc = 0;
 
 	if (argc != 1 && argc != 2) {
@@ -251,10 +258,17 @@ int snap_snap_list(int argc, char **argv)
 		return CMD_HELP;
 	}
 	if (open_device_table.count == 0) {
-		fprintf(stderr, "Please open a snapdevice first\n");
-		return (-EINVAL);
+		if (argc == 2) {
+			dev_name = argv[1];		
+		}	
+		if (dev_name) {
+			rc = open_snap_device(dev_name); 
+		}
+		if (!dev_name || rc) {	
+			fprintf(stderr, "Please open a snapdevice first\n");
+			return (-EINVAL);
+		}
 	}
-	
 	for (i = 0; i < open_device_table.count; i++) {
 		struct ioc_snap_tbl_data *snap_ioc_data;
 
@@ -281,16 +295,26 @@ int snap_snap_list(int argc, char **argv)
 }
 int snap_snap_del(int argc, char **argv)
 {
+	char   *dev_name = NULL, *snap_name = NULL;	
 	int    rc = 0, i;
 	
 	if (argc != 3 && argc !=2) {
 		fprintf(stderr, "The argument count is not right \n");
 		return CMD_HELP;
 	}
-
 	if (open_device_table.count == 0) {
-		fprintf(stderr, "Please open a snapdevice first\n");
-		return (-EINVAL);
+		if (argc == 3) {
+			dev_name = argv[1];		
+		} else if (argc == 4) {
+			dev_name = argv[2];
+		}
+		if (dev_name) {
+			rc = open_snap_device(dev_name); 
+		}
+		if (!dev_name || rc) {	
+			fprintf(stderr, "Please open a snapdevice first\n");
+			return (-EINVAL);
+		}
 	}
 	for (i = 0; i < open_device_table.count; i++) {
 		struct ioc_snap_tbl_data *snap_ioc_data;
@@ -302,38 +326,53 @@ int snap_snap_del(int argc, char **argv)
 
 		if (argc == 3) { 
 			snap_ioc_data->no = atoi(argv[1]);
-			memcpy(snap_ioc_data->snaps[0].name, 
-			       argv[2], strlen(argv[2]));
+			if (!snap_name)
+				snap_name = argv[2];
 		} else { 
 			snap_ioc_data->no = 0;
-			memcpy(snap_ioc_data->snaps[0].name, 
-			       argv[1], strlen(argv[1]));
+			if (!snap_name)
+				snap_name = argv[1];
 		}
+		memcpy(snap_ioc_data->snaps[0].name, 
+			       snap_name, strlen(snap_name));
+
 		snap_ioc_data->snaps[0].time = time(NULL);
 		
 		IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
 
 		if ((rc = ioctl(open_device_table.device[i].fd, 
 					IOC_SNAP_DELETE, buf))) {
-			fprintf(stderr, "del %s failed \n", argv[1]);
+			fprintf(stderr, "del %s failed \n", snap_name);
 		} else {
-			fprintf(stderr, "del %s success\n", argv[1]);
+			fprintf(stderr, "del %s success\n", snap_name);
 		}
 	}
 	return rc;
 }
 int snap_snap_add(int argc, char **argv)
 {
+	char   *dev_name = NULL, *snap_name = NULL;	
 	int    rc = 0, i;
 	
-	if (argc != 3 && argc !=2) {
+	if (argc != 3 && argc !=2 && argc !=4) {
 		fprintf(stderr, "The argument count is not right \n");
 		return CMD_HELP;
 	}
-
 	if (open_device_table.count == 0) {
-		fprintf(stderr, "Please open a snapdevice first\n");
-		return (-EINVAL);
+		if (argc == 3) {
+			dev_name = argv[1];		
+			snap_name = argv[2];
+		} else if (argc == 4) {
+			dev_name = argv[2];
+			snap_name = argv[3];
+		}
+		if (dev_name) {
+			rc = open_snap_device(dev_name); 
+		}
+		if (!dev_name || rc) {	
+			fprintf(stderr, "Please open a snapdevice first\n");
+			return (-EINVAL);
+		}
 	}
 	for (i = 0; i < open_device_table.count; i++) {
 		struct ioc_snap_tbl_data *snap_ioc_data;
@@ -345,22 +384,24 @@ int snap_snap_add(int argc, char **argv)
 
 		if (argc == 3) { 
 			snap_ioc_data->no = atoi(argv[1]);
-			memcpy(snap_ioc_data->snaps[0].name, 
-			       argv[2], strlen(argv[2]));
+			if (!snap_name)
+				snap_name = argv[2];
 		} else { 
 			snap_ioc_data->no = 0;
-			memcpy(snap_ioc_data->snaps[0].name, 
-			       argv[1], strlen(argv[1]));
+			if (!snap_name)
+				snap_name = argv[1];
 		}
+		memcpy(snap_ioc_data->snaps[0].name, 
+			       snap_name, strlen(snap_name));
 		snap_ioc_data->snaps[0].time = time(NULL);
 		
 		IOC_PACK(sizeof(struct ioc_snap_tbl_data) + sizeof(struct snap));
 
 		if ((rc = ioctl(open_device_table.device[i].fd, 
 					IOC_SNAP_ADD, buf))) {
-			fprintf(stderr, "add %s failed \n", argv[1]);
+			fprintf(stderr, "add %s failed \n", snap_name);
 		} else {
-			fprintf(stderr, "add %s success\n", argv[1]);
+			fprintf(stderr, "add %s success\n", snap_name);
 		}
 	}
 	return rc;