diff --git a/lustre/snapfs/cache.c b/lustre/snapfs/cache.c index bb1ed305309d21a09099b66b153c1dd8f768fee7..c92e870ec9eccb097c922ec1b0cf37937d39bf29 100644 --- a/lustre/snapfs/cache.c +++ b/lustre/snapfs/cache.c @@ -72,15 +72,9 @@ struct snap_cache *snap_init_cache(void) /* make a snap_cache structure for the hash */ SNAP_ALLOC(cache, sizeof(struct snap_cache)); if ( cache ) { - int i; - memset(cache, 0, sizeof(struct snap_cache)); INIT_LIST_HEAD(&cache->cache_chain); INIT_LIST_HEAD(&cache->cache_clone_list); - - for (i = 0; i < SNAP_MAX_TABLES; i++) { - init_MUTEX(&snap_tables[i].tbl_sema); - } } return cache; } diff --git a/lustre/snapfs/snapfs_internal.h b/lustre/snapfs/snapfs_internal.h index ce43dbfbc074c95e483b54042d254138d70e574c..04ead20f974cebe42b752da8f72e0bb7442300a5 100644 --- a/lustre/snapfs/snapfs_internal.h +++ b/lustre/snapfs/snapfs_internal.h @@ -39,7 +39,12 @@ struct snap_table_data { unsigned int tblcmd_count; /* how many snaps */ struct snap tblcmd_snaps[0]; /* sorted times! */ }; - +/*FIXME, use ioc_data temporary, will use obd_ioc_data later*/ +struct ioc_data { + unsigned int ioc_inlen; + char *ioc_inbuf; + char ioc_bulk[0]; +}; /* we have just a single snapshot control device it contains a list of all the snap_current info's */ @@ -47,6 +52,8 @@ struct snap_table_data { #define SNAP_PSDEV_MINOR 240 #define SNAP_PSDEV_MAJOR 10 +#define SNAP_TABLE_OUTBUF_LEN 1020 + #ifdef __KERNEL__ #if 0 diff --git a/lustre/snapfs/snaptable.c b/lustre/snapfs/snaptable.c index ac5b712fd2488034ce4664bc4aa9796e5c183df2..fae06f462f4ff9584251d430084333421339c2a9 100644 --- a/lustre/snapfs/snaptable.c +++ b/lustre/snapfs/snaptable.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/string.h> #include <linux/snap.h> +#include <linux/time.h> #include <asm/uaccess.h> #include "snapfs_internal.h" @@ -116,35 +117,12 @@ 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 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); @@ -153,38 +131,37 @@ int snap_print_table(struct snap_table_data *data, char *buf, int *buflen) 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; } @@ -222,7 +199,7 @@ int snaptable_add_item(struct snap_table_data *data) 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); } @@ -230,7 +207,7 @@ int snaptable_add_item(struct snap_table_data *data) 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; @@ -253,7 +230,8 @@ int snaptable_add_item(struct snap_table_data *data) 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); @@ -268,7 +246,7 @@ int snaptable_add_item(struct snap_table_data *data) table->tbl_count++; table->generation++; - up(&table->tbl_sema); + //up(&table->tbl_sema); return 0; } @@ -459,14 +437,19 @@ 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); + 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); @@ -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) @@ -673,8 +655,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 */ @@ -809,69 +790,63 @@ int snap_iterate_func(int len, struct snap_ioc_data *ioc_data, unsigned int cmd) 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: { @@ -889,7 +864,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 +876,7 @@ 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 +934,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(input.ioc_inlen, karg, cmd); break; #ifdef SNAP_DEBUG case IOC_SNAP_DEVFAIL: @@ -986,13 +961,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); } diff --git a/lustre/snapfs/utils/snapconf.c b/lustre/snapfs/utils/snapconf.c index 1344873834bc060a645c39c2ab7fc89b429a9209..4aad130d8fa4e301c64d7429bf180400e29b2912 100644 --- a/lustre/snapfs/utils/snapconf.c +++ b/lustre/snapfs/utils/snapconf.c @@ -35,11 +35,15 @@ command_t cmdlist[] = { "ignore errors that occur during script processing\n" "--ignore_errors"}, /* snapshot commands*/ - {"add", snapshot_add, 0, + {"device_list", snap_dev_list, 0, + "device_list list snap available device\n"}, + {"device", snap_dev_open, 0, + "dev <device> open available snap device\n"}, + {"add", snap_snap_add, 0, "add [table_no] <snap_name> add snapshot to the device\n"}, - {"list", snapshot_list, 0, "snap_list list snap available device\n"}, - {"dev", snapshot_dev, 0, "open <device> open available snap device\n"}, - + {"snap_list", snap_snap_list, 0, + "snap_list [table_no] list all the snapshots on the device\n"}, + /* User interface commands */ {"======= control ========", jt_noop, 0, "control commands"}, {"help", Parser_help, 0, "help"}, diff --git a/lustre/snapfs/utils/snapctl.c b/lustre/snapfs/utils/snapctl.c index 8f82b6274713ad07019cfad57c03827c15442b93..a7828bae2df91bfaa338f9e3863115993bc840f1 100644 --- a/lustre/snapfs/utils/snapctl.c +++ b/lustre/snapfs/utils/snapctl.c @@ -14,11 +14,20 @@ #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; @@ -57,6 +66,7 @@ static int get_snaplist() } 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) { @@ -77,7 +87,6 @@ static int get_snaplist() goto exit; } s_mnt->device.dev = (unsigned long)statbuf.st_rdev; - list_add(&s_mnt->snap_mnt_list, &snap_list); } } @@ -161,7 +170,7 @@ static int open_device(char *name, unsigned int dev) return 0; } -int snapshot_dev(int argc, char **argv) +int snap_dev_open(int argc, char **argv) { struct snap_mnt *snaplist; char *dev_name; @@ -184,29 +193,67 @@ int snapshot_dev(int argc, char **argv) } } 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"); @@ -214,40 +261,36 @@ int snapshot_add(int argc, char **argv) } 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; } diff --git a/lustre/snapfs/utils/snapctl.h b/lustre/snapfs/utils/snapctl.h index ef0f68b956923c70399b4661acfdeadc830b1756..fe9eb5d0436d23db226a5efc7b98221862a58e93 100644 --- a/lustre/snapfs/utils/snapctl.h +++ b/lustre/snapfs/utils/snapctl.h @@ -2,6 +2,7 @@ #define DEV_NAME_MAX_LEN 64 struct snap_device { char name[DEV_NAME_MAX_LEN]; + char mntpt[DEV_NAME_MAX_LEN]; unsigned long dev; int fd; }; @@ -13,12 +14,9 @@ struct open_snap_device { struct snap_device device[10]; int count; }; -struct ioc_data { - int len; - char *data; -}; extern void init_snap_list(void); -extern int snapshot_dev(int argc, char **argv); -extern int snapshot_list(int argc, char **argv); -extern int snapshot_add(int argc, char **argv); +extern int snap_dev_open(int argc, char **argv); +extern int snap_dev_list(int argc, char **argv); +extern int snap_snap_add(int argc, char **argv); +extern int snap_snap_list(int argc, char **argv);