Commit bd0a30cd authored by Andrea Arcangeli's avatar Andrea Arcangeli

userfaultfd: allocate the userfaultfd_ctx cacheline aligned

Use proper slab to guarantee alignment.
parent 18c5b6c4
......@@ -27,20 +27,26 @@
#include <linux/ioctl.h>
#include <linux/security.h>
static struct kmem_cache *userfaultfd_ctx_cachep __read_mostly;
enum userfaultfd_state {
UFFD_STATE_WAIT_API,
UFFD_STATE_RUNNING,
};
/*
* Start with fault_pending_wqh and fault_wqh so they're more likely
* to be in the same cacheline.
*/
struct userfaultfd_ctx {
/* pseudo fd refcounting */
atomic_t refcount;
/* waitqueue head for the pending (i.e. not read) userfaults */
wait_queue_head_t fault_pending_wqh;
/* waitqueue head for the userfaults */
wait_queue_head_t fault_wqh;
/* waitqueue head for the pseudo fd to wakeup poll/read */
wait_queue_head_t fd_wqh;
/* pseudo fd refcounting */
atomic_t refcount;
/* userfaultfd syscall flags */
unsigned int flags;
/* state machine */
......@@ -117,7 +123,7 @@ static void userfaultfd_ctx_put(struct userfaultfd_ctx *ctx)
VM_BUG_ON(spin_is_locked(&ctx->fd_wqh.lock));
VM_BUG_ON(waitqueue_active(&ctx->fd_wqh));
mmput(ctx->mm);
kfree(ctx);
kmem_cache_free(userfaultfd_ctx_cachep, ctx);
}
}
......@@ -987,6 +993,15 @@ static const struct file_operations userfaultfd_fops = {
.llseek = noop_llseek,
};
static void init_once_userfaultfd_ctx(void *mem)
{
struct userfaultfd_ctx *ctx = (struct userfaultfd_ctx *) mem;
init_waitqueue_head(&ctx->fault_pending_wqh);
init_waitqueue_head(&ctx->fault_wqh);
init_waitqueue_head(&ctx->fd_wqh);
}
/**
* userfaultfd_file_create - Creates an userfaultfd file pointer.
* @flags: Flags for the userfaultfd file.
......@@ -1017,14 +1032,11 @@ static struct file *userfaultfd_file_create(int flags)
goto out;
file = ERR_PTR(-ENOMEM);
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
ctx = kmem_cache_alloc(userfaultfd_ctx_cachep, GFP_KERNEL);
if (!ctx)
goto out;
atomic_set(&ctx->refcount, 1);
init_waitqueue_head(&ctx->fault_pending_wqh);
init_waitqueue_head(&ctx->fault_wqh);
init_waitqueue_head(&ctx->fd_wqh);
ctx->flags = flags;
ctx->state = UFFD_STATE_WAIT_API;
ctx->released = false;
......@@ -1035,7 +1047,7 @@ static struct file *userfaultfd_file_create(int flags)
file = anon_inode_getfile("[userfaultfd]", &userfaultfd_fops, ctx,
O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
if (IS_ERR(file))
kfree(ctx);
kmem_cache_free(userfaultfd_ctx_cachep, ctx);
out:
return file;
}
......@@ -1064,3 +1076,14 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
return error;
}
static int __init userfaultfd_init(void)
{
userfaultfd_ctx_cachep = kmem_cache_create("userfaultfd_ctx_cache",
sizeof(struct userfaultfd_ctx),
0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC,
init_once_userfaultfd_ctx);
return 0;
}
__initcall(userfaultfd_init);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment