staging: usbip: usbip_common: kill rx thread on tx thread creation error.

Signed-off-by: Himanshu Chauhan <hschauhan@nulltrace.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Himanshu Chauhan 2010-06-04 23:16:27 +05:30 committed by Greg Kroah-Hartman
parent 9341625307
commit f2102d31de

View file

@ -378,47 +378,67 @@ int usbip_thread(void *param)
complete_and_exit(&ut->thread_done, 0); complete_and_exit(&ut->thread_done, 0);
} }
static void stop_rx_thread(struct usbip_device *ud)
{
if (ud->tcp_rx.thread != NULL) {
send_sig(SIGKILL, ud->tcp_rx.thread, 1);
wait_for_completion(&ud->tcp_rx.thread_done);
usbip_udbg("rx_thread for ud %p has finished\n", ud);
}
}
static void stop_tx_thread(struct usbip_device *ud)
{
if (ud->tcp_tx.thread != NULL) {
send_sig(SIGKILL, ud->tcp_tx.thread, 1);
wait_for_completion(&ud->tcp_tx.thread_done);
usbip_udbg("tx_thread for ud %p has finished\n", ud);
}
}
int usbip_start_threads(struct usbip_device *ud) int usbip_start_threads(struct usbip_device *ud)
{ {
/* /*
* threads are invoked per one device (per one connection). * threads are invoked per one device (per one connection).
*/ */
struct task_struct *th; struct task_struct *th;
int err = 0;
th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip"); th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
if (IS_ERR(th)) { if (IS_ERR(th)) {
printk(KERN_WARNING printk(KERN_WARNING
"Unable to start control thread\n"); "Unable to start control thread\n");
return PTR_ERR(th); err = PTR_ERR(th);
goto ust_exit;
} }
th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip"); th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
if (IS_ERR(th)) { if (IS_ERR(th)) {
printk(KERN_WARNING printk(KERN_WARNING
"Unable to start control thread\n"); "Unable to start control thread\n");
return PTR_ERR(th); err = PTR_ERR(th);
goto tx_thread_err;
} }
/* confirm threads are starting */ /* confirm threads are starting */
wait_for_completion(&ud->tcp_rx.thread_done); wait_for_completion(&ud->tcp_rx.thread_done);
wait_for_completion(&ud->tcp_tx.thread_done); wait_for_completion(&ud->tcp_tx.thread_done);
return 0; return 0;
tx_thread_err:
stop_rx_thread(ud);
ust_exit:
return err;
} }
EXPORT_SYMBOL_GPL(usbip_start_threads); EXPORT_SYMBOL_GPL(usbip_start_threads);
void usbip_stop_threads(struct usbip_device *ud) void usbip_stop_threads(struct usbip_device *ud)
{ {
/* kill threads related to this sdev, if v.c. exists */ /* kill threads related to this sdev, if v.c. exists */
if (ud->tcp_rx.thread != NULL) { stop_rx_thread(ud);
send_sig(SIGKILL, ud->tcp_rx.thread, 1); stop_tx_thread(ud);
wait_for_completion(&ud->tcp_rx.thread_done);
usbip_udbg("rx_thread for ud %p has finished\n", ud);
}
if (ud->tcp_tx.thread != NULL) {
send_sig(SIGKILL, ud->tcp_tx.thread, 1);
wait_for_completion(&ud->tcp_tx.thread_done);
usbip_udbg("tx_thread for ud %p has finished\n", ud);
}
} }
EXPORT_SYMBOL_GPL(usbip_stop_threads); EXPORT_SYMBOL_GPL(usbip_stop_threads);