All of lore.kernel.org
 help / color / mirror / Atom feed
From: Max Vozeler <max@vozeler.com>
To: Arnd Bergmann <arnd@arndb.de>
Cc: linux-kernel@vger.kernel.org, Greg Kroah-Hartman <gregkh@suse.de>,
	Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>
Subject: Re: [PATCH 03/20] staging/usbip: convert to kthread
Date: Fri, 28 Jan 2011 19:53:48 +0200	[thread overview]
Message-ID: <4D4302AC.3050903@vozeler.com> (raw)
In-Reply-To: <1295993854-4971-4-git-send-email-arnd@arndb.de>

Hi Arnd,

On 26.01.2011 00:17, Arnd Bergmann wrote:
> usbip has its own infrastructure for managing kernel
> threads, similar to kthread. By changing it to use
> the standard functions, we can simplify the code
> and get rid of one of the last BKL users at the
> same time.
> 
> Compile-tested only, please verify.

I started reviewing and testing, but need to 
postpone proper testing until mid next week. I did 
notice a few problems (see below)

> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Cc: Greg Kroah-Hartman <gregkh@suse.de>
> Cc: Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>
> ---
>  drivers/staging/usbip/Kconfig        |    2 +-
>  drivers/staging/usbip/stub.h         |    4 +-
>  drivers/staging/usbip/stub_dev.c     |   13 +++--
>  drivers/staging/usbip/stub_rx.c      |   13 ++---
>  drivers/staging/usbip/stub_tx.c      |   14 ++---
>  drivers/staging/usbip/usbip_common.c |  105 ----------------------------------
>  drivers/staging/usbip/usbip_common.h |   20 +------
>  drivers/staging/usbip/usbip_event.c  |   31 +++-------
>  drivers/staging/usbip/vhci.h         |    4 +-
>  drivers/staging/usbip/vhci_hcd.c     |   10 ++-
>  drivers/staging/usbip/vhci_rx.c      |   16 ++---
>  drivers/staging/usbip/vhci_sysfs.c   |    9 +--
>  drivers/staging/usbip/vhci_tx.c      |   14 ++---
>  13 files changed, 58 insertions(+), 197 deletions(-)

What is not to like :)

> diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
> index b11ec37..2c1d10a 100644
> --- a/drivers/staging/usbip/Kconfig
> +++ b/drivers/staging/usbip/Kconfig
> @@ -1,6 +1,6 @@
>  config USB_IP_COMMON
>  	tristate "USB IP support (EXPERIMENTAL)"
> -	depends on USB && NET && EXPERIMENTAL && BKL
> +	depends on USB && NET && EXPERIMENTAL
>  	default N
>  	---help---
>  	  This enables pushing USB packets over IP to allow remote
> diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
> index 30dbfb6..5b44e7b 100644
> --- a/drivers/staging/usbip/stub.h
> +++ b/drivers/staging/usbip/stub.h
> @@ -94,13 +94,13 @@ extern struct kmem_cache *stub_priv_cache;
>  
>  /* stub_tx.c */
>  void stub_complete(struct urb *);
> -void stub_tx_loop(struct usbip_task *);
> +int stub_tx_loop(void *data);
>  
>  /* stub_dev.c */
>  extern struct usb_driver stub_driver;
>  
>  /* stub_rx.c */
> -void stub_rx_loop(struct usbip_task *);
> +int stub_rx_loop(void *data);
>  void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32);
>  
>  /* stub_main.c */
> diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
> index b186b5f..4ee70d4 100644
> --- a/drivers/staging/usbip/stub_dev.c
> +++ b/drivers/staging/usbip/stub_dev.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/slab.h>
> +#include <linux/kthread.h>
>  
>  #include "usbip_common.h"
>  #include "stub.h"
> @@ -138,7 +139,8 @@ static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
>  
>  		spin_unlock(&sdev->ud.lock);
>  
> -		usbip_start_threads(&sdev->ud);
> +		wake_up_process(sdev->ud.tcp_rx);
> +		wake_up_process(sdev->ud.tcp_tx);

The threads may have exited already if the
device was in use then then shut down.

Can we create or kthread_run() the threads 
here as I think happened before?

This is what I saw from a quick test:

[  405.674068] usbip 1-1:1.0: stub up
[  405.674110] general protection fault: 0000 [#1] SMP 
[  405.674876] last sysfs file: /sys/devices/pci0000:00/0000:00:01.2/usb1/1-1/1-1:1.0/usbip_sockfd
[  405.676045] CPU 0 
[  405.676045] Modules linked in: usbip(C) usbip_common_mod(C) snd_pcm_oss snd_mixer_oss snd_seq snd_seq_device edd nfs lockd fscache nfs_acl auth_rpcgss sunrpc ipv6 af_packet mperf microcode configfs fuse loop dm_mod snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_timer tpm_tis tpm snd soundcore tpm_bios rtc_cmos rtc_core i2c_piix4 i2c_core virtio_net snd_page_alloc pcspkr rtc_lib floppy virtio_balloon button uhci_hcd ehci_hcd usbcore ext3 mbcache jbd fan processor virtio_blk virtio_pci virtio_ring virtio ide_pci_generic piix ide_core ata_generic ata_piix libata scsi_mod thermal thermal_sys hwmon
[  405.676045] 
[  405.676045] Pid: 3360, comm: usbipd Tainted: G         C  2.6.38-rc2-0.5-default+ #1 /Bochs
[  405.676045] RIP: 0010:[<ffffffff8104c41f>]  [<ffffffff8104c41f>] task_rq_lock+0x4f/0xb0
[  405.676045] RSP: 0018:ffff88003b687db8  EFLAGS: 00010006
[  405.676045] RAX: 6b6b6b6b6b6b6b6b RBX: 00000000001d54c0 RCX: 0000000000000001
[  405.676045] RDX: ffff880037da1310 RSI: 0000000000000000 RDI: ffffffff8104c41a
[  405.676045] RBP: ffff88003b687dd8 R08: 0000000000000000 R09: 0000000000000001
[  405.676045] R10: 0000000000000008 R11: 0000000000000001 R12: ffff880038fdd2d0
[  405.676045] R13: ffff88003b687e10 R14: 00000000001d54c0 R15: 000000000000000f
[  405.676045] FS:  00007f6a43816700(0000) GS:ffff88003e200000(0000) knlGS:0000000000000000
[  405.676045] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  405.676045] CR2: 00007fae487ab000 CR3: 000000003b439000 CR4: 00000000000006f0
[  405.676045] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[  405.676045] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[  405.676045] Process usbipd (pid: 3360, threadinfo ffff88003b686000, task ffff880037da1310)
[  405.676045] Stack:
[  405.676045]  ffff880038fdd2d0 ffff880039be54b0 0000000000000000 0000000000000000
[  405.676045]  ffff88003b687e48 ffffffff8105985c ffff880037da1380 ffffffffa013f0a2
[  405.676045]  ffff88003b687e38 0000000000000246 0000000000000002 0000000000000286
[  405.676045] Call Trace:
[  405.676045]  [<ffffffff8105985c>] try_to_wake_up+0x3c/0x430
[  405.676045]  [<ffffffffa013f0a2>] ? store_sockfd+0xa2/0x1a0 [usbip]
[  405.676045]  [<ffffffff81059ca5>] wake_up_process+0x15/0x20
[  405.676045]  [<ffffffffa013f0ab>] store_sockfd+0xab/0x1a0 [usbip]
[  405.676045]  [<ffffffff8130b390>] dev_attr_store+0x20/0x30
[  405.676045]  [<ffffffff811c4186>] sysfs_write_file+0xe6/0x170
[  405.676045]  [<ffffffff81156e80>] vfs_write+0xd0/0x1a0
[  405.676045]  [<ffffffff81157054>] sys_write+0x54/0xa0
[  405.676045]  [<ffffffff8100bf42>] system_call_fastpath+0x16/0x1b

>  		spin_lock(&sdev->ud.lock);
>  		sdev->ud.status = SDEV_ST_USED;
> @@ -218,7 +220,8 @@ static void stub_shutdown_connection(struct usbip_device *ud)
>  	}
>  
>  	/* 1. stop threads */
> -	usbip_stop_threads(ud);
> +	kthread_stop(ud->tcp_rx);
> +	kthread_stop(ud->tcp_tx);
>  
>  	/* 2. close the socket */
>  	/*
> @@ -333,8 +336,8 @@ static struct stub_device *stub_device_alloc(struct usb_interface *interface)
>  	 */
>  	sdev->devid     = (busnum << 16) | devnum;
>  
> -	usbip_task_init(&sdev->ud.tcp_rx, "stub_rx", stub_rx_loop);
> -	usbip_task_init(&sdev->ud.tcp_tx, "stub_tx", stub_tx_loop);
> +	sdev->ud.tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx");
> +	sdev->ud.tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx");

>  	sdev->ud.side = USBIP_STUB;
>  	sdev->ud.status = SDEV_ST_AVAILABLE;
> @@ -537,7 +540,7 @@ static void stub_disconnect(struct usb_interface *interface)
>  	stub_remove_files(&interface->dev);
>  
>  	/*If usb reset called from event handler*/
> -	if (busid_priv->sdev->ud.eh.thread == current) {
> +	if (busid_priv->sdev->ud.eh == current) {
>  		busid_priv->interf_count--;
>  		return;
>  	}
> diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
> index 3de6fd2..4ecc2bb 100644
> --- a/drivers/staging/usbip/stub_rx.c
> +++ b/drivers/staging/usbip/stub_rx.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/slab.h>
> +#include <linux/kthread.h>
>  
>  #include "usbip_common.h"
>  #include "stub.h"
> @@ -616,19 +617,15 @@ static void stub_rx_pdu(struct usbip_device *ud)
>  
>  }
>  
> -void stub_rx_loop(struct usbip_task *ut)
> +int stub_rx_loop(void *data)
>  {
> -	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
> -
> -	while (1) {
> -		if (signal_pending(current)) {
> -			usbip_dbg_stub_rx("signal caught!\n");
> -			break;
> -		}
> +	struct usbip_device *ud = data;
>  
> +	while (!kthread_should_stop()) {
>  		if (usbip_event_happened(ud))
>  			break;
>  
>  		stub_rx_pdu(ud);
>  	}
> +	return 0;
>  }
> diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
> index d7136e2..2477481 100644
> --- a/drivers/staging/usbip/stub_tx.c
> +++ b/drivers/staging/usbip/stub_tx.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/slab.h>
> +#include <linux/kthread.h>
>  
>  #include "usbip_common.h"
>  #include "stub.h"
> @@ -333,17 +334,12 @@ static int stub_send_ret_unlink(struct stub_device *sdev)
>  
>  /*-------------------------------------------------------------------------*/
>  
> -void stub_tx_loop(struct usbip_task *ut)
> +int stub_tx_loop(void *data)
>  {
> -	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
> +	struct usbip_device *ud = data;
>  	struct stub_device *sdev = container_of(ud, struct stub_device, ud);
>  
> -	while (1) {
> -		if (signal_pending(current)) {
> -			usbip_dbg_stub_tx("signal catched\n");
> -			break;
> -		}
> -
> +	while (!kthread_should_stop()) {
>  		if (usbip_event_happened(ud))
>  			break;
>  
> @@ -371,4 +367,6 @@ void stub_tx_loop(struct usbip_task *ut)
>  				(!list_empty(&sdev->priv_tx) ||
>  				 !list_empty(&sdev->unlink_tx)));
>  	}

I think this needs kthread_should_stop() as 
condition for the wait_event_interruptible() or
the thread may not actually stop.

--- a/drivers/staging/usbip/stub_tx.c
+++ b/drivers/staging/usbip/stub_tx.c
@@ -365,7 +365,8 @@ int stub_tx_loop(void *data)
 
                wait_event_interruptible(sdev->tx_waitq,
                                (!list_empty(&sdev->priv_tx) ||
-                                !list_empty(&sdev->unlink_tx)));
+                                !list_empty(&sdev->unlink_tx)) ||
+                               kthread_should_stop());
        }
 
        return 0;

> diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
> index 210ef16..337abc4 100644
> --- a/drivers/staging/usbip/usbip_common.c
> +++ b/drivers/staging/usbip/usbip_common.c
> @@ -18,7 +18,6 @@
>   */
>  
>  #include <linux/kernel.h>
> -#include <linux/smp_lock.h>
>  #include <linux/file.h>
>  #include <linux/tcp.h>
>  #include <linux/in.h>
> @@ -349,110 +348,6 @@ void usbip_dump_header(struct usbip_header *pdu)
>  }
>  EXPORT_SYMBOL_GPL(usbip_dump_header);
>  
> -
> -/*-------------------------------------------------------------------------*/
> -/* thread routines */
> -
> -int usbip_thread(void *param)
> -{
> -	struct usbip_task *ut = param;
> -
> -	if (!ut)
> -		return -EINVAL;
> -
> -	lock_kernel();
> -	daemonize(ut->name);
> -	allow_signal(SIGKILL);
> -	ut->thread = current;
> -	unlock_kernel();
> -
> -	/* srv.rb must wait for rx_thread starting */
> -	complete(&ut->thread_done);
> -
> -	/* start of while loop */
> -	ut->loop_ops(ut);
> -
> -	/* end of loop */
> -	ut->thread = NULL;
> -
> -	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)
> -{
> -	/*
> -	 * threads are invoked per one device (per one connection).
> -	 */
> -	struct task_struct *th;
> -	int err = 0;
> -
> -	th = kthread_run(usbip_thread, (void *)&ud->tcp_rx, "usbip");
> -	if (IS_ERR(th)) {
> -		printk(KERN_WARNING
> -			"Unable to start control thread\n");
> -		err = PTR_ERR(th);
> -		goto ust_exit;
> -	}
> -
> -	th = kthread_run(usbip_thread, (void *)&ud->tcp_tx, "usbip");
> -	if (IS_ERR(th)) {
> -		printk(KERN_WARNING
> -			"Unable to start control thread\n");
> -		err = PTR_ERR(th);
> -		goto tx_thread_err;
> -	}
> -
> -	/* confirm threads are starting */
> -	wait_for_completion(&ud->tcp_rx.thread_done);
> -	wait_for_completion(&ud->tcp_tx.thread_done);
> -
> -	return 0;
> -
> -tx_thread_err:
> -	stop_rx_thread(ud);
> -
> -ust_exit:
> -	return err;
> -}
> -EXPORT_SYMBOL_GPL(usbip_start_threads);
> -
> -void usbip_stop_threads(struct usbip_device *ud)
> -{
> -	/* kill threads related to this sdev, if v.c. exists */
> -	stop_rx_thread(ud);
> -	stop_tx_thread(ud);
> -}
> -EXPORT_SYMBOL_GPL(usbip_stop_threads);
> -
> -void usbip_task_init(struct usbip_task *ut, char *name,
> -		void (*loop_ops)(struct usbip_task *))
> -{
> -	ut->thread = NULL;
> -	init_completion(&ut->thread_done);
> -	ut->name = name;
> -	ut->loop_ops = loop_ops;
> -}
> -EXPORT_SYMBOL_GPL(usbip_task_init);
> -
> -
>  /*-------------------------------------------------------------------------*/
>  /* socket routines */
>  
> diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
> index d280e23..9f809c3 100644
> --- a/drivers/staging/usbip/usbip_common.h
> +++ b/drivers/staging/usbip/usbip_common.h
> @@ -307,13 +307,6 @@ void usbip_dump_header(struct usbip_header *pdu);
>  
>  struct usbip_device;
>  
> -struct usbip_task {
> -	struct task_struct *thread;
> -	struct completion thread_done;
> -	char *name;
> -	void (*loop_ops)(struct usbip_task *);
> -};
> -
>  enum usbip_side {
>  	USBIP_VHCI,
>  	USBIP_STUB,
> @@ -346,8 +339,8 @@ struct usbip_device {
>  
>  	struct socket *tcp_socket;
>  
> -	struct usbip_task tcp_rx;
> -	struct usbip_task tcp_tx;
> +	struct task_struct *tcp_rx;
> +	struct task_struct *tcp_tx;
>  
>  	/* event handler */
>  #define USBIP_EH_SHUTDOWN	(1 << 0)
> @@ -367,7 +360,7 @@ struct usbip_device {
>  #define	VDEV_EVENT_ERROR_MALLOC	(USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
>  
>  	unsigned long event;
> -	struct usbip_task eh;
> +	struct task_struct *eh;
>  	wait_queue_head_t eh_waitq;
>  
>  	struct eh_ops {
> @@ -378,13 +371,6 @@ struct usbip_device {
>  };
>  
>  
> -void usbip_task_init(struct usbip_task *ut, char *,
> -				void (*loop_ops)(struct usbip_task *));
> -
> -int usbip_start_threads(struct usbip_device *ud);
> -void usbip_stop_threads(struct usbip_device *ud);
> -int usbip_thread(void *param);
> -
>  void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
>  								int pack);
>  
> diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c
> index af3832b..89aecec 100644
> --- a/drivers/staging/usbip/usbip_event.c
> +++ b/drivers/staging/usbip/usbip_event.c
> @@ -62,16 +62,11 @@ static int event_handler(struct usbip_device *ud)
>  	return 0;
>  }
>  
> -static void event_handler_loop(struct usbip_task *ut)
> +static int event_handler_loop(void *data)
>  {
> -	struct usbip_device *ud = container_of(ut, struct usbip_device, eh);
> -
> -	while (1) {
> -		if (signal_pending(current)) {
> -			usbip_dbg_eh("signal catched!\n");
> -			break;
> -		}
> +	struct usbip_device *ud = data;
>  
> +	while (!kthread_should_stop()) {
>  		if (event_handler(ud) < 0)
>  			break;
>  
> @@ -79,38 +74,30 @@ static void event_handler_loop(struct usbip_task *ut)
>  					usbip_event_happened(ud));
>  		usbip_dbg_eh("wakeup\n");
>  	}
> +	return 0;
>  }

Same here, I think this is needed:

--- a/drivers/staging/usbip/usbip_event.c
+++ b/drivers/staging/usbip/usbip_event.c
@@ -71,7 +71,9 @@ static int event_handler_loop(void *data)
                        break;
 
                wait_event_interruptible(ud->eh_waitq,
-                                       usbip_event_happened(ud));
+                                       usbip_event_happened(ud) ||
+                                       kthread_should_stop());
+
                usbip_dbg_eh("wakeup\n");
        }
        return 0;

The event handler also needs to get a chance to
run the shutdown functions before it exists. 

This was implicitly the case before.

@@ -67,14 +67,14 @@ static int event_handler_loop(void *data)
        struct usbip_device *ud = data;
 
        while (!kthread_should_stop()) {
-               if (event_handler(ud) < 0)
-                       break;
-
                wait_event_interruptible(ud->eh_waitq,
                                        usbip_event_happened(ud) ||
                                        kthread_should_stop());
 
                usbip_dbg_eh("wakeup\n");
+
+               if (event_handler(ud) < 0)
+                       break;
        }
        return 0;
 }

>  int usbip_start_eh(struct usbip_device *ud)
>  {
> -	struct usbip_task *eh = &ud->eh;
> -	struct task_struct *th;
> -
>  	init_waitqueue_head(&ud->eh_waitq);
>  	ud->event = 0;
>  
> -	usbip_task_init(eh, "usbip_eh", event_handler_loop);
> -
> -	th = kthread_run(usbip_thread, (void *)eh, "usbip");
> -	if (IS_ERR(th)) {
> +	ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh");
> +	if (IS_ERR(ud->eh)) {
>  		printk(KERN_WARNING
>  			"Unable to start control thread\n");
> -		return PTR_ERR(th);
> +		return PTR_ERR(ud->eh);
>  	}
> -
> -	wait_for_completion(&eh->thread_done);
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(usbip_start_eh);
>  
>  void usbip_stop_eh(struct usbip_device *ud)
>  {
> -	struct usbip_task *eh = &ud->eh;
> -
> -	if (eh->thread == current)
> +	if (ud->eh == current)
>  		return; /* do not wait for myself */
>  
> -	wait_for_completion(&eh->thread_done);
> +	kthread_stop(ud->eh);
>  	usbip_dbg_eh("usbip_eh has finished\n");
>  }
>  EXPORT_SYMBOL_GPL(usbip_stop_eh);
> diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h
> index 41a1fe5..ed51983 100644
> --- a/drivers/staging/usbip/vhci.h
> +++ b/drivers/staging/usbip/vhci.h
> @@ -116,8 +116,8 @@ extern struct attribute_group dev_attr_group;
>  /* vhci_hcd.c */
>  void rh_port_connect(int rhport, enum usb_device_speed speed);
>  void rh_port_disconnect(int rhport);
> -void vhci_rx_loop(struct usbip_task *ut);
> -void vhci_tx_loop(struct usbip_task *ut);
> +int vhci_rx_loop(void *data);
> +int vhci_tx_loop(void *data);
>  
>  #define hardware		(&the_controller->pdev.dev)
>  
> diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
> index 08bd26a..f048b47 100644
> --- a/drivers/staging/usbip/vhci_hcd.c
> +++ b/drivers/staging/usbip/vhci_hcd.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/slab.h>
> +#include <linux/kthread.h>
>  
>  #include "usbip_common.h"
>  #include "vhci.h"
> @@ -840,7 +841,10 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
>  		kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
>  	}
>  
> -	usbip_stop_threads(&vdev->ud);
> +	/* kill threads related to this sdev, if v.c. exists */
> +	kthread_stop(vdev->ud.tcp_rx);
> +	kthread_stop(vdev->ud.tcp_tx);
> +
>  	usbip_uinfo("stop threads\n");
>  
>  	/* active connection is closed */
> @@ -907,8 +911,8 @@ static void vhci_device_init(struct vhci_device *vdev)
>  {
>  	memset(vdev, 0, sizeof(*vdev));
>  
> -	usbip_task_init(&vdev->ud.tcp_rx, "vhci_rx", vhci_rx_loop);
> -	usbip_task_init(&vdev->ud.tcp_tx, "vhci_tx", vhci_tx_loop);
> +	vdev->ud.tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
> +	vdev->ud.tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
>  
>  	vdev->ud.side   = USBIP_VHCI;
>  	vdev->ud.status = VDEV_ST_NULL;
> diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
> index 8147d72..b03b277 100644
> --- a/drivers/staging/usbip/vhci_rx.c
> +++ b/drivers/staging/usbip/vhci_rx.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/slab.h>
> +#include <linux/kthread.h>
>  
>  #include "usbip_common.h"
>  #include "vhci.h"
> @@ -235,22 +236,17 @@ static void vhci_rx_pdu(struct usbip_device *ud)
>  
>  /*-------------------------------------------------------------------------*/
>  
> -void vhci_rx_loop(struct usbip_task *ut)
> +int vhci_rx_loop(void *data)
>  {
> -	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_rx);
> -
> -
> -	while (1) {
> -		if (signal_pending(current)) {
> -			usbip_dbg_vhci_rx("signal catched!\n");
> -			break;
> -		}
> +	struct usbip_device *ud = data;
>  
>  
> +	while (!kthread_should_stop()) {
>  		if (usbip_event_happened(ud))
>  			break;
>  
>  		vhci_rx_pdu(ud);
>  	}
> -}
>  
> +	return 0;
> +}
> diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
> index f6e34e0..3f2459f 100644
> --- a/drivers/staging/usbip/vhci_sysfs.c
> +++ b/drivers/staging/usbip/vhci_sysfs.c
> @@ -220,16 +220,13 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
>  	vdev->ud.tcp_socket = socket;
>  	vdev->ud.status     = VDEV_ST_NOTASSIGNED;
>  
> +	wake_up_process(vdev->ud.tcp_rx);
> +	wake_up_process(vdev->ud.tcp_tx);
> +
>  	spin_unlock(&vdev->ud.lock);
>  	spin_unlock(&the_controller->lock);
>  	/* end the lock */

Is it ok to call wake_up_process() while holding
the spinlocks? (I don't know - just noticed the
comment which used to be there)

> -	/*
> -	 * this function will sleep, so should be out of the lock. but, it's ok
> -	 * because we already marked vdev as being used. really?
> -	 */
> -	usbip_start_threads(&vdev->ud);
> -
>  	rh_port_connect(rhport, speed);
>  
>  	return count;
> diff --git a/drivers/staging/usbip/vhci_tx.c b/drivers/staging/usbip/vhci_tx.c
> index e1c1f71..6d065b9 100644
> --- a/drivers/staging/usbip/vhci_tx.c
> +++ b/drivers/staging/usbip/vhci_tx.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/slab.h>
> +#include <linux/kthread.h>
>  
>  #include "usbip_common.h"
>  #include "vhci.h"
> @@ -215,17 +216,12 @@ static int vhci_send_cmd_unlink(struct vhci_device *vdev)
>  
>  /*-------------------------------------------------------------------------*/
>  
> -void vhci_tx_loop(struct usbip_task *ut)
> +int vhci_tx_loop(void *data)
>  {
> -	struct usbip_device *ud = container_of(ut, struct usbip_device, tcp_tx);
> +	struct usbip_device *ud = data;
>  	struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
>  
> -	while (1) {
> -		if (signal_pending(current)) {
> -			usbip_uinfo("vhci_tx signal catched\n");
> -			break;
> -		}
> -
> +	while (!kthread_should_stop()) {
>  		if (vhci_send_cmd_submit(vdev) < 0)
>  			break;
>  

vhci_tx_loop() also needs the kthread_should_stop
in its wait_event_interruptible, I think.

--- a/drivers/staging/usbip/vhci_tx.c
+++ b/drivers/staging/usbip/vhci_tx.c
@@ -230,7 +230,8 @@ int vhci_tx_loop(void *data)
 
                wait_event_interruptible(vdev->waitq_tx,
                                (!list_empty(&vdev->priv_tx) ||
-                                !list_empty(&vdev->unlink_tx)));
+                                !list_empty(&vdev->unlink_tx)) ||
+                               kthread_should_stop());
 
                usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
        }

> @@ -238,4 +234,6 @@ void vhci_tx_loop(struct usbip_task *ut)
>  
>  		usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
>  	}
> +
> +	return 0;
>  }

I need to leave now for the next couple of days,
so this is a bit rushed.

I can take a closer look and do tests in different
setups during the next week.

	Max

  reply	other threads:[~2011-01-28 17:54 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-25 22:17 [RFC 00/20] Proposal for remaining BKL users Arnd Bergmann
2011-01-25 22:17 ` Arnd Bergmann
2011-01-25 22:17 ` [PATCH 01/20] drm/i810: remove the BKL Arnd Bergmann
2011-01-25 22:17 ` [PATCH 02/20] drm: remove i830 driver Arnd Bergmann
2011-01-25 22:17 ` [PATCH 03/20] staging/usbip: convert to kthread Arnd Bergmann
2011-01-28 17:53   ` Max Vozeler [this message]
2011-01-28 18:48     ` Arnd Bergmann
2011-03-01 22:15     ` Arnd Bergmann
2011-01-25 22:17 ` [PATCH 04/20] staging/cx25721: serialize access to devlist Arnd Bergmann
2011-01-26 16:23   ` Palash Bandyopadhyay
2011-01-31 21:37   ` Greg KH
2011-01-25 22:17 ` [PATCH 05/20] staging/go7007: remove the BKL Arnd Bergmann
2011-01-25 22:17 ` [PATCH 06/20] staging: Remove autofs3 Arnd Bergmann
2011-01-26  7:41   ` H. Peter Anvin
2011-01-25 22:17 ` [PATCH 07/20] staging: remove smbfs Arnd Bergmann
2011-01-25 22:17 ` [PATCH 08/20] adfs: remove the big kernel lock Arnd Bergmann
2011-01-25 22:20   ` Russell King
2011-01-25 22:17 ` [PATCH 09/20] hpfs: rename big kernel lock to hpfs_lock Arnd Bergmann
2011-01-25 22:17 ` [PATCH 10/20] hpfs: replace BKL with a global mutex Arnd Bergmann
2011-01-26  0:15   ` Andi Kleen
2011-01-26  0:19   ` Andi Kleen
2011-01-26 12:48     ` [PATCH v2] hpfs: remove the BKL Arnd Bergmann
2011-01-26 12:50     ` [PATCH 10/20] hpfs: replace BKL with a global mutex Arnd Bergmann
2011-01-26 16:52       ` Andi Kleen
2011-01-27  5:01         ` Nick Piggin
2011-01-27 10:57           ` Miklos Szeredi
2011-01-25 22:17 ` [PATCH 11/20] hpfs: move to drivers/staging Arnd Bergmann
2011-02-07 16:17   ` Mikulas Patocka
2011-02-07 19:31     ` Arnd Bergmann
2011-01-25 22:17 ` [PATCH 12/20] x25: remove the BKL Arnd Bergmann
2011-01-27 10:07   ` Andrew Hendry
2011-01-27 12:17     ` Arnd Bergmann
2011-01-27 12:38       ` [PATCH v2] " Arnd Bergmann
2011-01-27 13:20         ` Eric Dumazet
2011-01-27 13:43           ` Arnd Bergmann
2011-01-25 22:17 ` [PATCH 13/20] appletalk: move to staging Arnd Bergmann
2011-01-25 22:17 ` [PATCH 14/20] staging/appletalk: remove the BKL Arnd Bergmann
2011-01-25 22:29   ` David Miller
2011-01-26 12:57     ` Arnd Bergmann
2011-01-25 22:17 ` [PATCH 15/20] ufs: " Arnd Bergmann
2011-01-26  2:30   ` Nick Bowler
2011-01-26 12:53     ` Arnd Bergmann
2011-01-27  5:47   ` Nick Piggin
2011-01-27 13:13     ` Arnd Bergmann
2011-01-25 22:17 ` [PATCH 16/20] ipx: " Arnd Bergmann
2011-01-25 22:17 ` [PATCH 17/20] tracing: don't trace " Arnd Bergmann
2011-01-25 22:28   ` Frederic Weisbecker
2011-01-25 22:17 ` [PATCH 18/20] rtmutex-tester: remove BKL tests Arnd Bergmann
2011-01-26 15:00   ` [tip:core/locking] rtmutex-tester: Remove " tip-bot for Arnd Bergmann
2011-02-22 20:57   ` [tip:irq/core] rtmutex: tester: " tip-bot for Arnd Bergmann
2011-01-25 22:17 ` [PATCH 19/20] drivers: remove extraneous includes of smp_lock.h Arnd Bergmann
2011-01-25 22:17 ` [PATCH 20/20] BKL: That's all, folks Arnd Bergmann
2011-01-26  6:19   ` Ingo Molnar
2011-01-26  8:47     ` Alan Cox
2011-01-26 11:01       ` Ingo Molnar
2011-01-26 11:22   ` Thomas Gleixner
2011-01-26  2:22 ` [RFC 00/20] Proposal for remaining BKL users Greg KH
2011-01-26  2:22   ` Greg KH
2011-01-26 11:31   ` Arnd Bergmann
2011-01-26 11:31     ` Arnd Bergmann
2011-01-26 11:58     ` Mauro Carvalho Chehab
2011-01-26 13:45       ` Arnd Bergmann
2011-01-26 13:45         ` Arnd Bergmann
2011-01-26 13:45         ` Arnd Bergmann
2011-01-26 16:24         ` Palash Bandyopadhyay

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4D4302AC.3050903@vozeler.com \
    --to=max@vozeler.com \
    --cc=arnd@arndb.de \
    --cc=gregkh@suse.de \
    --cc=hirofuchi@users.sourceforge.net \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.