X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Fiface-file.c;h=880c4d98dc53a5819a5e0c207fec0013e5ee8200;hb=c8b23e99efde3aa5a2c26d1b8e9bc7dc914e6113;hp=1df1d6d590f5bd1237cdde5d93bcb2895f01bd8e;hpb=dc41a5e6b7601dcdf9eb2ac84dbf297cac037f5b;p=palacios.git diff --git a/linux_module/iface-file.c b/linux_module/iface-file.c index 1df1d6d..880c4d9 100644 --- a/linux_module/iface-file.c +++ b/linux_module/iface-file.c @@ -20,6 +20,12 @@ static struct list_head global_files; #define isprint(a) ((a >= ' ') && (a <= '~')) +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) +#define PAL_VFS_GETATTR(path, kstat) vfs_getattr((path)->mnt, (path)->dentry, kstat) +#else +#define PAL_VFS_GETATTR(path, kstat) vfs_getattr(path, kstat) +#endif + struct palacios_file { struct file * filp; @@ -49,8 +55,14 @@ static int mkdir_recursive(const char * path, unsigned short perms) { char * dirname_ptr; char * tmp_iter; - tmp_str = kmalloc(strlen(path) + 1, GFP_KERNEL); + tmp_str = palacios_alloc(strlen(path) + 1); + if (!tmp_str) { + ERROR("Cannot allocate in mkdir recursive\n"); + return -1; + } + memset(tmp_str, 0, strlen(path) + 1); + // will terminate tmp_str strncpy(tmp_str, path, strlen(path)); dirname_ptr = tmp_str; @@ -66,7 +78,8 @@ static int mkdir_recursive(const char * path, unsigned short perms) { (*tmp_iter != '\0')) { if ( (!isprint(*tmp_iter))) { - printk("Invalid character in path name (%d)\n", *tmp_iter); + ERROR("Invalid character in path name (%d)\n", *tmp_iter); + palacios_free(tmp_str); return -1; } else { tmp_iter++; @@ -82,7 +95,8 @@ static int mkdir_recursive(const char * path, unsigned short perms) { // 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); + ERROR("Could not create directory (%s)\n", tmp_str); + palacios_free(tmp_str); return -1; } } @@ -98,7 +112,7 @@ static int mkdir_recursive(const char * path, unsigned short perms) { dirname_ptr = tmp_iter; } - kfree(tmp_str); + palacios_free(tmp_str); return 0; } @@ -106,11 +120,14 @@ static int mkdir_recursive(const char * path, unsigned short perms) { 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) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41) /* DO NOT REFERENCE THIS VARIABLE */ /* It only exists to provide version compatibility */ struct path tmp_path; #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,41) + struct nameidata nd; +#endif struct path * path_ptr = NULL; struct dentry * dentry; @@ -123,12 +140,10 @@ static int palacios_file_mkdir(const char * pathname, unsigned short perms, int } /* Before Linux 3.1 this was somewhat more difficult */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,41) { - 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,37) +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38) ret = kern_path_parent(pathname, &nd); #else @@ -142,7 +157,7 @@ static int palacios_file_mkdir(const char * pathname, unsigned short perms, int #endif if (ret != 0) { - printk("%s:%d - Error: kern_path_parent() returned error for (%s)\n", __FILE__, __LINE__, + ERROR("%s:%d - Error: kern_path_parent() returned error for (%s)\n", __FILE__, __LINE__, pathname); return -1; } @@ -154,7 +169,7 @@ static int palacios_file_mkdir(const char * pathname, unsigned short perms, int { dentry = kern_path_create(AT_FDCWD, pathname, &tmp_path, 1); - if (IS_ERR(dentry)) { + if (!dentry || IS_ERR(dentry)) { return 0; } @@ -163,7 +178,7 @@ static int palacios_file_mkdir(const char * pathname, unsigned short perms, int #endif - if (!IS_ERR(dentry)) { + if (!(!dentry || IS_ERR(dentry))) { ret = vfs_mkdir(path_ptr->dentry->d_inode, dentry, perms); } @@ -183,12 +198,16 @@ static void * palacios_file_open(const char * path, int mode, void * private_dat vm_state = get_vm_ext_data(guest, "FILE_INTERFACE"); if (vm_state == NULL) { - printk("ERROR: Could not locate vm file state for extension FILE_INTERFACE\n"); + ERROR("ERROR: Could not locate vm file state for extension FILE_INTERFACE\n"); return NULL; } } - pfile = kmalloc(sizeof(struct palacios_file), GFP_KERNEL); + pfile = palacios_alloc(sizeof(struct palacios_file)); + if (!pfile) { + ERROR("Cannot allocate in file open\n"); + return NULL; + } memset(pfile, 0, sizeof(struct palacios_file)); if ((mode & FILE_OPEN_MODE_READ) && (mode & FILE_OPEN_MODE_WRITE)) { @@ -207,18 +226,26 @@ static void * palacios_file_open(const char * path, int mode, void * private_dat pfile->mode |= O_LARGEFILE; - pfile->filp = filp_open(path, pfile->mode, 0); + pfile->filp = filp_open(path, pfile->mode, 0600); // rw------- to start - if (IS_ERR(pfile->filp)) { - printk("Cannot open file: %s\n", path); + if (!pfile->filp || IS_ERR(pfile->filp)) { + ERROR("Cannot open file: %s\n", path); + palacios_free(pfile); return NULL; } - pfile->path = kmalloc(strlen(path) + 1, GFP_KERNEL); - strncpy(pfile->path, path, strlen(path)); + pfile->path = palacios_alloc(strlen(path) + 1); + + if (!pfile->path) { + ERROR("Cannot allocate in file open\n"); + filp_close(pfile->filp,NULL); + palacios_free(pfile); + return NULL; + } + strncpy(pfile->path, path, strlen(path)); // will terminate pfile->path pfile->guest = guest; - spin_lock_init(&(pfile->lock)); + palacios_spinlock_init(&(pfile->lock)); if (guest == NULL) { list_add(&(pfile->file_node), &(global_files)); @@ -233,33 +260,39 @@ static void * palacios_file_open(const char * path, int mode, void * private_dat static int palacios_file_close(void * file_ptr) { struct palacios_file * pfile = (struct palacios_file *)file_ptr; + if (!pfile) { + return -1; + } + filp_close(pfile->filp, NULL); list_del(&(pfile->file_node)); - kfree(pfile->path); - kfree(pfile); + palacios_spinlock_deinit(&(pfile->lock)); + + palacios_free(pfile->path); + palacios_free(pfile); return 0; } -static long long palacios_file_size(void * file_ptr) { +static unsigned long long palacios_file_size(void * file_ptr) { struct palacios_file * pfile = (struct palacios_file *)file_ptr; struct file * filp = pfile->filp; struct kstat s; int ret; - ret = vfs_getattr(filp->f_path.mnt, filp->f_path.dentry, &s); + ret = PAL_VFS_GETATTR(&(filp->f_path), &s); if (ret != 0) { - printk("Failed to fstat file\n"); + ERROR("Failed to fstat file\n"); return -1; } return s.size; } -static long long palacios_file_read(void * file_ptr, void * buffer, long long length, long long offset){ +static unsigned long long palacios_file_read(void * file_ptr, void * buffer, unsigned long long length, unsigned long long offset){ struct palacios_file * pfile = (struct palacios_file *)file_ptr; struct file * filp = pfile->filp; ssize_t ret; @@ -273,14 +306,14 @@ static long long palacios_file_read(void * file_ptr, void * buffer, long long le set_fs(old_fs); if (ret <= 0) { - printk("sys_read of %p for %lld bytes failed\n", filp, length); + ERROR("sys_read of %p for %lld bytes at offset %llu failed (ret=%ld)\n", filp, length, offset, ret); } return ret; } -static long long palacios_file_write(void * file_ptr, void * buffer, long long length, long long offset) { +static unsigned long long palacios_file_write(void * file_ptr, void * buffer, unsigned long long length, unsigned long long offset) { struct palacios_file * pfile = (struct palacios_file *)file_ptr; struct file * filp = pfile->filp; mm_segment_t old_fs; @@ -295,7 +328,7 @@ static long long palacios_file_write(void * file_ptr, void * buffer, long long l if (ret <= 0) { - printk("sys_write failed\n"); + ERROR("sys_write for %llu bytes at offset %llu failed (ret=%ld)\n", length, offset, ret); } return ret; @@ -323,15 +356,27 @@ static int file_init( void ) { static int file_deinit( void ) { - if (!list_empty(&(global_files))) { - printk("Error removing module with open files\n"); + struct palacios_file * pfile = NULL; + struct palacios_file * tmp = NULL; + + list_for_each_entry_safe(pfile, tmp, &(global_files), file_node) { + filp_close(pfile->filp, NULL); + list_del(&(pfile->file_node)); + palacios_free(pfile->path); + palacios_free(pfile); } return 0; } static int guest_file_init(struct v3_guest * guest, void ** vm_data) { - struct vm_file_state * state = kmalloc(sizeof(struct vm_file_state), GFP_KERNEL); + struct vm_file_state * state = palacios_alloc(sizeof(struct vm_file_state)); + + if (!state) { + ERROR("Cannot allocate when intializing file services for guest\n"); + return -1; + } + INIT_LIST_HEAD(&(state->open_files)); @@ -343,7 +388,18 @@ static int guest_file_init(struct v3_guest * guest, void ** vm_data) { static int guest_file_deinit(struct v3_guest * guest, void * vm_data) { + struct vm_file_state * state = (struct vm_file_state *)vm_data; + struct palacios_file * pfile = NULL; + struct palacios_file * tmp = NULL; + list_for_each_entry_safe(pfile, tmp, &(state->open_files), file_node) { + filp_close(pfile->filp, NULL); + list_del(&(pfile->file_node)); + palacios_free(pfile->path); + palacios_free(pfile); + } + + palacios_free(state); return 0; }