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 /litmus/fdso.c | |
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.
Diffstat (limited to 'litmus/fdso.c')
-rw-r--r-- | litmus/fdso.c | 51 |
1 files changed, 32 insertions, 19 deletions
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 | ||