aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/core/uverbs_main.c
diff options
context:
space:
mode:
authorRoland Dreier <roland@eddore.topspincom.com>2005-09-09 18:55:08 -0400
committerRoland Dreier <rolandd@cisco.com>2005-09-09 18:55:08 -0400
commit63aaf647529e8a56bdf31fd8f2979d4371c6a332 (patch)
treedd1ed29d591da4ef6ec0c4260d59b1910010c314 /drivers/infiniband/core/uverbs_main.c
parent2e9f7cb7869059e55cd91f5e23c6380f3763db56 (diff)
Make sure that userspace does not retrieve stale asynchronous or
completion events after destroying a CQ, QP or SRQ. We do this by sweeping the event lists before returning from a destroy calls, and then return the number of events already reported before the destroy call. This allows userspace wait until it has processed all events for an object returned from the kernel before it frees its context for the object. The ABI of the destroy CQ, destroy QP and destroy SRQ commands has to change to return the event count, so bump the ABI version from 1 to 2. The userspace libibverbs library has already been updated to handle both the old and new ABI versions. Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/core/uverbs_main.c')
-rw-r--r--drivers/infiniband/core/uverbs_main.c98
1 files changed, 62 insertions, 36 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 09caf5b1ef36..ce5bdb7af306 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -120,7 +120,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
120 idr_remove(&ib_uverbs_qp_idr, uobj->id); 120 idr_remove(&ib_uverbs_qp_idr, uobj->id);
121 ib_destroy_qp(qp); 121 ib_destroy_qp(qp);
122 list_del(&uobj->list); 122 list_del(&uobj->list);
123 kfree(uobj); 123 kfree(container_of(uobj, struct ib_uevent_object, uobject));
124 } 124 }
125 125
126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) { 126 list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
@@ -128,7 +128,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
128 idr_remove(&ib_uverbs_cq_idr, uobj->id); 128 idr_remove(&ib_uverbs_cq_idr, uobj->id);
129 ib_destroy_cq(cq); 129 ib_destroy_cq(cq);
130 list_del(&uobj->list); 130 list_del(&uobj->list);
131 kfree(uobj); 131 kfree(container_of(uobj, struct ib_ucq_object, uobject));
132 } 132 }
133 133
134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) { 134 list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
@@ -136,7 +136,7 @@ static int ib_dealloc_ucontext(struct ib_ucontext *context)
136 idr_remove(&ib_uverbs_srq_idr, uobj->id); 136 idr_remove(&ib_uverbs_srq_idr, uobj->id);
137 ib_destroy_srq(srq); 137 ib_destroy_srq(srq);
138 list_del(&uobj->list); 138 list_del(&uobj->list);
139 kfree(uobj); 139 kfree(container_of(uobj, struct ib_uevent_object, uobject));
140 } 140 }
141 141
142 /* XXX Free MWs */ 142 /* XXX Free MWs */
@@ -182,7 +182,7 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
182 size_t count, loff_t *pos) 182 size_t count, loff_t *pos)
183{ 183{
184 struct ib_uverbs_event_file *file = filp->private_data; 184 struct ib_uverbs_event_file *file = filp->private_data;
185 void *event; 185 struct ib_uverbs_event *event;
186 int eventsz; 186 int eventsz;
187 int ret = 0; 187 int ret = 0;
188 188
@@ -207,21 +207,23 @@ static ssize_t ib_uverbs_event_read(struct file *filp, char __user *buf,
207 return -ENODEV; 207 return -ENODEV;
208 } 208 }
209 209
210 if (file->is_async) { 210 event = list_entry(file->event_list.next, struct ib_uverbs_event, list);
211 event = list_entry(file->event_list.next, 211
212 struct ib_uverbs_async_event, list); 212 if (file->is_async)
213 eventsz = sizeof (struct ib_uverbs_async_event_desc); 213 eventsz = sizeof (struct ib_uverbs_async_event_desc);
214 } else { 214 else
215 event = list_entry(file->event_list.next,
216 struct ib_uverbs_comp_event, list);
217 eventsz = sizeof (struct ib_uverbs_comp_event_desc); 215 eventsz = sizeof (struct ib_uverbs_comp_event_desc);
218 }
219 216
220 if (eventsz > count) { 217 if (eventsz > count) {
221 ret = -EINVAL; 218 ret = -EINVAL;
222 event = NULL; 219 event = NULL;
223 } else 220 } else {
224 list_del(file->event_list.next); 221 list_del(file->event_list.next);
222 if (event->counter) {
223 ++(*event->counter);
224 list_del(&event->obj_list);
225 }
226 }
225 227
226 spin_unlock_irq(&file->lock); 228 spin_unlock_irq(&file->lock);
227 229
@@ -257,16 +259,13 @@ static unsigned int ib_uverbs_event_poll(struct file *filp,
257 259
258static void ib_uverbs_event_release(struct ib_uverbs_event_file *file) 260static void ib_uverbs_event_release(struct ib_uverbs_event_file *file)
259{ 261{
260 struct list_head *entry, *tmp; 262 struct ib_uverbs_event *entry, *tmp;
261 263
262 spin_lock_irq(&file->lock); 264 spin_lock_irq(&file->lock);
263 if (file->fd != -1) { 265 if (file->fd != -1) {
264 file->fd = -1; 266 file->fd = -1;
265 list_for_each_safe(entry, tmp, &file->event_list) 267 list_for_each_entry_safe(entry, tmp, &file->event_list, list)
266 if (file->is_async) 268 kfree(entry);
267 kfree(list_entry(entry, struct ib_uverbs_async_event, list));
268 else
269 kfree(list_entry(entry, struct ib_uverbs_comp_event, list));
270 } 269 }
271 spin_unlock_irq(&file->lock); 270 spin_unlock_irq(&file->lock);
272} 271}
@@ -304,18 +303,23 @@ static struct file_operations uverbs_event_fops = {
304 303
305void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context) 304void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
306{ 305{
307 struct ib_uverbs_file *file = cq_context; 306 struct ib_uverbs_file *file = cq_context;
308 struct ib_uverbs_comp_event *entry; 307 struct ib_ucq_object *uobj;
309 unsigned long flags; 308 struct ib_uverbs_event *entry;
309 unsigned long flags;
310 310
311 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 311 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
312 if (!entry) 312 if (!entry)
313 return; 313 return;
314 314
315 entry->desc.cq_handle = cq->uobject->user_handle; 315 uobj = container_of(cq->uobject, struct ib_ucq_object, uobject);
316
317 entry->desc.comp.cq_handle = cq->uobject->user_handle;
318 entry->counter = &uobj->comp_events_reported;
316 319
317 spin_lock_irqsave(&file->comp_file[0].lock, flags); 320 spin_lock_irqsave(&file->comp_file[0].lock, flags);
318 list_add_tail(&entry->list, &file->comp_file[0].event_list); 321 list_add_tail(&entry->list, &file->comp_file[0].event_list);
322 list_add_tail(&entry->obj_list, &uobj->comp_list);
319 spin_unlock_irqrestore(&file->comp_file[0].lock, flags); 323 spin_unlock_irqrestore(&file->comp_file[0].lock, flags);
320 324
321 wake_up_interruptible(&file->comp_file[0].poll_wait); 325 wake_up_interruptible(&file->comp_file[0].poll_wait);
@@ -323,20 +327,25 @@ void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context)
323} 327}
324 328
325static void ib_uverbs_async_handler(struct ib_uverbs_file *file, 329static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
326 __u64 element, __u64 event) 330 __u64 element, __u64 event,
331 struct list_head *obj_list,
332 u32 *counter)
327{ 333{
328 struct ib_uverbs_async_event *entry; 334 struct ib_uverbs_event *entry;
329 unsigned long flags; 335 unsigned long flags;
330 336
331 entry = kmalloc(sizeof *entry, GFP_ATOMIC); 337 entry = kmalloc(sizeof *entry, GFP_ATOMIC);
332 if (!entry) 338 if (!entry)
333 return; 339 return;
334 340
335 entry->desc.element = element; 341 entry->desc.async.element = element;
336 entry->desc.event_type = event; 342 entry->desc.async.event_type = event;
343 entry->counter = counter;
337 344
338 spin_lock_irqsave(&file->async_file.lock, flags); 345 spin_lock_irqsave(&file->async_file.lock, flags);
339 list_add_tail(&entry->list, &file->async_file.event_list); 346 list_add_tail(&entry->list, &file->async_file.event_list);
347 if (obj_list)
348 list_add_tail(&entry->obj_list, obj_list);
340 spin_unlock_irqrestore(&file->async_file.lock, flags); 349 spin_unlock_irqrestore(&file->async_file.lock, flags);
341 350
342 wake_up_interruptible(&file->async_file.poll_wait); 351 wake_up_interruptible(&file->async_file.poll_wait);
@@ -345,23 +354,39 @@ static void ib_uverbs_async_handler(struct ib_uverbs_file *file,
345 354
346void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr) 355void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr)
347{ 356{
348 ib_uverbs_async_handler(context_ptr, 357 struct ib_ucq_object *uobj;
349 event->element.cq->uobject->user_handle, 358
350 event->event); 359 uobj = container_of(event->element.cq->uobject,
360 struct ib_ucq_object, uobject);
361
362 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
363 event->event, &uobj->async_list,
364 &uobj->async_events_reported);
365
351} 366}
352 367
353void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr) 368void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
354{ 369{
355 ib_uverbs_async_handler(context_ptr, 370 struct ib_uevent_object *uobj;
356 event->element.qp->uobject->user_handle, 371
357 event->event); 372 uobj = container_of(event->element.qp->uobject,
373 struct ib_uevent_object, uobject);
374
375 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
376 event->event, &uobj->event_list,
377 &uobj->events_reported);
358} 378}
359 379
360void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr) 380void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
361{ 381{
362 ib_uverbs_async_handler(context_ptr, 382 struct ib_uevent_object *uobj;
363 event->element.srq->uobject->user_handle, 383
364 event->event); 384 uobj = container_of(event->element.srq->uobject,
385 struct ib_uevent_object, uobject);
386
387 ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
388 event->event, &uobj->event_list,
389 &uobj->events_reported);
365} 390}
366 391
367static void ib_uverbs_event_handler(struct ib_event_handler *handler, 392static void ib_uverbs_event_handler(struct ib_event_handler *handler,
@@ -370,7 +395,8 @@ static void ib_uverbs_event_handler(struct ib_event_handler *handler,
370 struct ib_uverbs_file *file = 395 struct ib_uverbs_file *file =
371 container_of(handler, struct ib_uverbs_file, event_handler); 396 container_of(handler, struct ib_uverbs_file, event_handler);
372 397
373 ib_uverbs_async_handler(file, event->element.port_num, event->event); 398 ib_uverbs_async_handler(file, event->element.port_num, event->event,
399 NULL, NULL);
374} 400}
375 401
376static int ib_uverbs_event_init(struct ib_uverbs_event_file *file, 402static int ib_uverbs_event_init(struct ib_uverbs_event_file *file,