fileobj: use MCS locks for per-file page hash

This commit is contained in:
Balazs Gerofi
2018-04-10 16:45:03 +09:00
parent aaa246f86f
commit 249bda4aef
2 changed files with 24 additions and 22 deletions

View File

@@ -134,6 +134,8 @@ typedef struct mcs_lock_node {
unsigned long irqsave; unsigned long irqsave;
} __attribute__((aligned(64))) mcs_lock_node_t; } __attribute__((aligned(64))) mcs_lock_node_t;
typedef mcs_lock_node_t mcs_lock_t;
static void mcs_lock_init(struct mcs_lock_node *node) static void mcs_lock_init(struct mcs_lock_node *node)
{ {
node->locked = 0; node->locked = 0;

View File

@@ -38,7 +38,7 @@
#define ekprintf(...) kprintf(__VA_ARGS__) #define ekprintf(...) kprintf(__VA_ARGS__)
#endif #endif
mcs_rwlock_lock_t fileobj_list_lock; mcs_lock_t fileobj_list_lock;
static LIST_HEAD(fileobj_list); static LIST_HEAD(fileobj_list);
#define FILEOBJ_PAGE_HASH_SHIFT 9 #define FILEOBJ_PAGE_HASH_SHIFT 9
@@ -52,7 +52,7 @@ struct fileobj {
uintptr_t handle; uintptr_t handle;
struct list_head list; struct list_head list;
struct list_head page_hash[FILEOBJ_PAGE_HASH_SIZE]; struct list_head page_hash[FILEOBJ_PAGE_HASH_SIZE];
mcs_rwlock_lock_t page_hash_locks[FILEOBJ_PAGE_HASH_SIZE]; mcs_lock_t page_hash_locks[FILEOBJ_PAGE_HASH_SIZE];
}; };
static memobj_release_func_t fileobj_release; static memobj_release_func_t fileobj_release;
@@ -89,7 +89,7 @@ static void fileobj_page_hash_init(struct fileobj *obj)
{ {
int i; int i;
for (i = 0; i < FILEOBJ_PAGE_HASH_SIZE; ++i) { for (i = 0; i < FILEOBJ_PAGE_HASH_SIZE; ++i) {
mcs_rwlock_init(&obj->page_hash_locks[i]); mcs_lock_init(&obj->page_hash_locks[i]);
INIT_LIST_HEAD(&obj->page_hash[i]); INIT_LIST_HEAD(&obj->page_hash[i]);
} }
return; return;
@@ -198,7 +198,7 @@ int fileobj_create(int fd, struct memobj **objp, int *maxprotp, uintptr_t virt_a
int error; int error;
struct fileobj *newobj = NULL; struct fileobj *newobj = NULL;
struct fileobj *obj; struct fileobj *obj;
struct mcs_rwlock_node node; struct mcs_lock_node node;
dkprintf("fileobj_create(%d)\n", fd); dkprintf("fileobj_create(%d)\n", fd);
newobj = kmalloc(sizeof(*newobj), IHK_MC_AP_NOWAIT); newobj = kmalloc(sizeof(*newobj), IHK_MC_AP_NOWAIT);
@@ -228,7 +228,7 @@ int fileobj_create(int fd, struct memobj **objp, int *maxprotp, uintptr_t virt_a
fileobj_page_hash_init(newobj); fileobj_page_hash_init(newobj);
ihk_mc_spinlock_init(&newobj->memobj.lock); ihk_mc_spinlock_init(&newobj->memobj.lock);
mcs_rwlock_writer_lock_noirq(&fileobj_list_lock, &node); mcs_lock_lock_noirq(&fileobj_list_lock, &node);
obj = obj_list_lookup(result.handle); obj = obj_list_lookup(result.handle);
if (!obj) { if (!obj) {
obj_list_insert(newobj); obj_list_insert(newobj);
@@ -308,7 +308,7 @@ error_cleanup:
to_memobj(obj)->flags & MF_ZEROFILL ? "zerofill" : ""); to_memobj(obj)->flags & MF_ZEROFILL ? "zerofill" : "");
} }
mcs_rwlock_writer_unlock_noirq(&fileobj_list_lock, &node); mcs_lock_unlock_noirq(&fileobj_list_lock, &node);
error = 0; error = 0;
*objp = to_memobj(obj); *objp = to_memobj(obj);
@@ -339,7 +339,7 @@ static void fileobj_release(struct memobj *memobj)
long free_sref = 0; long free_sref = 0;
uintptr_t free_handle; uintptr_t free_handle;
struct fileobj *free_obj = NULL; struct fileobj *free_obj = NULL;
struct mcs_rwlock_node node; struct mcs_lock_node node;
dkprintf("fileobj_release(%p %lx)\n", obj, obj->handle); dkprintf("fileobj_release(%p %lx)\n", obj, obj->handle);
@@ -364,7 +364,7 @@ static void fileobj_release(struct memobj *memobj)
obj->cref, obj->cref,
free_obj, free_obj,
to_memobj(obj)->flags & MF_ZEROFILL ? "zerofill" : ""); to_memobj(obj)->flags & MF_ZEROFILL ? "zerofill" : "");
mcs_rwlock_writer_lock_noirq(&fileobj_list_lock, &node); mcs_lock_lock_noirq(&fileobj_list_lock, &node);
/* zap page_list */ /* zap page_list */
for (;;) { for (;;) {
struct page *page; struct page *page;
@@ -435,7 +435,7 @@ static void fileobj_release(struct memobj *memobj)
} }
obj_list_remove(free_obj); obj_list_remove(free_obj);
mcs_rwlock_writer_unlock_noirq(&fileobj_list_lock, &node); mcs_lock_unlock_noirq(&fileobj_list_lock, &node);
kfree(free_obj); kfree(free_obj);
} }
@@ -481,10 +481,10 @@ static void fileobj_do_pageio(void *args0)
struct page *page; struct page *page;
ihk_mc_user_context_t ctx; ihk_mc_user_context_t ctx;
ssize_t ss; ssize_t ss;
struct mcs_rwlock_node mcs_node; struct mcs_lock_node mcs_node;
int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK; int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK;
mcs_rwlock_writer_lock_noirq(&obj->page_hash_locks[hash], mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
page = __fileobj_page_hash_lookup(obj, hash, off); page = __fileobj_page_hash_lookup(obj, hash, off);
if (!page) { if (!page) {
@@ -492,10 +492,10 @@ static void fileobj_do_pageio(void *args0)
} }
while (page->mode == PM_PAGEIO) { while (page->mode == PM_PAGEIO) {
mcs_rwlock_writer_unlock_noirq(&obj->page_hash_locks[hash], mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
cpu_pause(); cpu_pause();
mcs_rwlock_writer_lock_noirq(&obj->page_hash_locks[hash], mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
} }
@@ -509,7 +509,7 @@ static void fileobj_do_pageio(void *args0)
} }
else { else {
page->mode = PM_PAGEIO; page->mode = PM_PAGEIO;
mcs_rwlock_writer_unlock_noirq(&obj->page_hash_locks[hash], mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
ihk_mc_syscall_arg0(&ctx) = PAGER_REQ_READ; ihk_mc_syscall_arg0(&ctx) = PAGER_REQ_READ;
@@ -522,7 +522,7 @@ static void fileobj_do_pageio(void *args0)
__FUNCTION__, obj->handle); __FUNCTION__, obj->handle);
ss = syscall_generic_forwarding(__NR_mmap, &ctx); ss = syscall_generic_forwarding(__NR_mmap, &ctx);
mcs_rwlock_writer_lock_noirq(&obj->page_hash_locks[hash], mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
if (page->mode != PM_PAGEIO) { if (page->mode != PM_PAGEIO) {
kprintf("fileobj_do_pageio(%p,%lx,%lx):" kprintf("fileobj_do_pageio(%p,%lx,%lx):"
@@ -549,7 +549,7 @@ static void fileobj_do_pageio(void *args0)
page->mode = PM_DONE_PAGEIO; page->mode = PM_DONE_PAGEIO;
} }
out: out:
mcs_rwlock_writer_unlock_noirq(&obj->page_hash_locks[hash], mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
fileobj_release(&obj->memobj); /* got fileobj_get_page() */ fileobj_release(&obj->memobj); /* got fileobj_get_page() */
kfree(args0); kfree(args0);
@@ -568,7 +568,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
uintptr_t phys = -1; uintptr_t phys = -1;
struct page *page; struct page *page;
struct pageio_args *args = NULL; struct pageio_args *args = NULL;
struct mcs_rwlock_node mcs_node; struct mcs_lock_node mcs_node;
int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK; int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK;
dkprintf("fileobj_get_page(%p,%lx,%x,%x,%p)\n", obj, off, p2align, virt_addr, physp); dkprintf("fileobj_get_page(%p,%lx,%x,%x,%p)\n", obj, off, p2align, virt_addr, physp);
@@ -619,7 +619,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
goto out_nolock; goto out_nolock;
} }
mcs_rwlock_writer_lock_noirq(&obj->page_hash_locks[hash], mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
page = __fileobj_page_hash_lookup(obj, hash, off); page = __fileobj_page_hash_lookup(obj, hash, off);
if (!page || (page->mode == PM_WILL_PAGEIO) if (!page || (page->mode == PM_WILL_PAGEIO)
@@ -698,7 +698,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
*physp = page_to_phys(page); *physp = page_to_phys(page);
virt = NULL; virt = NULL;
out: out:
mcs_rwlock_writer_unlock_noirq(&obj->page_hash_locks[hash], mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
out_nolock: out_nolock:
if (virt) { if (virt) {
@@ -775,7 +775,7 @@ static int fileobj_lookup_page(struct memobj *memobj, off_t off,
struct fileobj *obj = to_fileobj(memobj); struct fileobj *obj = to_fileobj(memobj);
int error = -1; int error = -1;
struct page *page; struct page *page;
struct mcs_rwlock_node mcs_node; struct mcs_lock_node mcs_node;
int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK; int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK;
dkprintf("fileobj_lookup_page(%p,%lx,%x,%p)\n", obj, off, p2align, physp); dkprintf("fileobj_lookup_page(%p,%lx,%x,%p)\n", obj, off, p2align, physp);
@@ -784,7 +784,7 @@ static int fileobj_lookup_page(struct memobj *memobj, off_t off,
return -ENOMEM; return -ENOMEM;
} }
mcs_rwlock_reader_lock_noirq(&obj->page_hash_locks[hash], mcs_lock_lock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
page = __fileobj_page_hash_lookup(obj, hash, off); page = __fileobj_page_hash_lookup(obj, hash, off);
@@ -796,7 +796,7 @@ static int fileobj_lookup_page(struct memobj *memobj, off_t off,
error = 0; error = 0;
out: out:
mcs_rwlock_reader_unlock_noirq(&obj->page_hash_locks[hash], mcs_lock_unlock_noirq(&obj->page_hash_locks[hash],
&mcs_node); &mcs_node);
dkprintf("fileobj_lookup_page(%p,%lx,%x,%p): %d \n", dkprintf("fileobj_lookup_page(%p,%lx,%x,%p): %d \n",