Whamcloud - gitweb
- tagging RC_CURRENT
[fs/lustre-release.git] / lustre / snapfs / snaptable.c
index ac5b712..5759058 100644 (file)
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/snap.h>
+#include <linux/time.h>
 #include <asm/uaccess.h>
 #include "snapfs_internal.h" 
 
 
 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;
 
-       for ( slot=0 ; slot<snap_table->tbl_count ; slot++ )
+       for ( slot=0 ; slot < snap_table->tbl_count ; slot++ )
                if ( snap_table->snap_items[slot].index == snap_index )
                        return slot;
        return -1;
@@ -116,89 +101,61 @@ int snap_needs_cow(struct inode *inode)
        RETURN(index);
 } /* snap_needs_cow */
 
-static int nprint_buf(char *buf, int buflen, char *fmt, ...)
-{
-        va_list args;
-        int n;
-       char local_buf[1024];
-
-        va_start(args, fmt);
-        n = vsprintf(local_buf, fmt, args);
-        va_end(args);
-       
-       if( n > buflen ) {
-               if( buflen > 1024)      buflen=1024;
-               memcpy(buf, local_buf, buflen);
-               return buflen;
-       }
-       else {
-               memcpy(buf, local_buf, n);
-               return n;
-       }
-}
-       
-int snap_print_table(struct snap_table_data *data, char *buf, int *buflen)
+int snap_print_table(struct ioc_snap_tbl_data *data, char *buf, int *buflen)
 {
-       int tableno = data->tblcmd_no;
-       int i;
        struct snap_table *table;
+       struct ioc_snap_tbl_data *stbl_out;
+       int tableno = data->no;
+       int i, rc = 0, nleft = (*buflen);
+
        char *buf_ptr;
-       int nleft = (*buflen);
-       int nprint = 0;
 
-       if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
+       if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
                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);
-       for ( i = 0 ; i < SNAP_MAX ; i++ ) {
-               printk("     -- slot %d, idx %d, time %ld, name %s\n",
-                      i, table->snap_items[i].index, table->snap_items[i].time, 
-                       &table->snap_items[i].name[0]);
-       }
-
-       buf_ptr = buf;
-       nprint= nprint_buf(buf_ptr, nleft, "------- snap table %d\n", tableno);
-       nleft -= nprint;
-       if( nleft > 0 )  buf_ptr += nprint;
-       else goto exit; 
-       nprint = nprint_buf(buf_ptr, nleft, "     -- snap count %d\n", table->tbl_count);
-       nleft -= nprint;
-       if( nleft > 0 )  buf_ptr += nprint;
-       else goto exit;
-
-       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->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;
+       stbl_out = (struct ioc_snap_tbl_data *)buf;
+       stbl_out->count = table->tbl_count - 1;
+       stbl_out->no = tableno; 
+       buf_ptr = (char*)stbl_out->snaps; 
+       nleft -= buf_ptr - buf; 
+       for (i = 1; i < table->tbl_count; i++) {
+               memcpy(buf_ptr, &table->snap_items[i], sizeof(struct snap));
+               
+               nleft -= sizeof(struct snap);
+               if(nleft < 0) { 
+                       CERROR("can not get enough space to print snaptable\n");
+                       rc = -ERANGE;
+                       goto exit; 
+               } else {
+                       buf_ptr += sizeof(struct snap);
+               }       
        }
-
 exit:
-       if(nleft > 0) (*buflen) = (*buflen) - nleft;
-
+       if(nleft > 0) 
+               (*buflen) = (*buflen) - nleft;
        return 0;
 }
-static int inline get_index_of_item(struct snap_table *table)
+static int inline get_index_of_item(struct snap_table *table, char *name)
 {
        int count = table->tbl_count;
        int i, j;
-
-       for (i = 0; i < SNAP_MAX; i ++) {
-               for (j = 1; j < count; j++) {
-                       if (table->snap_items[j].index == i)
-                               break;
+       
+       for (i = 0; i < SNAP_MAX; i++) { 
+               if (!strcmp(name, table->snap_items[i].name)) 
+                       return -EINVAL; 
+       }
+       for (i = 0; i < SNAP_MAX; i++) {
+               int found = 0;
+               for (j = 0; j < (count + 1); j++) {
+                       if (table->snap_items[j].index == i) {
+                               found = 1;
+                               break;  
+                       }
                 }
-               if (j >= count) 
+               if (!found)
                        return i;
        }
        return -EINVAL;
@@ -206,7 +163,7 @@ static int inline get_index_of_item(struct snap_table *table)
 /* 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)
+static int snaptable_add_item(struct ioc_snap_tbl_data *data)
 {
        struct snap_table               *table;
        struct snap_disk_table          *disk_snap_table;
@@ -221,8 +178,8 @@ int snaptable_add_item(struct snap_table_data *data)
        if (!snapops || !snapops->set_meta_attr)
                RETURN(-EINVAL);
 
-       tableno = data->tblcmd_no;
-       if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
+       tableno = data->no;
+       if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
                CERROR("invalid table number %d\n", tableno);
                RETURN(-EINVAL);
        }
@@ -232,34 +189,37 @@ int snaptable_add_item(struct snap_table_data *data)
        /* 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;
+       /*add item in snap_table set generation*/
+       table->snap_items[count].gen = table->generation + 1;
+       table->snap_items[count].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);
+       index = get_index_of_item(table, data->snaps[0].name);
+       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;
+       memcpy(&table->snap_items[count].name[0], 
+              data->snaps[0].name, 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);
+               GOTO(exit, rc = -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);
+       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));
+       
        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);
+               disk_snap_table->snap_items[i-1].time = cpu_to_le64((__u64)item->time);
+               disk_snap_table->snap_items[i-1].gen = cpu_to_le32((__u32)item->gen);
+               disk_snap_table->snap_items[i-1].flags = cpu_to_le32((__u32)item->flags);
+               disk_snap_table->snap_items[i-1].index = cpu_to_le32((__u32)item->index);
+               memcpy(&disk_snap_table->snap_items[i-1].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));
@@ -267,10 +227,9 @@ int snaptable_add_item(struct snap_table_data *data)
        SNAP_FREE(disk_snap_table, sizeof(struct snap_disk_table));
        table->tbl_count++;
        table->generation++;
-       
+exit:
        up(&table->tbl_sema);
-       
-       return 0;
+       RETURN(rc);
 }
 
 static int delete_inode(struct inode *primary, void *param)
@@ -289,67 +248,68 @@ static int delete_inode(struct inode *primary, void *param)
        struct inode *next_ind = NULL;
        int my_table[SNAP_MAX];
 
-       if(!primary) return 0;
+       ENTRY;
+
+       if(!primary) RETURN(0);
 
        data = (struct snap_iterdata*) param;
 
-       if(data) {
+       if (data) {
                index = data->index;
                tableno = data->tableno;
        }
 
-       CDEBUG(D_INODE, "delete_inode ino %lu, index %d\n", primary->i_ino, index);
+       CDEBUG(D_SNAP, "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;
-
+       if (!redirect) {
+               CDEBUG(D_SNAP, "redirect inode index %d not exist \n", index);
+               RETURN(0); 
+       }
        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 ) {
+       if (slot > 0) {
                this_index = table->snap_items[slot].index;
                redirect = snap_get_indirect(primary, NULL, this_index);
-               if(redirect)    
+               if (redirect) { 
                        iput(redirect);
-               else  {
+               } else {
                        snap_set_indirect(primary, old_ind, this_index, 0);
                        snap_set_indirect(primary, 0, index, 0);
-                       return 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);
 
-       if(next_ind)    iput(next_ind);
-
-       if(rc != 0)     
+       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);
-       return 0;
+       RETURN(0);
 }
 
 static int snap_delete(struct super_block *sb, struct snap_iterdata *data)
@@ -364,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)
 {
@@ -371,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);
@@ -391,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)
@@ -459,20 +435,27 @@ int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
 
        size = sizeof(struct snap_disk_table);
 
+       
+       table = &snap_tables[tableno];
+
+       memset(table, 0, sizeof(struct snap_table));
+        init_MUTEX(&table->tbl_sema); 
+
+       /*Initialized table */
+       table->tbl_count = 1;
        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];
-
+       
        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);
+       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);
@@ -486,35 +469,34 @@ int snapfs_read_snaptable(struct snap_cache *cache, int tableno)
        return 0;
 }
 
-static int getdata(int len, void **data)
+static int getdata(struct ioc_data *input, void **karg)
 {
        void *tmp = NULL;
 
-       if (!len) {
-               *data = NULL;
+       if (!input->ioc_inlen || !input->ioc_inbuf) 
                return 0;
-       }
 
-       SNAP_ALLOC(tmp, len);
-       if ( !tmp )
-               return -ENOMEM;
+       SNAP_ALLOC(tmp, input->ioc_inlen);
+       if (!tmp)
+               RETURN(-ENOMEM);
 
-       CDEBUG(D_SNAP, "snap_alloc:len %d, add %p\n", len, tmp);
+       CDEBUG(D_SNAP, "snap_alloc:len %d, add %p\n", input->ioc_inlen, tmp);
 
-       memset(tmp, 0, len);
-       if ( copy_from_user(tmp, *data, len)) {
-               SNAP_FREE(tmp, len);
-               CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, tmp);
-               return -EFAULT;
+       memset(tmp, 0, input->ioc_inlen);
+       if (copy_from_user(tmp, input->ioc_inbuf, input->ioc_inlen)) {
+               CERROR("get inbuf data error \n");
+               SNAP_FREE(tmp, input->ioc_inlen);
+               RETURN(-EFAULT);
        }
-       *data = tmp;
+       *karg = tmp;
 
        return 0;
 }
 
-static void freedata(void *data, int len) {
-       SNAP_FREE(data, len);
-       CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", len, data);
+static inline void freedata(void *data, struct ioc_data *input) 
+{
+       SNAP_FREE(data, input->ioc_inlen);
+       CDEBUG(D_SNAP, "snap_free:len %d, add %p\n", input->ioc_inlen, data);
 }
 
 static int get_next_inode(struct inode *pri, void *ino)
@@ -611,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) {
@@ -638,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;
@@ -659,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;
 
@@ -673,8 +652,7 @@ static int restore_inode(struct inode *pri, void *param)
                        pri->i_ino, index, restore_time, tableno);
 
                /* XXX: should we have = here? */       
-       if( pri->i_mtime > restore_time || pri->i_ctime > restore_time )
-       {
+       if(pri->i_mtime > restore_time || pri->i_ctime > restore_time) {
                restore_index = index;
                table = &snap_tables[tableno];
                /* first find if there are indirected at the index */
@@ -710,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)
@@ -732,146 +709,140 @@ int snap_get_index_from_name(int tableno, char *name)
        int slot;
 
        if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
-               CDEBUG(D_SNAP, ": invalid table number %d\n", tableno);
+               CERROR("invalid table number %d\n", tableno);
                return -EINVAL;
        }
 
        table = &snap_tables[tableno];
 
-       for ( slot = 0 ; slot < SNAP_MAX ; slot++ ) {
-               if(strncmp (&table->snap_items[slot].name[0], name, 
-                       SNAP_MAX_NAMELEN) == 0 ) {
+       for ( slot = 0 ; slot < table->tbl_count; slot++) {
+               if (!strcmp(&table->snap_items[slot].name[0], name)) {
                        return table->snap_items[slot].index;
                }
        }
        return -EINVAL;
 }
 
-int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd)
+int snap_iterate_func( struct ioc_snap_tbl_data *data, unsigned int cmd)
 {
-       struct snap_iterdata data;
+       struct snapshot_operations      *snapops;
+       struct snap_iterdata iterate_data;
        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 ;
+       int index, tableno, slot, rc;
 
        ENTRY;
+       
+       if (!(cache = snap_find_cache((kdev_t)data->dev)))
+               RETURN(-ENODEV);
 
-       dev = ioc_data->dev;
-       cache = snap_find_cache(dev); 
-       if ( !cache ) 
-                RETURN(-EINVAL);
+       snapops = filter_c2csnapops(cache->cache_filter);
+       if (!snapops || !snapops->set_meta_attr)
+               RETURN(-EINVAL);
+
+       tableno = data->no;
+       if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
+               CERROR("invalid table number %d\n", tableno);
+               RETURN(-EINVAL);
+       }
 
        sb = cache->cache_sb;
-       tableno = cache->cache_snap_tableno;
        table = &snap_tables[tableno];
-
-       name_len = len - sizeof(kdev_t);        
-       memset(name, 0, SNAP_MAX_NAMELEN);      
-       if(name_len > SNAP_MAX_NAMELEN)
-               name_len = SNAP_MAX_NAMELEN;
-       if(name_len < 0 ) 
-               name_len = 0;
-       memcpy(name, ioc_data->name, name_len);
        
-       if ((index = snap_get_index_from_name (tableno, name)) < 0) 
+       index = snap_get_index_from_name(tableno, data->snaps[0].name);
+       if (index < 0) {
+               CERROR("Could not find %s in snaptable\n", 
+                      data->snaps[0].name);
                RETURN(-EINVAL);
-       
-       data.dev = dev;
-       data.index = index;
-       data.tableno = tableno;
+       }
+       iterate_data.dev = (kdev_t)data->dev;
+       iterate_data.index = index;
+       iterate_data.tableno = tableno;
        slot = snap_index2slot (table, index);
        if( slot < 0 ) 
                RETURN(-EINVAL);
        
-       data.time = table->snap_items[slot].time;
+       iterate_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 );
+              iterate_data.dev, iterate_data.tableno, 
+              iterate_data.index, iterate_data.time);
 
        switch (cmd) {
                case IOC_SNAP_DEBUG:
-                       rc = snap_print(sb, &data);     
+                       rc = snap_print(sb, &iterate_data);     
                        break;
                case IOC_SNAP_DELETE:
-                       rc = snaptable_delete_item(sb, &data);  
+                       rc = snaptable_delete_item(sb, &iterate_data);  
                        break;
                case IOC_SNAP_RESTORE:
-                       rc = snap_restore(sb, &data);   
+                       rc = snap_restore(sb, &iterate_data);   
                        break;
                default:
                        CERROR("unrecognized cmd %d \n", cmd);
                        rc = -EINVAL;
                        break;
        }
-       RETURN(0);
+       RETURN(rc);
 }
 
+#define BUF_SIZE 1024
 int snap_ioctl (struct inode * inode, struct file * filp, 
                             unsigned int cmd, unsigned long arg)
 {
-       void *uarg, *karg;
-       int len;
-       int err;
-       kdev_t dev;
-       struct  {
-               int len;
-               char *data;
-       }input;
+       struct ioc_data input; 
+       void *karg = NULL;
        int rc = 0;
+       kdev_t dev;
 
        ENTRY;  
 
         dev = MINOR(inode->i_rdev);
         if (dev != SNAP_PSDEV_MINOR)
-                return -ENODEV;
+                RETURN(-ENODEV);
 
         if (!inode) {
                 CDEBUG(D_IOCTL, "invalid inode\n");
-                return -EINVAL;
+                RETURN(-EINVAL);
         }
 
         if ( _IOC_TYPE(cmd) != IOC_SNAP_TYPE || 
              _IOC_NR(cmd) < IOC_SNAP_MIN_NR  || 
              _IOC_NR(cmd) > IOC_SNAP_MAX_NR ) {
                 /*FIXME: Sometimes Gettimeof the day will come here
-                * Do not know the reason*/
+                * still 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 0;
+                RETURN(0);
         }
 
        /* get data structures */
-       err = copy_from_user(&input, (void *)arg, sizeof(input));
-       if ( err ) {
-               EXIT;
-               return err;
-       }
-       uarg = input.data;
-       len = input.len;
+       rc = copy_from_user(&input, (void *)arg, sizeof(input));
+       if (rc) RETURN(rc);
+
+       /* get data from the input data*/
+       rc = getdata(&input, &karg);
+       if (rc) RETURN(rc);
 
-       karg = input.data;
-       err = getdata(input.len, &karg);
-       if ( err ) {
-               EXIT;
-               return err;
-       }
-       
        switch (cmd) {
-       case IOC_SNAP_ADD:
+       case IOC_SNAP_ADD: {
                rc = snaptable_add_item(karg);
                break;
+       }
        case IOC_SNAP_PRINTTABLE: {
-               struct output_data{
-                       int len;
-                       char buf[1024];
-               }output;
-               output.len = sizeof(output.buf);
-               snap_print_table(karg, output.buf, &(output.len));
-               rc = copy_to_user((char *)arg, &output, output.len+sizeof(int));
+               struct ioc_data *output;
+               char   *tmp;
+               
+               SNAP_ALLOC(tmp, BUF_SIZE);
+               output=(struct ioc_data*)tmp;
+               output->ioc_inbuf = output->ioc_bulk;
+               output->ioc_inlen = BUF_SIZE - sizeof(int) - sizeof(unsigned long);
+               snap_print_table(karg, output->ioc_inbuf, &(output->ioc_inlen));
+               
+               rc = copy_to_user((char *)arg, output, 
+                                 (output->ioc_inlen + sizeof(int) + sizeof(unsigned long)));
+               SNAP_FREE(tmp, BUF_SIZE);
+
                break;
        }
        case IOC_SNAP_GETINDEXFROMNAME: {
@@ -889,7 +860,7 @@ int snap_ioctl (struct inode * inode, struct file * filp,
 
                struct get_index_struct *data = karg;
        
-               name_len = len - sizeof(kdev_t);        
+               name_len = input.ioc_inlen - sizeof(kdev_t);    
                dev = data->dev;
                memset(name, 0, SNAP_MAX_NAMELEN);      
                if(name_len > SNAP_MAX_NAMELEN)
@@ -901,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, len, 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;
@@ -959,7 +931,7 @@ int snap_ioctl (struct inode * inode, struct file * filp,
        case IOC_SNAP_DELETE: 
        case IOC_SNAP_RESTORE:
        case IOC_SNAP_DEBUG:
-               rc = snap_iterate_func(len, karg, cmd);
+               rc = snap_iterate_func(karg, cmd);
                break;
 #ifdef SNAP_DEBUG
        case IOC_SNAP_DEVFAIL:
@@ -986,13 +958,11 @@ int snap_ioctl (struct inode * inode, struct file * filp,
                
                break;
        }
-
        default:
                rc = -EINVAL;
                break;
        }
 
-       freedata(karg, input.len);
-       EXIT;
-       return rc;
+       freedata(karg, &input);
+       RETURN(rc);
 }