From 7f0bd4c213ff8dca0eb3bdd887f5c62c8d30fab5 Mon Sep 17 00:00:00 2001 From: "Bjoern B. Brandenburg" Date: Sat, 29 Jan 2011 15:50:52 -0500 Subject: fdso: pass userpsace config argument to object constructor As Glenn pointed out, it is useful for some protocols (e.g., k-exclusion protocols) to know the userspace configuration at object creation time. This patch changes the fdso API to pass the parameter to the object constructor, which is then in turn passed to the lock allocater. The return code from the lock allocater is passed to userspace in return. This also fixes some null pointer dereferences in the FDSO code found by the test suite in liblitmus. --- include/litmus/fdso.h | 2 +- include/litmus/sched_plugin.h | 3 ++- litmus/fdso.c | 51 +++++++++++++++++++++++++++---------------- litmus/locking.c | 11 +++++----- litmus/sched_gsn_edf.c | 3 ++- litmus/sched_plugin.c | 3 ++- litmus/sched_psn_edf.c | 3 ++- 7 files changed, 46 insertions(+), 30 deletions(-) diff --git a/include/litmus/fdso.h b/include/litmus/fdso.h index 25a292d68d96..caf2a1e6918c 100644 --- a/include/litmus/fdso.h +++ b/include/litmus/fdso.h @@ -43,7 +43,7 @@ struct od_table_entry { }; struct fdso_ops { - void* (*create)(obj_type_t type); + int (*create)(void** obj_ref, obj_type_t type, void* __user); void (*destroy)(obj_type_t type, void*); int (*open) (struct od_table_entry*, void* __user); int (*close) (struct od_table_entry*); diff --git a/include/litmus/sched_plugin.h b/include/litmus/sched_plugin.h index 8a3ed6d19a3c..6e7cabdddae8 100644 --- a/include/litmus/sched_plugin.h +++ b/include/litmus/sched_plugin.h @@ -55,7 +55,8 @@ typedef void (*task_exit_t) (struct task_struct *); /* Called when the current task attempts to create a new lock of a given * protocol type. */ -typedef long (*allocate_lock_t) (struct litmus_lock **lock, int type); +typedef long (*allocate_lock_t) (struct litmus_lock **lock, int type, + void* __user config); /********************* sys call backends ********************/ diff --git a/litmus/fdso.c b/litmus/fdso.c index b3a95f13d651..aa7b384264e3 100644 --- a/litmus/fdso.c +++ b/litmus/fdso.c @@ -25,12 +25,12 @@ static const struct fdso_ops* fdso_ops[] = { &generic_lock_ops, /* SRP_SEM */ }; -static void* fdso_create(obj_type_t type) +static int fdso_create(void** obj_ref, obj_type_t type, void* __user config) { if (fdso_ops[type]->create) - return fdso_ops[type]->create(type); + return fdso_ops[type]->create(obj_ref, type, config); else - return NULL; + return -EINVAL; } static void fdso_destroy(obj_type_t type, void* obj) @@ -55,20 +55,27 @@ static int fdso_close(struct od_table_entry* entry) } /* inode must be locked already */ -static struct inode_obj_id* alloc_inode_obj(struct inode* inode, - obj_type_t type, - unsigned int id) +static int alloc_inode_obj(struct inode_obj_id** obj_ref, + struct inode* inode, + obj_type_t type, + unsigned int id, + void* __user config) { struct inode_obj_id* obj; void* raw_obj; - - raw_obj = fdso_create(type); - if (!raw_obj) - return NULL; + int err; obj = kmalloc(sizeof(*obj), GFP_KERNEL); - if (!obj) - return NULL; + if (!obj) { + return -ENOMEM; + } + + err = fdso_create(&raw_obj, type, config); + if (err != 0) { + kfree(obj); + return err; + } + INIT_LIST_HEAD(&obj->list); atomic_set(&obj->count, 1); obj->type = type; @@ -80,7 +87,9 @@ static struct inode_obj_id* alloc_inode_obj(struct inode* inode, atomic_inc(&inode->i_count); printk(KERN_DEBUG "alloc_inode_obj(%p, %d, %d): object created\n", inode, type, id); - return obj; + + *obj_ref = obj; + return 0; } /* inode must be locked already */ @@ -169,7 +178,7 @@ void exit_od_table(struct task_struct* t) static int do_sys_od_open(struct file* file, obj_type_t type, int id, void* __user config) { - int idx = 0, err; + int idx = 0, err = 0; struct inode* inode; struct inode_obj_id* obj = NULL; struct od_table_entry* entry; @@ -183,9 +192,10 @@ static int do_sys_od_open(struct file* file, obj_type_t type, int id, mutex_lock(&inode->i_obj_mutex); obj = get_inode_obj(inode, type, id); if (!obj) - obj = alloc_inode_obj(inode, type, id); - if (!obj) { - idx = -ENOMEM; + err = alloc_inode_obj(&obj, inode, type, id, config); + if (err != 0) { + obj = NULL; + idx = err; entry->used = 0; } else { entry->obj = obj; @@ -195,12 +205,15 @@ static int do_sys_od_open(struct file* file, obj_type_t type, int id, mutex_unlock(&inode->i_obj_mutex); - err = fdso_open(entry, config); + /* open only if creation succeeded */ + if (!err) + err = fdso_open(entry, config); if (err < 0) { /* The class rejected the open call. * We need to clean up and tell user space. */ - put_od_entry(entry); + if (obj) + put_od_entry(entry); idx = err; } diff --git a/litmus/locking.c b/litmus/locking.c index d39afaeefffe..8ee6a6b68009 100644 --- a/litmus/locking.c +++ b/litmus/locking.c @@ -5,7 +5,7 @@ #include #include -static void* create_generic_lock(obj_type_t type); +static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg); static int open_generic_lock(struct od_table_entry* entry, void* __user arg); static int close_generic_lock(struct od_table_entry* entry); static void destroy_generic_lock(obj_type_t type, void* sem); @@ -28,16 +28,15 @@ static inline struct litmus_lock* get_lock(struct od_table_entry* entry) return (struct litmus_lock*) entry->obj->obj; } -static void* create_generic_lock(obj_type_t type) +static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg) { struct litmus_lock* lock; int err; - err = litmus->allocate_lock(&lock, type); + err = litmus->allocate_lock(&lock, type, arg); if (err == 0) - return lock; - else - return NULL; + *obj_ref = lock; + return err; } static int open_generic_lock(struct od_table_entry* entry, void* __user arg) diff --git a/litmus/sched_gsn_edf.c b/litmus/sched_gsn_edf.c index c525d43eb051..c5c9600c33d8 100644 --- a/litmus/sched_gsn_edf.c +++ b/litmus/sched_gsn_edf.c @@ -895,7 +895,8 @@ static struct litmus_lock* gsnedf_new_fmlp(void) /* **** lock constructor **** */ -static long gsnedf_allocate_lock(struct litmus_lock **lock, int type) +static long gsnedf_allocate_lock(struct litmus_lock **lock, int type, + void* __user unused) { int err = -ENXIO; diff --git a/litmus/sched_plugin.c b/litmus/sched_plugin.c index 2f8f399b195f..d54886df1f57 100644 --- a/litmus/sched_plugin.c +++ b/litmus/sched_plugin.c @@ -123,7 +123,8 @@ static long litmus_dummy_deactivate_plugin(void) #ifdef CONFIG_LITMUS_LOCKING -static long litmus_dummy_allocate_lock(struct litmus_lock **lock, int type) +static long litmus_dummy_allocate_lock(struct litmus_lock **lock, int type, + void* __user config) { return -ENXIO; } diff --git a/litmus/sched_psn_edf.c b/litmus/sched_psn_edf.c index 801bc92c5835..abb06fa53e3a 100644 --- a/litmus/sched_psn_edf.c +++ b/litmus/sched_psn_edf.c @@ -547,7 +547,8 @@ static struct litmus_lock* psnedf_new_fmlp(void) /* **** lock constructor **** */ -static long psnedf_allocate_lock(struct litmus_lock **lock, int type) +static long psnedf_allocate_lock(struct litmus_lock **lock, int type, + void* __user unused) { int err = -ENXIO; struct srp_semaphore* srp; -- cgit v1.2.2