From: Patrick G. Bridges Date: Fri, 28 Oct 2011 16:13:15 +0000 (-0600) Subject: Merge branch 'devel' of ssh://newskysaw.cs.northwestern.edu/home/palacios/palacios... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=d71b19cdb18342f2b761f6d9aac7ec175486e1ba;hp=95b1b11f48e19834fca26e87f594d6794f1c6d55 Merge branch 'devel' of ssh://newskysaw.cs.northwestern.edu/home/palacios/palacios into devel --- diff --git a/linux_module/iface-file.c b/linux_module/iface-file.c index 965023a..96a2477 100644 --- a/linux_module/iface-file.c +++ b/linux_module/iface-file.c @@ -4,6 +4,8 @@ #include +#include +#include #include #include #include @@ -16,6 +18,7 @@ static struct list_head global_files; +#define isprint(a) ((a >= ' ') && (a <= '~')) struct palacios_file { struct file * filp; @@ -39,6 +42,138 @@ struct vm_file_state { +static int palacios_file_mkdir(const char * pathname, unsigned short perms, int recurse); + +static int mkdir_recursive(const char * path, unsigned short perms) { + char * tmp_str = NULL; + char * dirname_ptr; + char * tmp_iter; + + tmp_str = kmalloc(strlen(path) + 1, GFP_KERNEL); + memset(tmp_str, 0, strlen(path) + 1); + strncpy(tmp_str, path, strlen(path)); + + dirname_ptr = tmp_str; + tmp_iter = tmp_str; + + // parse path string, call palacios_file_mkdir recursively. + + + while (dirname_ptr != NULL) { + int done = 0; + + while ((*tmp_iter != '/') && + (*tmp_iter != '\0')) { + + if ( (!isprint(*tmp_iter))) { + printk("Invalid character in path name (%d)\n", *tmp_iter); + return -1; + } else { + tmp_iter++; + } + } + + if (*tmp_iter == '/') { + *tmp_iter = '\0'; + } else { + done = 1; + } + + // Ignore empty directories + if ((tmp_iter - dirname_ptr) > 1) { + if (palacios_file_mkdir(tmp_str, perms, 0) != 0) { + printk("Could not create directory (%s)\n", tmp_str); + return -1; + } + } + + if (done) { + break; + } else { + *tmp_iter = '/'; + } + + tmp_iter++; + + dirname_ptr = tmp_iter; + } + + kfree(tmp_str); + + return 0; +} + +static int palacios_file_mkdir(const char * pathname, unsigned short perms, int recurse) { + /* Welcome to the jungle... */ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0) + /* DO NOT REFERENCE THIS VARIABLE */ + /* It only exists to provide version compatibility */ + struct path tmp_path; +#endif + + struct path * path_ptr = NULL; + struct dentry * dentry; + int ret = 0; + + + + if (recurse != 0) { + return mkdir_recursive(pathname, perms); + } + + /* Before Linux 3.1 this was somewhat more difficult */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) + { + struct nameidata nd; + + // I'm not 100% sure about the version here, but it was around this time that the API changed +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35) + ret = kern_path_parent(pathname, &nd); +#else + + if (path_lookup(pathname, LOOKUP_DIRECTORY | LOOKUP_FOLLOW, &nd) == 0) { + return 0; + } + + if (path_lookup(pathname, LOOKUP_PARENT | LOOKUP_FOLLOW, &nd) != 0) { + return -1; + } +#endif + + if (ret != 0) { + printk("%s:%d - Error: kern_path_parent() returned error for (%s)\n", __FILE__, __LINE__, + pathname); + return -1; + } + + dentry = lookup_create(&nd, 1); + path_ptr = &(nd.path); + } +#else + { + dentry = kern_path_create(AT_FDCWD, pathname, &tmp_path, 1); + + if (IS_ERR(dentry)) { + return 0; + } + + path_ptr = &tmp_path; + } +#endif + + + if (!IS_ERR(dentry)) { + ret = vfs_mkdir(path_ptr->dentry->d_inode, dentry, perms); + } + + mutex_unlock(&(path_ptr->dentry->d_inode->i_mutex)); + path_put(path_ptr); + + return ret; +} + + static void * palacios_file_open(const char * path, int mode, void * private_data) { struct v3_guest * guest = (struct v3_guest *)private_data; struct palacios_file * pfile = NULL; @@ -170,6 +305,7 @@ static struct v3_file_hooks palacios_file_hooks = { .read = palacios_file_read, .write = palacios_file_write, .size = palacios_file_size, + .mkdir = palacios_file_mkdir, }; @@ -198,6 +334,7 @@ static int guest_file_init(struct v3_guest * guest, void ** vm_data) { *vm_data = state; + return 0; } diff --git a/palacios/include/interfaces/vmm_file.h b/palacios/include/interfaces/vmm_file.h index 46b89b1..69b78d8 100644 --- a/palacios/include/interfaces/vmm_file.h +++ b/palacios/include/interfaces/vmm_file.h @@ -27,6 +27,8 @@ #ifdef __V3VEE__ typedef void * v3_file_t; +int v3_mkdir(char * path, uint16_t permissions, uint8_t recursive); + v3_file_t v3_file_open(struct v3_vm_info * vm, char * path, uint8_t mode); int v3_file_close(v3_file_t file); @@ -42,6 +44,7 @@ uint64_t v3_file_write(v3_file_t file, uint8_t * buf, uint64_t len, uint64_t off #define FILE_OPEN_MODE_CREATE (1 << 2) struct v3_file_hooks { + int (*mkdir)(const char * path, unsigned short perms, int recursive); void * (*open)(const char * path, int mode, void * host_data); int (*close)(void * fd); diff --git a/palacios/src/interfaces/vmm_file.c b/palacios/src/interfaces/vmm_file.c index c22267a..c4d3f28 100644 --- a/palacios/src/interfaces/vmm_file.c +++ b/palacios/src/interfaces/vmm_file.c @@ -34,6 +34,13 @@ void V3_Init_File(struct v3_file_hooks * hooks) { } +int v3_mkdir(char * path, uint16_t permissions, uint8_t recursive) { + V3_ASSERT(file_hooks); + V3_ASSERT(file_hooks->mkdir); + + return file_hooks->mkdir(path, permissions, recursive); +} + v3_file_t v3_file_open(struct v3_vm_info * vm, char * path, uint8_t mode) { void * priv_data = NULL; V3_ASSERT(file_hooks); diff --git a/palacios/src/palacios/vmm_chkpt_stores.h b/palacios/src/palacios/vmm_chkpt_stores.h index 505ef8c..389a0ca 100644 --- a/palacios/src/palacios/vmm_chkpt_stores.h +++ b/palacios/src/palacios/vmm_chkpt_stores.h @@ -179,6 +179,109 @@ register_chkpt_store(keyed_stream_store); +#ifdef V3_CONFIG_FILE +#include + + +struct file_ctx { + v3_file_t file; + uint64_t offset; + char * filename; +}; + + +static void * dir_open_chkpt(char * url, chkpt_mode_t mode) { + if (mode == SAVE) { + if (v3_mkdir(url, 0755, 1) != 0) { + return NULL; + } + } + + return url; +} + + + +static int dir_close_chkpt(void * store_data) { + return 0; +} + +static void * dir_open_ctx(void * store_data, + void * parent_ctx, + char * name) { + + char * url = store_data; + struct file_ctx * ctx = NULL; + + + ctx = V3_Malloc(sizeof(struct file_ctx)); + memset(ctx, 0, sizeof(struct file_ctx)); + + ctx->filename = V3_Malloc(strlen(url) + strlen(name) + 5); + memset(ctx->filename, 0, strlen(url) + strlen(name) + 5); + + snprintf(ctx->filename, strlen(url) + strlen(name) + 5, "%s/%s", url, name); + + + ctx->file = v3_file_open(NULL, ctx->filename, FILE_OPEN_MODE_READ | FILE_OPEN_MODE_WRITE | FILE_OPEN_MODE_CREATE); + + return ctx; +} + +static int dir_close_ctx(void * store_data, void * ctx) { + struct file_ctx * file_ctx = ctx; + + v3_file_close(file_ctx->file); + + V3_Free(file_ctx->filename); + V3_Free(file_ctx); + + return 0; +} + +static int dir_save(void * store_data, void * ctx, + char * tag, uint64_t len, void * buf) { + struct file_ctx * file_ctx = ctx; + uint64_t ret = 0; + + ret = v3_file_write(file_ctx->file, buf, len, file_ctx->offset); + + file_ctx->offset += ret; + + return 0; +} + +static int dir_load(void * store_data, void * ctx, + char * tag, uint64_t len, void * buf) { + struct file_ctx * file_ctx = ctx; + uint64_t ret = 0; + + ret = v3_file_read(file_ctx->file, buf, len, file_ctx->offset); + + file_ctx->offset += ret; + + return 0; +} + + +static struct chkpt_interface dir_store = { + .name = "DIR", + .open_chkpt = dir_open_chkpt, + .close_chkpt = dir_close_chkpt, + .open_ctx = dir_open_ctx, + .close_ctx = dir_close_ctx, + .save = dir_save, + .load = dir_load +}; + +register_chkpt_store(dir_store); + + + +#endif + + +