diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-03-13 19:07:18 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-10 09:28:04 -0700 |
commit | ba46ce30f13a13bb24d05e21df2571ad724f1a1e (patch) | |
tree | 1bf3d9685389f6effee3db17307409abe9093e2d /drivers/staging/usbip/usbip_common.h | |
parent | 96ddcd439871658b797289dde8fcead8bde73b68 (diff) | |
download | kernel_goldelico_gta04-ba46ce30f13a13bb24d05e21df2571ad724f1a1e.zip kernel_goldelico_gta04-ba46ce30f13a13bb24d05e21df2571ad724f1a1e.tar.gz kernel_goldelico_gta04-ba46ce30f13a13bb24d05e21df2571ad724f1a1e.tar.bz2 |
staging: usbip: fix the usage of kthread_stop()
stub_shutdown_connection() and vhci_shutdown_connection() use
task_is_dead() before kthread_stop(). This buys nothing and wrong.
kthread_stop() is fine even if this thread is dead. However, if it
is dead nothing protects this task_struct, we shouldn't touch this
memory.
Change the code to do the necessary get_task_struct/put_task_struct.
This patch assumes that
- xxx_shutdown_connection() is always called, so we can't
leak the task_struct.
- kthread_stop_put() can't be called twice on the same task.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Tobias Klauser <tklauser@distanz.ch>
Cc: Matt Mooney <mfm@muteddisk.com>,
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/usbip/usbip_common.h')
-rw-r--r-- | drivers/staging/usbip/usbip_common.h | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h index c7b888c..5d89c0f 100644 --- a/drivers/staging/usbip/usbip_common.h +++ b/drivers/staging/usbip/usbip_common.h @@ -292,6 +292,23 @@ struct usbip_device { } eh_ops; }; +#define kthread_get_run(threadfn, data, namefmt, ...) \ +({ \ + struct task_struct *__k \ + = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \ + if (!IS_ERR(__k)) { \ + get_task_struct(__k); \ + wake_up_process(__k); \ + } \ + __k; \ +}) + +#define kthread_stop_put(k) \ + do { \ + kthread_stop(k); \ + put_task_struct(k); \ + } while (0) + /* usbip_common.c */ void usbip_dump_urb(struct urb *purb); void usbip_dump_header(struct usbip_header *pdu); |