fork: clone_thread: free resources when an error is detected
Change-Id: I922f3fddc35942ef2c67db6673980770731dced9
This commit is contained in:
committed by
Masamichi Takagi
parent
3e9fdfc0f1
commit
bb08742467
@ -832,6 +832,7 @@ void hold_process_vm(struct process_vm *vm);
|
|||||||
void release_process_vm(struct process_vm *vm);
|
void release_process_vm(struct process_vm *vm);
|
||||||
void hold_process(struct process *);
|
void hold_process(struct process *);
|
||||||
void release_process(struct process *);
|
void release_process(struct process *);
|
||||||
|
void free_all_process_memory_range(struct process_vm *vm);
|
||||||
void free_process_memory_ranges(struct process_vm *vm);
|
void free_process_memory_ranges(struct process_vm *vm);
|
||||||
int populate_process_memory(struct process_vm *vm, void *start, size_t len);
|
int populate_process_memory(struct process_vm *vm, void *start, size_t len);
|
||||||
|
|
||||||
|
|||||||
@ -84,6 +84,7 @@ extern void procfs_delete_thread(struct thread *);
|
|||||||
|
|
||||||
static int free_process_memory_range(struct process_vm *vm,
|
static int free_process_memory_range(struct process_vm *vm,
|
||||||
struct vm_range *range);
|
struct vm_range *range);
|
||||||
|
static void free_thread_pages(struct thread *thread);
|
||||||
|
|
||||||
struct list_head resource_set_list;
|
struct list_head resource_set_list;
|
||||||
mcs_rwlock_lock_t resource_set_lock;
|
mcs_rwlock_lock_t resource_set_lock;
|
||||||
@ -407,8 +408,12 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
|||||||
KERNEL_STACK_NR_PAGES * PAGE_SIZE, pc, sp);
|
KERNEL_STACK_NR_PAGES * PAGE_SIZE, pc, sp);
|
||||||
|
|
||||||
/* copy fp_regs from parent */
|
/* copy fp_regs from parent */
|
||||||
save_fp_regs(org);
|
if (save_fp_regs(org)) {
|
||||||
copy_fp_regs(org, thread);
|
goto free_thread;
|
||||||
|
}
|
||||||
|
if (copy_fp_regs(org, thread)) {
|
||||||
|
goto free_fp_regs;
|
||||||
|
}
|
||||||
arch_clone_thread(org, pc, sp, thread);
|
arch_clone_thread(org, pc, sp, thread);
|
||||||
|
|
||||||
memcpy(thread->uctx, org->uctx, sizeof(*org->uctx));
|
memcpy(thread->uctx, org->uctx, sizeof(*org->uctx));
|
||||||
@ -432,24 +437,20 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
|||||||
else {
|
else {
|
||||||
proc = kmalloc(sizeof(struct process), IHK_MC_AP_NOWAIT);
|
proc = kmalloc(sizeof(struct process), IHK_MC_AP_NOWAIT);
|
||||||
if(!proc)
|
if(!proc)
|
||||||
goto err_free_proc;
|
goto free_fp_regs;
|
||||||
memset(proc, '\0', sizeof(struct process));
|
memset(proc, '\0', sizeof(struct process));
|
||||||
init_process(proc, org->proc);
|
init_process(proc, org->proc);
|
||||||
#ifdef PROFILE_ENABLE
|
#ifdef PROFILE_ENABLE
|
||||||
proc->profile = org->proc->profile;
|
proc->profile = org->proc->profile;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
proc->termsig = termsig;
|
proc->termsig = termsig;
|
||||||
asp = create_address_space(cpu_local_var(resource_set), 1);
|
asp = create_address_space(cpu_local_var(resource_set), 1);
|
||||||
if (!asp) {
|
if (!asp) {
|
||||||
kfree(proc);
|
goto free_fork_process_proc;
|
||||||
goto err_free_proc;
|
|
||||||
}
|
}
|
||||||
proc->vm = kmalloc(sizeof(struct process_vm), IHK_MC_AP_NOWAIT);
|
proc->vm = kmalloc(sizeof(struct process_vm), IHK_MC_AP_NOWAIT);
|
||||||
if (!proc->vm) {
|
if (!proc->vm) {
|
||||||
release_address_space(asp);
|
goto free_fork_process_asp;
|
||||||
kfree(proc);
|
|
||||||
goto err_free_proc;
|
|
||||||
}
|
}
|
||||||
memset(proc->vm, '\0', sizeof(struct process_vm));
|
memset(proc->vm, '\0', sizeof(struct process_vm));
|
||||||
|
|
||||||
@ -457,20 +458,14 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
|||||||
proc->saved_cmdline = kmalloc(proc->saved_cmdline_len,
|
proc->saved_cmdline = kmalloc(proc->saved_cmdline_len,
|
||||||
IHK_MC_AP_NOWAIT);
|
IHK_MC_AP_NOWAIT);
|
||||||
if (!proc->saved_cmdline) {
|
if (!proc->saved_cmdline) {
|
||||||
release_address_space(asp);
|
goto free_fork_process_vm;
|
||||||
kfree(proc->vm);
|
|
||||||
kfree(proc);
|
|
||||||
goto err_free_proc;
|
|
||||||
}
|
}
|
||||||
memcpy(proc->saved_cmdline, org->proc->saved_cmdline,
|
memcpy(proc->saved_cmdline, org->proc->saved_cmdline,
|
||||||
proc->saved_cmdline_len);
|
proc->saved_cmdline_len);
|
||||||
|
|
||||||
dkprintf("fork(): init_process_vm()\n");
|
dkprintf("fork(): init_process_vm()\n");
|
||||||
if (init_process_vm(proc, asp, proc->vm) != 0) {
|
if (init_process_vm(proc, asp, proc->vm) != 0) {
|
||||||
release_address_space(asp);
|
goto free_fork_process_cmdline;
|
||||||
kfree(proc->vm);
|
|
||||||
kfree(proc);
|
|
||||||
goto err_free_proc;
|
|
||||||
}
|
}
|
||||||
memcpy(&proc->vm->numa_mask, &org->vm->numa_mask,
|
memcpy(&proc->vm->numa_mask, &org->vm->numa_mask,
|
||||||
sizeof(proc->vm->numa_mask));
|
sizeof(proc->vm->numa_mask));
|
||||||
@ -488,11 +483,8 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
|||||||
* TODO: do this with COW later? */
|
* TODO: do this with COW later? */
|
||||||
v->on_fork_vm = proc->vm;
|
v->on_fork_vm = proc->vm;
|
||||||
if (copy_user_ranges(proc->vm, org->vm) != 0) {
|
if (copy_user_ranges(proc->vm, org->vm) != 0) {
|
||||||
release_address_space(asp);
|
|
||||||
v->on_fork_vm = NULL;
|
v->on_fork_vm = NULL;
|
||||||
kfree(proc->vm);
|
goto free_fork_process_cmdline;
|
||||||
kfree(proc);
|
|
||||||
goto err_free_proc;
|
|
||||||
}
|
}
|
||||||
v->on_fork_vm = NULL;
|
v->on_fork_vm = NULL;
|
||||||
|
|
||||||
@ -503,10 +495,9 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
|||||||
for (cur = org->proc->mckfd; cur; cur = cur->next) {
|
for (cur = org->proc->mckfd; cur; cur = cur->next) {
|
||||||
struct mckfd *mckfd = kmalloc(sizeof(struct mckfd), IHK_MC_AP_NOWAIT);
|
struct mckfd *mckfd = kmalloc(sizeof(struct mckfd), IHK_MC_AP_NOWAIT);
|
||||||
if(!mckfd) {
|
if(!mckfd) {
|
||||||
release_address_space(asp);
|
ihk_mc_spinlock_unlock(&proc->mckfd_lock,
|
||||||
kfree(proc->vm);
|
irqstate);
|
||||||
kfree(proc);
|
goto free_fork_process_mckfd;
|
||||||
goto err_free_proc;
|
|
||||||
}
|
}
|
||||||
memcpy(mckfd, cur, sizeof(struct mckfd));
|
memcpy(mckfd, cur, sizeof(struct mckfd));
|
||||||
|
|
||||||
@ -546,7 +537,10 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
|||||||
thread->sigcommon = kmalloc(sizeof(struct sig_common),
|
thread->sigcommon = kmalloc(sizeof(struct sig_common),
|
||||||
IHK_MC_AP_NOWAIT);
|
IHK_MC_AP_NOWAIT);
|
||||||
if (!thread->sigcommon) {
|
if (!thread->sigcommon) {
|
||||||
goto err_free_proc;
|
if (clone_flags & CLONE_VM) {
|
||||||
|
goto free_clone_process;
|
||||||
|
}
|
||||||
|
goto free_fork_process_mckfd;
|
||||||
}
|
}
|
||||||
memset(thread->sigcommon, '\0', sizeof(struct sig_common));
|
memset(thread->sigcommon, '\0', sizeof(struct sig_common));
|
||||||
|
|
||||||
@ -572,8 +566,52 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp,
|
|||||||
|
|
||||||
return thread;
|
return thread;
|
||||||
|
|
||||||
err_free_proc:
|
/*
|
||||||
ihk_mc_free_pages(thread, KERNEL_STACK_NR_PAGES);
|
* free process(clone)
|
||||||
|
* case of (clone_flags & CLONE_VM)
|
||||||
|
*/
|
||||||
|
free_clone_process:
|
||||||
|
goto free_fp_regs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free process(fork)
|
||||||
|
* case of !(clone_flags & CLONE_VM)
|
||||||
|
*/
|
||||||
|
free_fork_process_mckfd:
|
||||||
|
{
|
||||||
|
long irqstate = ihk_mc_spinlock_lock(&proc->mckfd_lock);
|
||||||
|
struct mckfd *cur = proc->mckfd;
|
||||||
|
|
||||||
|
while (cur) {
|
||||||
|
struct mckfd *next = cur->next;
|
||||||
|
|
||||||
|
kfree(cur);
|
||||||
|
cur = next;
|
||||||
|
}
|
||||||
|
ihk_mc_spinlock_unlock(&proc->mckfd_lock, irqstate);
|
||||||
|
}
|
||||||
|
free_all_process_memory_range(proc->vm);
|
||||||
|
free_fork_process_cmdline:
|
||||||
|
kfree(proc->saved_cmdline);
|
||||||
|
free_fork_process_vm:
|
||||||
|
kfree(proc->vm);
|
||||||
|
free_fork_process_asp:
|
||||||
|
ihk_mc_pt_destroy(asp->page_table);
|
||||||
|
kfree(asp);
|
||||||
|
free_fork_process_proc:
|
||||||
|
kfree(proc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free fp_regs
|
||||||
|
*/
|
||||||
|
free_fp_regs:
|
||||||
|
release_fp_regs(thread);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* free thread
|
||||||
|
*/
|
||||||
|
free_thread:
|
||||||
|
free_thread_pages(thread);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/* syscall.c COPYRIGHT FUJITSU LIMITED 2015-2018 */
|
/* syscall.c COPYRIGHT FUJITSU LIMITED 2015-2019 */
|
||||||
/**
|
/**
|
||||||
* \file syscall.c
|
* \file syscall.c
|
||||||
* License details are found in the file LICENSE.
|
* License details are found in the file LICENSE.
|
||||||
@ -120,7 +120,6 @@ extern int num_processors;
|
|||||||
extern unsigned long ihk_mc_get_ns_per_tsc(void);
|
extern unsigned long ihk_mc_get_ns_per_tsc(void);
|
||||||
extern int ptrace_detach(int pid, int data);
|
extern int ptrace_detach(int pid, int data);
|
||||||
extern void debug_log(unsigned long);
|
extern void debug_log(unsigned long);
|
||||||
extern void free_all_process_memory_range(struct process_vm *vm);
|
|
||||||
extern int arch_clear_host_user_space();
|
extern int arch_clear_host_user_space();
|
||||||
extern long arch_ptrace(long request, int pid, long addr, long data);
|
extern long arch_ptrace(long request, int pid, long addr, long data);
|
||||||
extern struct cpu_local_var *clv;
|
extern struct cpu_local_var *clv;
|
||||||
|
|||||||
Reference in New Issue
Block a user