X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Fiface-file.c;h=6f69c3d7766dac38a32a29e89edd48a1b58646b1;hb=a8686374c6aa74d805b32e7675f42f7ab9a0b348;hp=b770256796d8e357c7c796b5e6d74324437d0a64;hpb=791ea2f3e21cfbc9c47341efbb98995c33d86fcb;p=palacios.git diff --git a/linux_module/iface-file.c b/linux_module/iface-file.c index b770256..6f69c3d 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; @@ -67,6 +79,7 @@ static int mkdir_recursive(const char * path, unsigned short perms) { if ( (!isprint(*tmp_iter))) { ERROR("Invalid character in path name (%d)\n", *tmp_iter); + palacios_free(tmp_str); return -1; } else { tmp_iter++; @@ -83,6 +96,7 @@ static int mkdir_recursive(const char * path, unsigned short perms) { if ((tmp_iter - dirname_ptr) > 1) { if (palacios_file_mkdir(tmp_str, perms, 0) != 0) { 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; } @@ -111,6 +125,9 @@ static int palacios_file_mkdir(const char * pathname, unsigned short perms, int /* 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; @@ -125,10 +142,8 @@ 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(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 @@ -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); } @@ -188,7 +203,11 @@ static void * palacios_file_open(const char * path, int mode, void * private_dat } } - 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)) { + 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,12 +260,18 @@ 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; } @@ -249,7 +282,7 @@ static unsigned long long palacios_file_size(void * file_ptr) { 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) { ERROR("Failed to fstat file\n"); @@ -323,15 +356,27 @@ static int file_init( void ) { static int file_deinit( void ) { - if (!list_empty(&(global_files))) { - ERROR("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,8 +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; - kfree(vm_data); + 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; }