diff options
author | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-01-29 15:50:52 -0500 |
---|---|---|
committer | Bjoern B. Brandenburg <bbb@cs.unc.edu> | 2011-02-01 16:53:21 -0500 |
commit | 7f0bd4c213ff8dca0eb3bdd887f5c62c8d30fab5 (patch) | |
tree | 99b45b5466dc27308e6d65751baf5e109eb37385 | |
parent | fab768a4cdc49ad7886cac0d0361f8432965a817 (diff) |
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.
-rw-r--r-- | include/litmus/fdso.h | 2 | ||||
-rw-r--r-- | include/litmus/sched_plugin.h | 3 | ||||
-rw-r--r-- | litmus/fdso.c | 51 | ||||
-rw-r--r-- | litmus/locking.c | 11 | ||||
-rw-r--r-- | litmus/sched_gsn_edf.c | 3 | ||||
-rw-r--r-- | litmus/sched_plugin.c | 3 | ||||
-rw-r--r-- | 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 { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct fdso_ops { | 45 | struct fdso_ops { |
46 | void* (*create)(obj_type_t type); | 46 | int (*create)(void** obj_ref, obj_type_t type, void* __user); |
47 | void (*destroy)(obj_type_t type, void*); | 47 | void (*destroy)(obj_type_t type, void*); |
48 | int (*open) (struct od_table_entry*, void* __user); | 48 | int (*open) (struct od_table_entry*, void* __user); |
49 | int (*close) (struct od_table_entry*); | 49 | 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 *); | |||
55 | 55 | ||
56 | /* Called when the current task attempts to create a new lock of a given | 56 | /* Called when the current task attempts to create a new lock of a given |
57 | * protocol type. */ | 57 | * protocol type. */ |
58 | typedef long (*allocate_lock_t) (struct litmus_lock **lock, int type); | 58 | typedef long (*allocate_lock_t) (struct litmus_lock **lock, int type, |
59 | void* __user config); | ||
59 | 60 | ||
60 | 61 | ||
61 | /********************* sys call backends ********************/ | 62 | /********************* 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[] = { | |||
25 | &generic_lock_ops, /* SRP_SEM */ | 25 | &generic_lock_ops, /* SRP_SEM */ |
26 | }; | 26 | }; |
27 | 27 | ||
28 | static void* fdso_create(obj_type_t type) | 28 | static int fdso_create(void** obj_ref, obj_type_t type, void* __user config) |
29 | { | 29 | { |
30 | if (fdso_ops[type]->create) | 30 | if (fdso_ops[type]->create) |
31 | return fdso_ops[type]->create(type); | 31 | return fdso_ops[type]->create(obj_ref, type, config); |
32 | else | 32 | else |
33 | return NULL; | 33 | return -EINVAL; |
34 | } | 34 | } |
35 | 35 | ||
36 | static void fdso_destroy(obj_type_t type, void* obj) | 36 | static void fdso_destroy(obj_type_t type, void* obj) |
@@ -55,20 +55,27 @@ static int fdso_close(struct od_table_entry* entry) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | /* inode must be locked already */ | 57 | /* inode must be locked already */ |
58 | static struct inode_obj_id* alloc_inode_obj(struct inode* inode, | 58 | static int alloc_inode_obj(struct inode_obj_id** obj_ref, |
59 | obj_type_t type, | 59 | struct inode* inode, |
60 | unsigned int id) | 60 | obj_type_t type, |
61 | unsigned int id, | ||
62 | void* __user config) | ||
61 | { | 63 | { |
62 | struct inode_obj_id* obj; | 64 | struct inode_obj_id* obj; |
63 | void* raw_obj; | 65 | void* raw_obj; |
64 | 66 | int err; | |
65 | raw_obj = fdso_create(type); | ||
66 | if (!raw_obj) | ||
67 | return NULL; | ||
68 | 67 | ||
69 | obj = kmalloc(sizeof(*obj), GFP_KERNEL); | 68 | obj = kmalloc(sizeof(*obj), GFP_KERNEL); |
70 | if (!obj) | 69 | if (!obj) { |
71 | return NULL; | 70 | return -ENOMEM; |
71 | } | ||
72 | |||
73 | err = fdso_create(&raw_obj, type, config); | ||
74 | if (err != 0) { | ||
75 | kfree(obj); | ||
76 | return err; | ||
77 | } | ||
78 | |||
72 | INIT_LIST_HEAD(&obj->list); | 79 | INIT_LIST_HEAD(&obj->list); |
73 | atomic_set(&obj->count, 1); | 80 | atomic_set(&obj->count, 1); |
74 | obj->type = type; | 81 | obj->type = type; |
@@ -80,7 +87,9 @@ static struct inode_obj_id* alloc_inode_obj(struct inode* inode, | |||
80 | atomic_inc(&inode->i_count); | 87 | atomic_inc(&inode->i_count); |
81 | 88 | ||
82 | printk(KERN_DEBUG "alloc_inode_obj(%p, %d, %d): object created\n", inode, type, id); | 89 | printk(KERN_DEBUG "alloc_inode_obj(%p, %d, %d): object created\n", inode, type, id); |
83 | return obj; | 90 | |
91 | *obj_ref = obj; | ||
92 | return 0; | ||
84 | } | 93 | } |
85 | 94 | ||
86 | /* inode must be locked already */ | 95 | /* inode must be locked already */ |
@@ -169,7 +178,7 @@ void exit_od_table(struct task_struct* t) | |||
169 | static int do_sys_od_open(struct file* file, obj_type_t type, int id, | 178 | static int do_sys_od_open(struct file* file, obj_type_t type, int id, |
170 | void* __user config) | 179 | void* __user config) |
171 | { | 180 | { |
172 | int idx = 0, err; | 181 | int idx = 0, err = 0; |
173 | struct inode* inode; | 182 | struct inode* inode; |
174 | struct inode_obj_id* obj = NULL; | 183 | struct inode_obj_id* obj = NULL; |
175 | struct od_table_entry* entry; | 184 | struct od_table_entry* entry; |
@@ -183,9 +192,10 @@ static int do_sys_od_open(struct file* file, obj_type_t type, int id, | |||
183 | mutex_lock(&inode->i_obj_mutex); | 192 | mutex_lock(&inode->i_obj_mutex); |
184 | obj = get_inode_obj(inode, type, id); | 193 | obj = get_inode_obj(inode, type, id); |
185 | if (!obj) | 194 | if (!obj) |
186 | obj = alloc_inode_obj(inode, type, id); | 195 | err = alloc_inode_obj(&obj, inode, type, id, config); |
187 | if (!obj) { | 196 | if (err != 0) { |
188 | idx = -ENOMEM; | 197 | obj = NULL; |
198 | idx = err; | ||
189 | entry->used = 0; | 199 | entry->used = 0; |
190 | } else { | 200 | } else { |
191 | entry->obj = obj; | 201 | entry->obj = obj; |
@@ -195,12 +205,15 @@ static int do_sys_od_open(struct file* file, obj_type_t type, int id, | |||
195 | 205 | ||
196 | mutex_unlock(&inode->i_obj_mutex); | 206 | mutex_unlock(&inode->i_obj_mutex); |
197 | 207 | ||
198 | err = fdso_open(entry, config); | 208 | /* open only if creation succeeded */ |
209 | if (!err) | ||
210 | err = fdso_open(entry, config); | ||
199 | if (err < 0) { | 211 | if (err < 0) { |
200 | /* The class rejected the open call. | 212 | /* The class rejected the open call. |
201 | * We need to clean up and tell user space. | 213 | * We need to clean up and tell user space. |
202 | */ | 214 | */ |
203 | put_od_entry(entry); | 215 | if (obj) |
216 | put_od_entry(entry); | ||
204 | idx = err; | 217 | idx = err; |
205 | } | 218 | } |
206 | 219 | ||
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 @@ | |||
5 | #include <litmus/sched_plugin.h> | 5 | #include <litmus/sched_plugin.h> |
6 | #include <litmus/trace.h> | 6 | #include <litmus/trace.h> |
7 | 7 | ||
8 | static void* create_generic_lock(obj_type_t type); | 8 | static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg); |
9 | static int open_generic_lock(struct od_table_entry* entry, void* __user arg); | 9 | static int open_generic_lock(struct od_table_entry* entry, void* __user arg); |
10 | static int close_generic_lock(struct od_table_entry* entry); | 10 | static int close_generic_lock(struct od_table_entry* entry); |
11 | static void destroy_generic_lock(obj_type_t type, void* sem); | 11 | 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) | |||
28 | return (struct litmus_lock*) entry->obj->obj; | 28 | return (struct litmus_lock*) entry->obj->obj; |
29 | } | 29 | } |
30 | 30 | ||
31 | static void* create_generic_lock(obj_type_t type) | 31 | static int create_generic_lock(void** obj_ref, obj_type_t type, void* __user arg) |
32 | { | 32 | { |
33 | struct litmus_lock* lock; | 33 | struct litmus_lock* lock; |
34 | int err; | 34 | int err; |
35 | 35 | ||
36 | err = litmus->allocate_lock(&lock, type); | 36 | err = litmus->allocate_lock(&lock, type, arg); |
37 | if (err == 0) | 37 | if (err == 0) |
38 | return lock; | 38 | *obj_ref = lock; |
39 | else | 39 | return err; |
40 | return NULL; | ||
41 | } | 40 | } |
42 | 41 | ||
43 | static int open_generic_lock(struct od_table_entry* entry, void* __user arg) | 42 | 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) | |||
895 | /* **** lock constructor **** */ | 895 | /* **** lock constructor **** */ |
896 | 896 | ||
897 | 897 | ||
898 | static long gsnedf_allocate_lock(struct litmus_lock **lock, int type) | 898 | static long gsnedf_allocate_lock(struct litmus_lock **lock, int type, |
899 | void* __user unused) | ||
899 | { | 900 | { |
900 | int err = -ENXIO; | 901 | int err = -ENXIO; |
901 | 902 | ||
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) | |||
123 | 123 | ||
124 | #ifdef CONFIG_LITMUS_LOCKING | 124 | #ifdef CONFIG_LITMUS_LOCKING |
125 | 125 | ||
126 | static long litmus_dummy_allocate_lock(struct litmus_lock **lock, int type) | 126 | static long litmus_dummy_allocate_lock(struct litmus_lock **lock, int type, |
127 | void* __user config) | ||
127 | { | 128 | { |
128 | return -ENXIO; | 129 | return -ENXIO; |
129 | } | 130 | } |
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) | |||
547 | /* **** lock constructor **** */ | 547 | /* **** lock constructor **** */ |
548 | 548 | ||
549 | 549 | ||
550 | static long psnedf_allocate_lock(struct litmus_lock **lock, int type) | 550 | static long psnedf_allocate_lock(struct litmus_lock **lock, int type, |
551 | void* __user unused) | ||
551 | { | 552 | { |
552 | int err = -ENXIO; | 553 | int err = -ENXIO; |
553 | struct srp_semaphore* srp; | 554 | struct srp_semaphore* srp; |