fork: copy_user_ranges: rollback on error

Change-Id: Icdb8399cbce31835abcaeb783dde3ff14d30af6a
This commit is contained in:
TOIDA,Suguru
2019-08-20 13:21:34 +09:00
committed by Masamichi Takagi
parent 58f4593478
commit 3e9fdfc0f1

View File

@ -1,4 +1,4 @@
/* process.c COPYRIGHT FUJITSU LIMITED 2015-2018 */
/* process.c COPYRIGHT FUJITSU LIMITED 2015-2019 */
/**
* \file process.c
* License details are found in the file LICENSE.
@ -82,6 +82,9 @@ int ptrace_detach(int pid, int data);
extern void procfs_create_thread(struct thread *);
extern void procfs_delete_thread(struct thread *);
static int free_process_memory_range(struct process_vm *vm,
struct vm_range *range);
struct list_head resource_set_list;
mcs_rwlock_lock_t resource_set_lock;
ihk_spinlock_t runq_reservation_lock;
@ -740,12 +743,14 @@ static int copy_user_ranges(struct process_vm *vm, struct process_vm *orgvm)
int error;
struct vm_range *src_range;
struct vm_range *range;
struct vm_range *last_insert;
struct copy_args args;
unsigned long irqflags;
memory_range_write_lock(orgvm, &irqflags);
/* Iterate original process' vm_range list and take a copy one-by-one */
last_insert = NULL;
src_range = NULL;
for (;;) {
if (!src_range) {
@ -778,6 +783,9 @@ static int copy_user_ranges(struct process_vm *vm, struct process_vm *orgvm)
memobj_ref(range->memobj);
}
vm_range_insert(vm, range);
last_insert = src_range;
/* Copy actual mappings */
args.new_vrflag = range->flag;
args.new_vm = vm;
@ -796,27 +804,39 @@ static int copy_user_ranges(struct process_vm *vm, struct process_vm *orgvm)
range->start, range->end,
range->flag, args.fault_addr);
}
goto err_free_range_rollback;
goto err_rollback;
}
// memory_stat_rss_add() is called in child-node, i.e. copy_user_pte()
vm_range_insert(vm, range);
}
memory_range_write_unlock(orgvm, &irqflags);
return 0;
err_free_range_rollback:
kfree(range);
err_rollback:
if (last_insert) {
src_range = lookup_process_memory_range(orgvm, 0, -1);
while (src_range) {
struct vm_range *dest_range;
/* TODO: implement rollback */
if (src_range->flag & VR_DONTFORK)
continue;
dest_range = lookup_process_memory_range(vm,
src_range->start,
src_range->end);
if (dest_range) {
free_process_memory_range(vm, dest_range);
}
if (src_range == last_insert) {
break;
}
src_range = next_process_memory_range(orgvm, src_range);
}
}
memory_range_write_unlock(orgvm, &irqflags);
return -1;
}
@ -953,7 +973,8 @@ out:
return error;
}
int free_process_memory_range(struct process_vm *vm, struct vm_range *range)
static int free_process_memory_range(struct process_vm *vm,
struct vm_range *range)
{
const intptr_t start0 = range->start;
const intptr_t end0 = range->end;