support madvise(MADV_REMOVE) partially

This MADV_REMOVE works with a mapping which is
- created with shmat() and
- not sharing memobj with other mappings.
This commit is contained in:
NAKAMURA Gou
2015-10-28 18:40:18 +09:00
parent c25f8c7a39
commit 0b07dd1b79
3 changed files with 71 additions and 5 deletions

View File

@@ -31,6 +31,7 @@ enum {
/* for memobj.flags */
MF_HAS_PAGER = 0x0001,
MF_SHMDT_OK = 0x0002,
MF_IS_REMOVABLE = 0x0004,
};
struct memobj {
@@ -120,6 +121,11 @@ static inline int memobj_has_pager(struct memobj *obj)
return !!(obj->flags & MF_HAS_PAGER);
}
static inline int memobj_is_removable(struct memobj *obj)
{
return !!(obj->flags & MF_IS_REMOVABLE);
}
int fileobj_create(int fd, struct memobj **objp, int *maxprotp);
struct shmid_ds;
int shmobj_create(struct shmid_ds *ds, struct memobj **objp);

View File

@@ -33,11 +33,13 @@ static ihk_spinlock_t shmobj_list_lock_body = SPIN_LOCK_UNLOCKED;
static memobj_release_func_t shmobj_release;
static memobj_ref_func_t shmobj_ref;
static memobj_get_page_func_t shmobj_get_page;
static memobj_invalidate_page_func_t shmobj_invalidate_page;
static struct memobj_ops shmobj_ops = {
.release = &shmobj_release,
.ref = &shmobj_ref,
.get_page = &shmobj_get_page,
.invalidate_page = &shmobj_invalidate_page,
};
static struct shmobj *to_shmobj(struct memobj *memobj)
@@ -158,7 +160,7 @@ int shmobj_create_indexed(struct shmid_ds *ds, struct shmobj **objp)
error = shmobj_create(ds, &obj);
if (!error) {
obj->flags |= MF_SHMDT_OK;
obj->flags |= MF_SHMDT_OK | MF_IS_REMOVABLE;
*objp = to_shmobj(obj);
}
return error;
@@ -369,3 +371,30 @@ out:
memobj, off, p2align, physp, error);
return error;
}
static int shmobj_invalidate_page(struct memobj *memobj, uintptr_t phys,
size_t pgsize)
{
struct shmobj *obj = to_shmobj(memobj);
int error;
struct page *page;
dkprintf("shmobj_invalidate_page(%p,%#lx,%#lx)\n", memobj, phys, pgsize);
if (!(page = phys_to_page(phys))
|| !(page = page_list_lookup(obj, page->offset))) {
error = 0;
goto out;
}
if (ihk_atomic_read(&page->count) == 1) {
if (page_unmap(page)) {
ihk_mc_free_pages(phys_to_virt(phys), pgsize/PAGE_SIZE);
}
}
error = 0;
out:
dkprintf("shmobj_invalidate_page(%p,%#lx,%#lx):%d\n", memobj, phys, pgsize, error);
return error;
}

View File

@@ -2691,6 +2691,8 @@ SYSCALL_DECLARE(madvise)
uintptr_t addr;
struct vm_range *range;
int error;
uintptr_t s;
uintptr_t e;
dkprintf("[%d]sys_madvise(%lx,%lx,%x)\n",
ihk_mc_get_processor_id(), start, len0, advice);
@@ -2732,10 +2734,7 @@ SYSCALL_DECLARE(madvise)
case MADV_DONTNEED:
case MADV_DONTFORK:
case MADV_DOFORK:
break;
case MADV_REMOVE:
error = -EACCES;
break;
case MADV_HWPOISON:
@@ -2777,7 +2776,17 @@ SYSCALL_DECLARE(madvise)
goto out;
}
if (!range->memobj || !memobj_has_pager(range->memobj)) {
if (advice == MADV_REMOVE) {
if (!range->memobj || !memobj_is_removable(range->memobj)) {
dkprintf("sys_madvise(%lx,%lx,%x):"
"not removable [%lx-%lx)\n",
start, len0, advice,
range->start, range->end);
error = -EACCES;
goto out;
}
}
else if (!range->memobj || !memobj_has_pager(range->memobj)) {
dkprintf("[%d]sys_madvise(%lx,%lx,%x):has not pager"
"[%lx-%lx) %lx\n",
ihk_mc_get_processor_id(), start,
@@ -2797,6 +2806,28 @@ SYSCALL_DECLARE(madvise)
error = -EINVAL;
goto out;
}
s = start;
if (s < range->start) {
s = range->start;
}
e = end;
if (range->end < e) {
e = range->end;
}
if (advice == MADV_REMOVE) {
error = invalidate_process_memory_range(
thread->vm, range, s, e);
if (error) {
kprintf("sys_madvise(%lx,%lx,%x):[%lx-%lx):"
"invalidate failed. %d\n",
start, len0, advice,
range->start, range->end,
error);
goto out;
}
}
}
error = 0;