#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;
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;
(*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++;
// 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;
}
}
dirname_ptr = tmp_iter;
}
- kfree(tmp_str);
+ palacios_free(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)
+#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;
}
/* 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,35)
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)
ret = kern_path_parent(pathname, &nd);
#else
#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;
}
{
dentry = kern_path_create(AT_FDCWD, pathname, &tmp_path, 1);
- if (IS_ERR(dentry)) {
+ if (!dentry || IS_ERR(dentry)) {
return 0;
}
#endif
- if (!IS_ERR(dentry)) {
+ if (!(!dentry || IS_ERR(dentry))) {
ret = vfs_mkdir(path_ptr->dentry->d_inode, dentry, perms);
}
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)) {
}
- pfile->filp = filp_open(path, pfile->mode, 0);
+ pfile->mode |= O_LARGEFILE;
+
+
+ pfile->filp = filp_open(path, pfile->mode, 0600); // rw------- to start
- if (pfile->filp == NULL) {
- 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));
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;
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;
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;
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));
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;
}