From: Peter Dinda Date: Tue, 22 Dec 2015 00:43:11 +0000 (-0600) Subject: Linux kernel compatability enhancements (through 3.19) X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=c8b23e99efde3aa5a2c26d1b8e9bc7dc914e6113 Linux kernel compatability enhancements (through 3.19) and other bug fixes --- diff --git a/linux_module/iface-file.c b/linux_module/iface-file.c index 6f69c3d..880c4d9 100644 --- a/linux_module/iface-file.c +++ b/linux_module/iface-file.c @@ -21,7 +21,7 @@ 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) +#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 @@ -282,7 +282,7 @@ static unsigned long long palacios_file_size(void * file_ptr) { struct kstat s; int ret; - ret = PAL_VFS_GETATTR(filp->f_path, &s); + ret = PAL_VFS_GETATTR(&(filp->f_path), &s); if (ret != 0) { ERROR("Failed to fstat file\n"); diff --git a/linux_module/iface-keyed-stream.c b/linux_module/iface-keyed-stream.c index 99524e1..1f75aa0 100644 --- a/linux_module/iface-keyed-stream.c +++ b/linux_module/iface-keyed-stream.c @@ -657,12 +657,157 @@ struct file_stream { struct file *f; // the opened file }; +/* lookup directory, see if it is writeable, and if so, create it if asked*/ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,41) + +static int lookup_check_mkdir(const char *path, int need_write, int create, unsigned short perms) +{ + struct nameidata nd; + + if (path_lookup(path,LOOKUP_DIRECTORY|LOOKUP_FOLLOW,&nd)) { + + // directory does does not exist. + + if (!create) { + // we are not being asked to create it + ERROR("attempt to open %s, which does not exist\n",path); + return -1; + } else { + // We are being asked to create it + + struct dentry *de; + int err; + + // Find its parent + if (path_lookup(path,LOOKUP_PARENT|LOOKUP_FOLLOW,&nd)) { + ERROR("attempt to create %s failed because its parent cannot be looked up\n",path); + return -1; + } + + // Can we write to the parent? + + if (inode_permission(nd.path.dentry->d_inode, MAY_WRITE | MAY_EXEC)) { + ERROR("attempt to open %s, which has the wrong permissions for directory creation\n",path); + return -1; + } + + // OK, we can, so let's create it + + de = lookup_create(&nd,1); + + if (!de || IS_ERR(de)) { + ERROR("cannot allocate dentry\n"); + return -1; + } + + err = vfs_mkdir(nd.path.dentry->d_inode, de, perms); + + // lookup_create locks this for us! + + mutex_unlock(&(nd.path.dentry->d_inode->i_mutex)); + + if (err) { + ERROR("attempt to create %s failed because mkdir failed\n",path); + return -1; + } + + // successfully created it. + return 0; + + } + + } else { + + // it exists, can we read (and write, if needed) to it? + + if (inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_READ | need_write ? MAY_WRITE : 0 )) { + ERROR("attempt to open %s, which has the wrong permissions\n",path); + return -1; + } + + return 0; + } +} +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,41) +static int lookup_check_mkdir(const char *path, int need_write, int create, unsigned short perms) +{ + struct path p; + + if (kern_path(path, LOOKUP_DIRECTORY|LOOKUP_FOLLOW, &p)) { + + // directory does does not exist. + + if (!create) { + // we are not being asked to create it + ERROR("attempt to open %s, which does not exist\n",path); + return -1; + } else { + // We are being asked to create it + + struct dentry *de; + int err; + + // Find its parent + if (kern_path(path,LOOKUP_PARENT|LOOKUP_FOLLOW,&p)) { + ERROR("attempt to create %s failed because its parent cannot be looked up\n",path); + return -1; + } + + // Can we write to the parent? + + if (inode_permission(p.dentry->d_inode, MAY_WRITE | MAY_EXEC)) { + ERROR("attempt to open %s, which has the wrong permissions for directory creation\n",path); + return -1; + } + + // OK, we can, so let's create it + + de = kern_path_create(AT_FDCWD,path,&p,1); + + if (!de || IS_ERR(de)) { + ERROR("cannot allocate dentry\n"); + return -1; + } + + err = vfs_mkdir(p.dentry->d_inode, de, perms); + + // lookup_create locks this for us! + + mutex_unlock(&(p.dentry->d_inode->i_mutex)); + + if (err) { + ERROR("attempt to create %s failed because mkdir failed\n",path); + return -1; + } + + // successfully created it. + return 0; + + } + + } else { + + // it exists, can we read (and write, if needed) to it? + + if (inode_permission(p.dentry->d_inode, MAY_EXEC | MAY_READ | need_write ? MAY_WRITE : 0 )) { + ERROR("attempt to open %s, which has the wrong permissions\n",path); + return -1; + } + + return 0; + } +} + +#endif + static v3_keyed_stream_t open_stream_file(char *url, v3_keyed_stream_open_t ot) { struct file_keyed_stream *fks; - struct nameidata nd; if (strncasecmp(url,"file:",5)) { WARNING("illegitimate attempt to open file stream \"%s\"\n",url); @@ -690,74 +835,12 @@ static v3_keyed_stream_t open_stream_file(char *url, fks->ot= ot==V3_KS_WR_ONLY_CREATE ? V3_KS_WR_ONLY : ot; - // Does the directory exist, and can we read/write it? - - if (path_lookup(fks->path,LOOKUP_DIRECTORY|LOOKUP_FOLLOW,&nd)) { - - // directory does does not exist. - - if (ot==V3_KS_RD_ONLY || ot==V3_KS_WR_ONLY) { - - // we are not being asked to create it - ERROR("attempt to open %s, which does not exist\n",fks->path); - goto fail_out; - - } else { - - // We are being asked to create it - - struct dentry *de; - int err; - - // Find its parent - if (path_lookup(fks->path,LOOKUP_PARENT|LOOKUP_FOLLOW,&nd)) { - ERROR("attempt to create %s failed because its parent cannot be looked up\n",fks->path); - goto fail_out; - } - - // Can we write to the parent? - - if (inode_permission(nd.path.dentry->d_inode, MAY_WRITE | MAY_EXEC)) { - ERROR("attempt to open %s, which has the wrong permissions for directory creation\n",fks->path); - goto fail_out; - } - - // OK, we can, so let's create it - - de = lookup_create(&nd,1); - - if (!de || IS_ERR(de)) { - ERROR("cannot allocate dentry\n"); - goto fail_out; - } - - err = vfs_mkdir(nd.path.dentry->d_inode, de, 0700); - - // lookup_create locks this for us! - - mutex_unlock(&(nd.path.dentry->d_inode->i_mutex)); - - if (err) { - ERROR("attempt to create %s failed because mkdir failed\n",fks->path); - goto fail_out; - } - - // now the directory should exist and have reasonable permissions - return (v3_keyed_stream_t) fks; - } - } - - - // we must be in V3_KS_RD_ONLY or V3_KS_WR_ONLY, - // and the directory exists, so we must check the permissions - - if (inode_permission(nd.path.dentry->d_inode, MAY_EXEC | (ot==V3_KS_RD_ONLY ? MAY_READ : MAY_WRITE))) { - ERROR("attempt to open %s, which has the wrong permissions\n",fks->path); - goto fail_out; - } else { - return (v3_keyed_stream_t) fks; + if (lookup_check_mkdir(fks->path,ot!=V3_KS_RD_ONLY,ot==V3_KS_WR_ONLY_CREATE,0700)) { + ERROR("cannot find or create directory for stream\n"); + goto fail_out; } + return fks; fail_out: palacios_free(fks->path); @@ -2352,8 +2435,12 @@ static int send_msg(struct net_stream *ns, char * buf, int len) msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0); +#endif iov.iov_base = (char *)&(buf[len-left]); iov.iov_len = (size_t)left; @@ -2406,8 +2493,12 @@ static int recv_msg(struct net_stream *ns, char * buf, int len) msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),READ,&iov,1,0); +#endif iov.iov_base = (void *)&(buf[len-left]); iov.iov_len = (size_t)left; diff --git a/linux_module/iface-pstate-ctrl.c b/linux_module/iface-pstate-ctrl.c index 9b3e4bb..2c49be9 100644 --- a/linux_module/iface-pstate-ctrl.c +++ b/linux_module/iface-pstate-ctrl.c @@ -939,8 +939,22 @@ static int governor_switch(char * s, unsigned int cpu) argv[3] = NULL; /* KCH: we can't wait here to actually see if we succeeded, we're in interrupt context */ - return call_usermodehelper_fns("/bin/sh", argv, envp, UMH_NO_WAIT, NULL, gov_switch_cleanup, NULL); +#if LINUX_VERSION_CODE <= KERNEL_VERSION(3,9,0) + return call_usermodehelper_fns("/bin/sh", argv, envp, UMH_NO_WAIT, NULL, gov_switch_cleanup, NULL); +#else + { + struct subprocess_info *sp; + + sp = call_usermodehelper_setup("/bin/sh", argv, envp, GFP_ATOMIC, NULL, gov_switch_cleanup, NULL); + if (!sp) { + goto out_freeargv; + } + + return call_usermodehelper_exec(sp,0); + } +#endif + out_freeargv: palacios_free(argv); return -1; @@ -1740,27 +1754,22 @@ int pstate_proc_setup(void) struct proc_dir_entry *proc; struct proc_dir_entry *prochw; - proc = create_proc_entry("v3-dvfs",0444, palacios_get_procdir()); + PAL_PROC_CREATE(proc,"v3-dvfs",0444,palacios_get_procdir(),&pstate_fops); if (!proc) { ERROR("Failed to create proc entry for p-state control\n"); return -1; } - proc->proc_fops = &pstate_fops; - INFO("/proc/v3vee/v3-dvfs successfully created\n"); - prochw = create_proc_entry("v3-dvfs-hw",0444,palacios_get_procdir()); - + PAL_PROC_CREATE(prochw,"v3-dvfs-hw",0444,palacios_get_procdir(),&pstate_hw_fops); if (!prochw) { ERROR("Failed to create proc entry for p-state hw info\n"); return -1; } - prochw->proc_fops = &pstate_hw_fops; - INFO("/proc/v3vee/v3-dvfs-hw successfully created\n"); return 0; diff --git a/linux_module/iface-pwrstat.c b/linux_module/iface-pwrstat.c index 98ea8c0..8157fa2 100644 --- a/linux_module/iface-pwrstat.c +++ b/linux_module/iface-pwrstat.c @@ -47,7 +47,7 @@ static struct rapl_domain rapl_domains[] = { [RAPL_DOMAIN_PKG] = { .domain_id = RAPL_DOMAIN_PKG, .msrs = { - .limit = MSR_PKG_RAPL_POWER_LIMIT, + .limit = MSR_PKG_POWER_LIMIT, .status = MSR_PKG_ENERGY_STATUS, }, .valid = 1, diff --git a/linux_module/iface-pwrstat.h b/linux_module/iface-pwrstat.h index eb22df3..338140f 100644 --- a/linux_module/iface-pwrstat.h +++ b/linux_module/iface-pwrstat.h @@ -9,9 +9,14 @@ /* WARNING WARNING: this is speculation... */ #define HASWELL_MODEL_NO 0x4A -#define MSR_RAPL_POWER_UNIT 0x606 +#ifdef MSR_RAPL_POWER_UNIT +// assume the rest are also defined by the kernel's msr include +// except for special ones here -#define MSR_PKG_RAPL_POWER_LIMIT 0x610 +#else +// assume none are defined by the kernel's msr include +#define MSR_RAPL_POWER_UNIT 0x606 +#define MSR_PKG_POWER_LIMIT 0x610 #define MSR_PKG_ENERGY_STATUS 0x611 #define MSR_PKG_PERF_STATUS 0x613 #define MSR_PKG_POWER_INFO 0x614 @@ -33,6 +38,8 @@ #define MSR_DRAM_PERF_STATUS 0x61B #define MSR_DRAM_POWER_INFO 0x61C +#endif + /* RAPL UNIT BITMASK */ #define POWER_UNIT_OFFSET 0 #define POWER_UNIT_MASK 0x0F @@ -43,4 +50,5 @@ #define TIME_UNIT_OFFSET 0x10 #define TIME_UNIT_MASK 0xF0000 + #endif diff --git a/linux_module/iface-socket.c b/linux_module/iface-socket.c index 7f0328c..3f85682 100644 --- a/linux_module/iface-socket.c +++ b/linux_module/iface-socket.c @@ -301,8 +301,12 @@ palacios_send( msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0); +#endif iov.iov_base = (char *)buf; iov.iov_len = (size_t)len; @@ -340,8 +344,12 @@ palacios_recv( msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),READ,&iov,1,0); +#endif iov.iov_base = (void *)&buf[0]; iov.iov_len = (size_t)len; @@ -385,8 +393,12 @@ palacios_sendto_ip( msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0); +#endif iov.iov_base = (char *)buf; iov.iov_len = (size_t)len; @@ -433,8 +445,12 @@ palacios_recvfrom_ip( msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),READ,&iov,1,0); +#endif iov.iov_base = (void *)&buf[0]; iov.iov_len = (size_t)len; diff --git a/linux_module/main.c b/linux_module/main.c index 7b40e19..b0dbfee 100644 --- a/linux_module/main.c +++ b/linux_module/main.c @@ -36,6 +36,7 @@ #include "util-hashtable.h" + MODULE_LICENSE("GPL"); // Module parameter diff --git a/linux_module/palacios-stubs.c b/linux_module/palacios-stubs.c index 7814987..039c170 100644 --- a/linux_module/palacios-stubs.c +++ b/linux_module/palacios-stubs.c @@ -9,6 +9,11 @@ #include #include #include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) +#include +#endif #include #include @@ -420,6 +425,7 @@ static int lnx_thread_target(void * arg) { // We are a kernel thread that needs FPU save/restore state // vcores definitely need this, all the other threads get it too, // but they just won't use it + fpu_alloc(&(current->thread.fpu)); #endif diff --git a/linux_module/palacios-vnet-brg.c b/linux_module/palacios-vnet-brg.c index 945909a..abf4142 100644 --- a/linux_module/palacios-vnet-brg.c +++ b/linux_module/palacios-vnet-brg.c @@ -162,7 +162,12 @@ static uint32_t _create_link(struct vnet_link * link) { if (link->sock_proto == UDP) { // no UDP checksumming lock_sock(link->sock->sk); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) link->sock->sk->sk_no_check = 1; +#else + link->sock->sk->sk_no_check_tx = 1; + link->sock->sk->sk_no_check_rx = 1; +#endif release_sock(link->sock->sk); } @@ -258,8 +263,12 @@ _udp_send(struct socket * sock, msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),WRITE,&iov,1,0); +#endif msg.msg_control = NULL; oldfs = get_fs(); @@ -293,8 +302,12 @@ _udp_recv(struct socket * sock, msg.msg_namelen = sizeof(struct sockaddr_in); msg.msg_control = NULL; msg.msg_controllen = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) msg.msg_iov = &iov; msg.msg_iovlen = 1; +#else + iov_iter_init(&(msg.msg_iter),READ,&iov,1,0); +#endif msg.msg_control = NULL; oldfs = get_fs(); @@ -403,7 +416,12 @@ static int init_vnet_serv(void) { if (vnet_brg_s.serv_proto == UDP) { // No UDP checksumming is done lock_sock(vnet_brg_s.serv_sock->sk); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0) vnet_brg_s.serv_sock->sk->sk_no_check = 1; +#else + vnet_brg_s.serv_sock->sk->sk_no_check_tx = 1; + vnet_brg_s.serv_sock->sk->sk_no_check_rx = 1; +#endif release_sock(vnet_brg_s.serv_sock->sk); } diff --git a/linux_module/palacios-vnet-ctrl.c b/linux_module/palacios-vnet-ctrl.c index 86ec129..6dae6bb 100644 --- a/linux_module/palacios-vnet-ctrl.c +++ b/linux_module/palacios-vnet-ctrl.c @@ -925,34 +925,33 @@ static int init_proc_files(void) { return -1; } - route_entry = create_proc_entry("routes", 0644, vnet_root); + + PAL_PROC_CREATE(route_entry,"routes",0644, vnet_root,&route_fops); + if (route_entry == NULL) { remove_proc_entry("vnet", NULL); return -1; } - route_entry->proc_fops = &route_fops; + PAL_PROC_CREATE(link_entry,"links", 0644, vnet_root,&link_fops); - link_entry = create_proc_entry("links", 0644, vnet_root); if (link_entry == NULL) { remove_proc_entry("routes", vnet_root); remove_proc_entry("vnet", NULL); return -1; } - link_entry->proc_fops = &link_fops; - - stat_entry = create_proc_entry("stats", 0644, vnet_root); + PAL_PROC_CREATE(stat_entry,"stats", 0644, vnet_root, &stat_fops); + if(stat_entry == NULL) { remove_proc_entry("links", vnet_root); remove_proc_entry("routes", vnet_root); remove_proc_entry("vnet", NULL); return -1; } - stat_entry->proc_fops = &stat_fops; + PAL_PROC_CREATE(debug_entry,"debug", 0644, vnet_root,&debug_fops); - debug_entry = create_proc_entry("debug", 0644, vnet_root); if(debug_entry == NULL) { remove_proc_entry("links", vnet_root); remove_proc_entry("routes", vnet_root); @@ -960,7 +959,6 @@ static int init_proc_files(void) { remove_proc_entry("vnet", NULL); return -1; } - debug_entry->proc_fops = &debug_fops; vnet_ctrl_s.vnet_proc_root = vnet_root; diff --git a/linux_module/palacios.h b/linux_module/palacios.h index 4694637..fc406bf 100644 --- a/linux_module/palacios.h +++ b/linux_module/palacios.h @@ -260,6 +260,10 @@ void palacios_mutex_unlock_irqrestore(void *mutex, void *flags); #endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(3,9,0) +#define strict_strtoull(s,b,r) kstrtoull(s,b,r) +#endif + #endif diff --git a/palacios/src/gears/ext_syscall_hijack.c b/palacios/src/gears/ext_syscall_hijack.c index 8e21769..c31bb59 100644 --- a/palacios/src/gears/ext_syscall_hijack.c +++ b/palacios/src/gears/ext_syscall_hijack.c @@ -133,6 +133,7 @@ int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_da if (list_empty(&(injects->code_inject_list))) { return 0; } else { + int ret; inject = (struct v3_code_inject_info*) list_first_entry( &(injects->code_inject_list),