xpmem: Make sure vm_range is used under memory_range_lock
Change-Id: I856ee9d401e7dcfd74559bad5b22a69d53a61e2f
This commit is contained in:
committed by
Masamichi Takagi
parent
4ac9dcdccd
commit
5dd989450d
@ -331,6 +331,7 @@ static void xpmem_ap_deref(struct xpmem_access_permit *ap);
|
|||||||
static void xpmem_att_deref(struct xpmem_attachment *att);
|
static void xpmem_att_deref(struct xpmem_attachment *att);
|
||||||
static int xpmem_validate_access(struct xpmem_access_permit *, off_t, size_t,
|
static int xpmem_validate_access(struct xpmem_access_permit *, off_t, size_t,
|
||||||
int, unsigned long *);
|
int, unsigned long *);
|
||||||
|
static int is_remote_vm(struct process_vm *vm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inlines that mark an internal driver structure as being destroyable or not.
|
* Inlines that mark an internal driver structure as being destroyable or not.
|
||||||
|
|||||||
@ -1119,16 +1119,18 @@ static int xpmem_attach(
|
|||||||
existing_vmr = lookup_process_memory_range(vm, vaddr,
|
existing_vmr = lookup_process_memory_range(vm, vaddr,
|
||||||
vaddr + size);
|
vaddr + size);
|
||||||
|
|
||||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
|
||||||
|
|
||||||
for (; existing_vmr && existing_vmr->start < vaddr + size;
|
for (; existing_vmr && existing_vmr->start < vaddr + size;
|
||||||
existing_vmr = next_process_memory_range(vm,
|
existing_vmr = next_process_memory_range(vm,
|
||||||
existing_vmr)) {
|
existing_vmr)) {
|
||||||
if (xpmem_is_private_data(existing_vmr)) {
|
if (xpmem_is_private_data(existing_vmr)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
ihk_rwspinlock_read_unlock_noirq(
|
||||||
|
&vm->memory_range_lock);
|
||||||
goto out_2;
|
goto out_2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
flags |= MAP_ANONYMOUS;
|
flags |= MAP_ANONYMOUS;
|
||||||
@ -1423,20 +1425,18 @@ static void xpmem_detach_att(
|
|||||||
|
|
||||||
XPMEM_DEBUG("detaching att->vm=0x%p", (void *)att->vm);
|
XPMEM_DEBUG("detaching att->vm=0x%p", (void *)att->vm);
|
||||||
|
|
||||||
vm = att->vm;
|
|
||||||
|
|
||||||
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
|
|
||||||
|
|
||||||
mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
|
mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
|
||||||
|
|
||||||
if (att->flags & XPMEM_FLAG_DESTROYING) {
|
if (att->flags & XPMEM_FLAG_DESTROYING) {
|
||||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
||||||
ihk_rwspinlock_read_unlock_noirq(&vm->memory_range_lock);
|
|
||||||
XPMEM_DEBUG("return: XPMEM_FLAG_DESTROYING");
|
XPMEM_DEBUG("return: XPMEM_FLAG_DESTROYING");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
att->flags |= XPMEM_FLAG_DESTROYING;
|
att->flags |= XPMEM_FLAG_DESTROYING;
|
||||||
|
|
||||||
|
vm = att->vm;
|
||||||
|
ihk_rwspinlock_read_lock_noirq(&vm->memory_range_lock);
|
||||||
|
|
||||||
range = lookup_process_memory_range(vm,
|
range = lookup_process_memory_range(vm,
|
||||||
att->at_vaddr, att->at_vaddr + 1);
|
att->at_vaddr, att->at_vaddr + 1);
|
||||||
|
|
||||||
@ -1676,10 +1676,8 @@ int xpmem_remove_process_memory_range(
|
|||||||
mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
|
mcs_rwlock_writer_lock(&att->at_lock, &at_lock);
|
||||||
|
|
||||||
if (att->flags & XPMEM_FLAG_DESTROYING) {
|
if (att->flags & XPMEM_FLAG_DESTROYING) {
|
||||||
mcs_rwlock_writer_unlock(&att->at_lock, &at_lock);
|
|
||||||
xpmem_att_deref(att);
|
|
||||||
XPMEM_DEBUG("already cleaned up");
|
XPMEM_DEBUG("already cleaned up");
|
||||||
return 0;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vmr->start == att->at_vaddr &&
|
if (vmr->start == att->at_vaddr &&
|
||||||
@ -1910,13 +1908,13 @@ static int xpmem_remap_pte(
|
|||||||
"seg_vaddr=0x%lx",
|
"seg_vaddr=0x%lx",
|
||||||
vmr, vaddr, reason, seg->segid, seg_vaddr);
|
vmr, vaddr, reason, seg->segid, seg_vaddr);
|
||||||
|
|
||||||
ihk_rwspinlock_read_lock_noirq(&seg_tg->vm->memory_range_lock);
|
if (is_remote_vm(seg_tg->vm)) {
|
||||||
|
ihk_rwspinlock_read_lock_noirq(&seg_tg->vm->memory_range_lock);
|
||||||
|
}
|
||||||
|
|
||||||
seg_vmr = lookup_process_memory_range(seg_tg->vm, seg_vaddr,
|
seg_vmr = lookup_process_memory_range(seg_tg->vm, seg_vaddr,
|
||||||
seg_vaddr + 1);
|
seg_vaddr + 1);
|
||||||
|
|
||||||
ihk_rwspinlock_read_unlock_noirq(&seg_tg->vm->memory_range_lock);
|
|
||||||
|
|
||||||
if (!seg_vmr) {
|
if (!seg_vmr) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
ekprintf("%s: ERROR: lookup_process_memory_range() failed\n",
|
ekprintf("%s: ERROR: lookup_process_memory_range() failed\n",
|
||||||
@ -1989,6 +1987,10 @@ static int xpmem_remap_pte(
|
|||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
if (is_remote_vm(seg_tg->vm)) {
|
||||||
|
ihk_rwspinlock_read_unlock_noirq(&seg_tg->vm->memory_range_lock);
|
||||||
|
}
|
||||||
|
|
||||||
XPMEM_DEBUG("return: ret=%d", ret);
|
XPMEM_DEBUG("return: ret=%d", ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -2336,3 +2338,14 @@ static int xpmem_validate_access(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_remote_vm(struct process_vm *vm)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (cpu_local_var(current)->proc->vm != vm) {
|
||||||
|
/* vm is not mine */
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user