IB/rxe: Wait for tasklets to finish before tearing down QP
The system may crash when a malformed request is received and the error is detected by the responder. NodeA: $ ibv_rc_pingpong -g 0 -d rxe0 -i 1 -n 1 -s 50000 NodeB: $ ibv_rc_pingpong -g 0 -d rxe0 -i 1 -n 1 -s 1024 <NodeA_ip> The responder generates a receive error on node B since the incoming SEND is oversized. If the client tears down the QP before the responder or the completer finish running, a page fault may occur. The fix makes the destroy operation spin until the tasks complete, which appears to be original intent of the design. Signed-off-by: Andrew Boyer <andrew.boyer@dell.com> Reviewed-by: Yuval Shaia <yuval.shaia@oracle.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
		
							parent
							
								
									5407f53012
								
							
						
					
					
						commit
						07bf9627d5
					
				| @ -121,6 +121,7 @@ int rxe_init_task(void *obj, struct rxe_task *task, | ||||
| 	task->arg	= arg; | ||||
| 	task->func	= func; | ||||
| 	snprintf(task->name, sizeof(task->name), "%s", name); | ||||
| 	task->destroyed	= false; | ||||
| 
 | ||||
| 	tasklet_init(&task->tasklet, rxe_do_task, (unsigned long)task); | ||||
| 
 | ||||
| @ -132,11 +133,29 @@ int rxe_init_task(void *obj, struct rxe_task *task, | ||||
| 
 | ||||
| void rxe_cleanup_task(struct rxe_task *task) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	bool idle; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Mark the task, then wait for it to finish. It might be | ||||
| 	 * running in a non-tasklet (direct call) context. | ||||
| 	 */ | ||||
| 	task->destroyed = true; | ||||
| 
 | ||||
| 	do { | ||||
| 		spin_lock_irqsave(&task->state_lock, flags); | ||||
| 		idle = (task->state == TASK_STATE_START); | ||||
| 		spin_unlock_irqrestore(&task->state_lock, flags); | ||||
| 	} while (!idle); | ||||
| 
 | ||||
| 	tasklet_kill(&task->tasklet); | ||||
| } | ||||
| 
 | ||||
| void rxe_run_task(struct rxe_task *task, int sched) | ||||
| { | ||||
| 	if (task->destroyed) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (sched) | ||||
| 		tasklet_schedule(&task->tasklet); | ||||
| 	else | ||||
|  | ||||
| @ -54,6 +54,7 @@ struct rxe_task { | ||||
| 	int			(*func)(void *arg); | ||||
| 	int			ret; | ||||
| 	char			name[16]; | ||||
| 	bool			destroyed; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user