#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;
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;
/* 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;
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);
}
/* 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));
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)
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)
/* 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)
{
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);
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)
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);
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)
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) {
}
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;
ENTRY;
- if(!pri) return 0;
+ if(!pri) RETURN(0);
data = (struct snap_iterdata*) 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 */
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)
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: {
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)
}
*/
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;
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:
break;
}
-
default:
rc = -EINVAL;
break;
}
- freedata(karg, input.len);
- EXIT;
- return rc;
+ freedata(karg, &input);
+ RETURN(rc);
}