mcctrl procfs: use semaphores instead of spinlocks to avoid sleeping in GFP_KERNEL kmalloc() in atomic context

This commit is contained in:
Balazs Gerofi
2016-08-01 20:33:51 +09:00
parent c484f766fa
commit dac6f2883e
2 changed files with 22 additions and 27 deletions

View File

@@ -32,6 +32,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/file.h> #include <linux/file.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/semaphore.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/delay.h> #include <asm/delay.h>
#include <asm/io.h> #include <asm/io.h>
@@ -802,7 +803,7 @@ long mcexec_ret_syscall(ihk_os_t os, struct syscall_ret_desc *__user arg)
} }
LIST_HEAD(mckernel_exec_files); LIST_HEAD(mckernel_exec_files);
DEFINE_SPINLOCK(mckernel_exec_file_lock); DEFINE_SEMAPHORE(mckernel_exec_file_lock);
struct mckernel_exec_file { struct mckernel_exec_file {
@@ -889,7 +890,7 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
goto out_put_file; goto out_put_file;
} }
spin_lock_irq(&mckernel_exec_file_lock); down(&mckernel_exec_file_lock);
/* Find previous file (if exists) and drop it */ /* Find previous file (if exists) and drop it */
list_for_each_entry(mcef_iter, &mckernel_exec_files, list) { list_for_each_entry(mcef_iter, &mckernel_exec_files, list) {
if (mcef_iter->os == os && mcef_iter->pid == task_tgid_vnr(current)) { if (mcef_iter->os == os && mcef_iter->pid == task_tgid_vnr(current)) {
@@ -910,7 +911,7 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
/* Create /proc/self/exe entry */ /* Create /proc/self/exe entry */
add_pid_entry(os_ind, task_tgid_vnr(current)); add_pid_entry(os_ind, task_tgid_vnr(current));
proc_exe_link(os_ind, task_tgid_vnr(current), fullpath); proc_exe_link(os_ind, task_tgid_vnr(current), fullpath);
spin_unlock(&mckernel_exec_file_lock); up(&mckernel_exec_file_lock);
dprintk("%d open_exec and holding file: %s\n", (int)task_tgid_vnr(current), filename); dprintk("%d open_exec and holding file: %s\n", (int)task_tgid_vnr(current), filename);
@@ -937,7 +938,7 @@ int mcexec_close_exec(ihk_os_t os)
return EINVAL; return EINVAL;
} }
spin_lock_irq(&mckernel_exec_file_lock); down(&mckernel_exec_file_lock);
list_for_each_entry(mcef, &mckernel_exec_files, list) { list_for_each_entry(mcef, &mckernel_exec_files, list) {
if (mcef->os == os && mcef->pid == task_tgid_vnr(current)) { if (mcef->os == os && mcef->pid == task_tgid_vnr(current)) {
allow_write_access(mcef->fp); allow_write_access(mcef->fp);
@@ -950,7 +951,7 @@ int mcexec_close_exec(ihk_os_t os)
} }
} }
spin_unlock(&mckernel_exec_file_lock); up(&mckernel_exec_file_lock);
return (found ? 0 : EINVAL); return (found ? 0 : EINVAL);
} }

View File

@@ -19,6 +19,7 @@
#include <linux/resource.h> #include <linux/resource.h>
#include "mcctrl.h" #include "mcctrl.h"
#include <linux/version.h> #include <linux/version.h>
#include <linux/semaphore.h>
//#define PROCFS_DEBUG //#define PROCFS_DEBUG
@@ -81,7 +82,7 @@ struct procfs_list_entry {
* file. * file.
*/ */
LIST_HEAD(procfs_file_list); LIST_HEAD(procfs_file_list);
static ihk_spinlock_t procfs_file_list_lock; DEFINE_SEMAPHORE(procfs_file_list_lock);
static char * static char *
getpath(struct procfs_list_entry *e, char *buf, int bufsize) getpath(struct procfs_list_entry *e, char *buf, int bufsize)
@@ -375,67 +376,62 @@ _add_tid_entry(int osnum, int pid, int tid, const struct cred *cred)
void void
add_tid_entry(int osnum, int pid, int tid) add_tid_entry(int osnum, int pid, int tid)
{ {
unsigned long irqflag;
const struct cred *cred = get_pid_cred(pid); const struct cred *cred = get_pid_cred(pid);
if(!cred) if(!cred)
return; return;
irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); down(&procfs_file_list_lock);
_add_tid_entry(osnum, pid, tid, cred); _add_tid_entry(osnum, pid, tid, cred);
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); up(&procfs_file_list_lock);
} }
void void
add_pid_entry(int osnum, int pid) add_pid_entry(int osnum, int pid)
{ {
struct procfs_list_entry *parent; struct procfs_list_entry *parent;
unsigned long irqflag;
const struct cred *cred = get_pid_cred(pid); const struct cred *cred = get_pid_cred(pid);
if(!cred) if(!cred)
return; return;
irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); down(&procfs_file_list_lock);
parent = get_pid_entry(osnum, pid); parent = get_pid_entry(osnum, pid);
add_procfs_entries(parent, pid_entry_stuff, cred->uid, cred->gid); add_procfs_entries(parent, pid_entry_stuff, cred->uid, cred->gid);
_add_tid_entry(osnum, pid, pid, cred); _add_tid_entry(osnum, pid, pid, cred);
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); up(&procfs_file_list_lock);
} }
void void
delete_tid_entry(int osnum, int pid, int tid) delete_tid_entry(int osnum, int pid, int tid)
{ {
unsigned long irqflag;
struct procfs_list_entry *e; struct procfs_list_entry *e;
irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); down(&procfs_file_list_lock);
e = find_tid_entry(osnum, pid, tid); e = find_tid_entry(osnum, pid, tid);
if(e) if(e)
delete_procfs_entries(e); delete_procfs_entries(e);
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); up(&procfs_file_list_lock);
} }
void void
delete_pid_entry(int osnum, int pid) delete_pid_entry(int osnum, int pid)
{ {
unsigned long irqflag;
struct procfs_list_entry *e; struct procfs_list_entry *e;
irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); down(&procfs_file_list_lock);
e = find_pid_entry(osnum, pid); e = find_pid_entry(osnum, pid);
if(e) if(e)
delete_procfs_entries(e); delete_procfs_entries(e);
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); up(&procfs_file_list_lock);
} }
void void
proc_exe_link(int osnum, int pid, const char *path) proc_exe_link(int osnum, int pid, const char *path)
{ {
struct procfs_list_entry *parent; struct procfs_list_entry *parent;
unsigned long irqflag;
kuid_t uid = KUIDT_INIT(0); kuid_t uid = KUIDT_INIT(0);
kgid_t gid = KGIDT_INIT(0); kgid_t gid = KGIDT_INIT(0);
irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); down(&procfs_file_list_lock);
parent = find_pid_entry(osnum, pid); parent = find_pid_entry(osnum, pid);
if(parent){ if(parent){
struct procfs_list_entry *task; struct procfs_list_entry *task;
@@ -451,7 +447,7 @@ proc_exe_link(int osnum, int pid, const char *path)
uid, gid, path); uid, gid, path);
} }
} }
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); up(&procfs_file_list_lock);
} }
/** /**
@@ -463,14 +459,13 @@ void
procfs_init(int osnum) procfs_init(int osnum)
{ {
struct procfs_list_entry *parent; struct procfs_list_entry *parent;
unsigned long irqflag;
kuid_t uid = KUIDT_INIT(0); kuid_t uid = KUIDT_INIT(0);
kgid_t gid = KGIDT_INIT(0); kgid_t gid = KGIDT_INIT(0);
irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); down(&procfs_file_list_lock);
parent = get_base_entry(osnum); parent = get_base_entry(osnum);
add_procfs_entries(parent, base_entry_stuff, uid, gid); add_procfs_entries(parent, base_entry_stuff, uid, gid);
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); up(&procfs_file_list_lock);
} }
/** /**
@@ -481,14 +476,13 @@ procfs_init(int osnum)
void void
procfs_exit(int osnum) procfs_exit(int osnum)
{ {
unsigned long irqflag;
struct procfs_list_entry *e; struct procfs_list_entry *e;
irqflag = ihk_ikc_spinlock_lock(&procfs_file_list_lock); down(&procfs_file_list_lock);
e = find_base_entry(osnum); e = find_base_entry(osnum);
if(e) if(e)
delete_procfs_entries(e); delete_procfs_entries(e);
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflag); up(&procfs_file_list_lock);
} }
/** /**