#include <linux/slab.h>
#include <linux/string.h>
#include <linux/snap.h>
+#include <linux/time.h>
#include <asm/uaccess.h>
#include "snapfs_internal.h"
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 tableno = data->tblcmd_no;
- int i;
struct snap_table *table;
+ int tableno = data->tblcmd_no;
+ int i, l, rc = 0, nleft = (*buflen);
char *buf_ptr;
- int nleft = (*buflen);
- int nprint = 0;
if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
CERROR("invalid table number %d\n", tableno);
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;
+ l = snprintf(buf_ptr, nleft, "snap table %d snap count %d \n",
+ tableno, table->tbl_count);
+ nleft -= l;
+ if(nleft < 0) {
+ CERROR("can not get enough space to print snaptable\n");
+ rc = -ERANGE;
+ goto exit;
+ } else {
+ buf_ptr += l;
+ }
+
+ for (i = 0; i < table->tbl_count; i++) {
+ /*FIXME later, will convert time to time string later */
+ l = snprintf(buf_ptr, nleft,
+ "-- slot %d, idx %d, time %lu, name %s\n", i,
+ table->snap_items[i+1].index, table->snap_items[i+1].time,
+ &table->snap_items[i+1].name[0]);
+
+ nleft -= l;
+ if(nleft < 0) {
+ CERROR("can not get enough space to print snaptable\n");
+ rc = -ERANGE;
+ goto exit;
+ } else {
+ buf_ptr += l;
+ }
}
-
exit:
- if(nleft > 0) (*buflen) = (*buflen) - nleft;
+ if(nleft > 0)
+ (*buflen) = (*buflen) - nleft;
return 0;
}
RETURN(-EINVAL);
tableno = data->tblcmd_no;
- if ( tableno < 0 || tableno > SNAP_MAX_TABLES ) {
+ if (tableno < 0 || tableno > SNAP_MAX_TABLES) {
CERROR("invalid table number %d\n", tableno);
RETURN(-EINVAL);
}
count = table->tbl_count;
/* XXX Is down this sema necessary*/
- down_interruptible(&table->tbl_sema);
+ //down_interruptible(&table->tbl_sema);
/*add item in snap_table*/
table->snap_items[count+1].gen = table->generation;
disk_snap_table->generation = cpu_to_le32((__u32)table->generation);
memset(&disk_snap_table->snap_items[0], 0,
SNAP_MAX * sizeof(struct snap_disk));
- for (i = 1; i <= count; i++) {
+
+ for (i = 1; i <= count + 1; 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);
table->tbl_count++;
table->generation++;
- up(&table->tbl_sema);
+ //up(&table->tbl_sema);
return 0;
}
size = sizeof(struct snap_disk_table);
+
+ table = &snap_tables[tableno];
+
+ memset(table, 0, sizeof(struct snap_table));
+ init_MUTEX(&table->tbl_sema);
+
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);
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)
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 */
RETURN(0);
}
+#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(input.ioc_inlen, 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);
}
#include "snapctl.h"
#include <snapfs_internal.h>
-#define IOC_PACK(ioc, length, input) \
-do{ \
- ioc.data = input; \
- ioc.len = length; \
-}while(0)
+#define IOC_BUF_MAX_LEN 8192
+static char rawbuf[IOC_BUF_MAX_LEN];
+static char *buf = rawbuf;
+
+/*FIXME add this temporary, will use obd_ioc_data later*/
+#define IOC_PACK(buffer, length) \
+do{ \
+ struct ioc_data* pbuf; \
+ memset(buf, 0, sizeof(rawbuf)); \
+ pbuf = (struct ioc_data*)buf; \
+ pbuf->ioc_inbuf = pbuf->ioc_bulk; \
+ pbuf->ioc_inlen = length; \
+ memcpy(pbuf->ioc_inbuf, buffer, length);\
+} while (0)
static struct list_head snap_list;
struct open_snap_device open_device_table;
}
memset(s_mnt, 0, sizeof(struct snap_mnt));
memcpy(&s_mnt->device.name[0], entry->mnt_fsname, strlen(entry->mnt_fsname));
+ memcpy(&s_mnt->device.mntpt[0], entry->mnt_dir, strlen(entry->mnt_dir));
opt = hasmntopt(entry, "loop");
memset(dev_name, 0, DEV_NAME_MAX_LEN);
if (opt) {
goto exit;
}
s_mnt->device.dev = (unsigned long)statbuf.st_rdev;
-
list_add(&s_mnt->snap_mnt_list, &snap_list);
}
}
return 0;
}
-int snapshot_dev(int argc, char **argv)
+int snap_dev_open(int argc, char **argv)
{
struct snap_mnt *snaplist;
char *dev_name;
}
}
release_snap_list();
- fprintf(stderr, "can not find the device %s", dev_name);
+ fprintf(stderr, "%s are not snapdevice\n", dev_name);
return (-EINVAL);
}
-int snapshot_list(int argc, char **argv)
+int snap_dev_list(int argc, char **argv)
{
struct snap_mnt *snaplist;
+ int index = 0;
+
if (argc != 1) {
fprintf(stderr, "The argument count is not right \n");
return CMD_HELP;
}
get_snaplist();
+ printf("index:\t\tmount_point:\t\tdevice:\n");
list_for_each_entry(snaplist, &snap_list, snap_mnt_list) {
- fprintf(stderr, "devid: %lu name: %s",
- snaplist->device.dev,
+ printf("%d\t\t%s\t\t%s \n", index,
+ &snaplist->device.mntpt[0],
&snaplist->device.name[0]);
+ index++;
}
release_snap_list();
return 0;
}
-int snapshot_add(int argc, char **argv)
+int snap_snap_list(int argc, char **argv)
{
- int rc, i;
+ int i, rc = 0;
+
+ if (argc != 1 && 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);
+ }
+
+ for (i = 0; i < open_device_table.count; i++) {
+ struct snap_table_data snap_ioc_data;
+
+ if (argc == 2) {
+ snap_ioc_data.tblcmd_no = atoi(argv[1]);
+ } else {
+ snap_ioc_data.tblcmd_no = 0;
+ }
+
+ IOC_PACK((char*)&snap_ioc_data, sizeof(struct snap_table_data));
+
+ if ((rc = ioctl(open_device_table.device[i].fd,
+ IOC_SNAP_PRINTTABLE, buf))) {
+ fprintf(stderr, "can not retrive snaptable on device %s failed %d \n",
+ &open_device_table.device[i].name[0], rc);
+ return (rc);
+ }
+ printf("%s", ((struct ioc_data*)buf)->ioc_bulk);
+ }
+ return rc;
+}
+int snap_snap_add(int argc, char **argv)
+{
+ int rc = 0, i;
if (argc != 3 && argc !=2) {
fprintf(stderr, "The argument count is not right \n");
}
if (open_device_table.count == 0) {
- fprintf(stderr, "Please first open a snapdevice \n");
+ fprintf(stderr, "Please open a snapdevice first\n");
return (-EINVAL);
}
for (i = 0; i < open_device_table.count; i++) {
- struct snap_table_data *snap_ioc_data;
- struct ioc_data ioc_data;
+ struct snap_table_data snap_ioc_data;
- snap_ioc_data = (struct snap_table_data *)
- malloc(sizeof(struct snap_table_data));
- snap_ioc_data->tblcmd_count = 1;
- snap_ioc_data->dev = open_device_table.device[i].dev;
+ snap_ioc_data.tblcmd_count = 1;
+ snap_ioc_data.dev = open_device_table.device[i].dev;
if (argc == 3) {
- snap_ioc_data->tblcmd_no = atoi(argv[1]);
- memcpy(&snap_ioc_data->tblcmd_snaps[0].name[0],
+ snap_ioc_data.tblcmd_no = atoi(argv[1]);
+ memcpy(&snap_ioc_data.tblcmd_snaps[0].name[0],
argv[2], strlen(argv[2]));
} else {
- snap_ioc_data->tblcmd_no = 0;
- memcpy(&snap_ioc_data->tblcmd_snaps[0].name[0],
+ snap_ioc_data.tblcmd_no = 0;
+ memcpy(&snap_ioc_data.tblcmd_snaps[0].name[0],
argv[1], strlen(argv[1]));
}
- snap_ioc_data->tblcmd_snaps[0].time = time(NULL);
- IOC_PACK(ioc_data, sizeof(struct snap_table_data), (char*)snap_ioc_data);
-
+ snap_ioc_data.tblcmd_snaps[0].time = time(NULL);
+
+ IOC_PACK(&snap_ioc_data, sizeof(struct snap_table_data));
+
if ((rc = ioctl(open_device_table.device[i].fd,
- IOC_SNAP_ADD, &ioc_data))) {
+ IOC_SNAP_ADD, buf))) {
fprintf(stderr, "add snapshot %s failed %d \n",
- &snap_ioc_data->tblcmd_snaps[0].name[0], rc);
+ &open_device_table.device[i].name[0], rc);
} else {
fprintf(stderr, "add snapshot %s success\n",
- &snap_ioc_data->tblcmd_snaps[0].name[0]);
+ &open_device_table.device[i].name[0]);
}
- free(snap_ioc_data);
- return rc;
}
- return 0;
+ return rc;
}