Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb-storage: fix bugs in the disconnect pathway

This patch (as961) fixes a couple of bugs in the disconnect pathway of
usb-storage.

The first problem, which apparently has been around for a while
although nobody noticed it, shows up when an aborted command is still
pending when a disconnect occurs. The SCSI error-handler will
continue to wait in command_abort() until the us->notify completion is
signalled. Thus quiesce_and_remove_host() needs to signal it.

The second problem was introduced recently along with autosuspend
support. Since usb_stor_scan_thread() now calls
usb_autopm_put_interface() before exiting, we can't simply leave the
scanning thread running after a disconnect; we must wait until the
thread exits. This is solved by adding a new struct completion to the
private data structure. Fortuitously, it allows the removal of the
rather clunky mechanism used in the past to insure that all threads
have finished before the module is unloaded.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
CC: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Alan Stern and committed by
Greg Kroah-Hartman
2f67cd5b fa0de2b6

+7 -27
+6 -27
drivers/usb/storage/usb.c
··· 112 112 MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); 113 113 114 114 115 - /* These are used to make sure the module doesn't unload before all the 116 - * threads have exited. 117 - */ 118 - static atomic_t total_threads = ATOMIC_INIT(0); 119 - static DECLARE_COMPLETION(threads_gone); 120 - 121 - 122 115 /* 123 116 * The entries in this table correspond, line for line, 124 117 * with the entries of us_unusual_dev_list[]. ··· 872 879 usb_stor_stop_transport(us); 873 880 wake_up(&us->delay_wait); 874 881 875 - /* It doesn't matter if the SCSI-scanning thread is still running. 876 - * The thread will exit when it sees the DISCONNECTING flag. */ 877 - 878 882 /* queuecommand won't accept any new commands and the control 879 883 * thread won't execute a previously-queued command. If there 880 884 * is such a command pending, complete it with an error. */ ··· 881 891 scsi_lock(host); 882 892 us->srb->scsi_done(us->srb); 883 893 us->srb = NULL; 894 + complete(&us->notify); /* in case of an abort */ 884 895 scsi_unlock(host); 885 896 } 886 897 mutex_unlock(&us->dev_mutex); 887 898 888 899 /* Now we own no commands so it's safe to remove the SCSI host */ 889 900 scsi_remove_host(host); 901 + 902 + /* Wait for the SCSI-scanning thread to stop */ 903 + wait_for_completion(&us->scanning_done); 890 904 } 891 905 892 906 /* Second stage of disconnect processing: deallocate all resources */ ··· 941 947 /* Should we unbind if no devices were detected? */ 942 948 } 943 949 944 - scsi_host_put(us_to_host(us)); 945 950 usb_autopm_put_interface(us->pusb_intf); 946 - complete_and_exit(&threads_gone, 0); 951 + complete_and_exit(&us->scanning_done, 0); 947 952 } 948 953 949 954 ··· 977 984 init_MUTEX_LOCKED(&(us->sema)); 978 985 init_completion(&(us->notify)); 979 986 init_waitqueue_head(&us->delay_wait); 987 + init_completion(&us->scanning_done); 980 988 981 989 /* Associate the us_data structure with the USB device */ 982 990 result = associate_dev(us, intf); ··· 1027 1033 goto BadDevice; 1028 1034 } 1029 1035 1030 - /* Take a reference to the host for the scanning thread and 1031 - * count it among all the threads we have launched. Then 1032 - * start it up. */ 1033 - scsi_host_get(us_to_host(us)); 1034 - atomic_inc(&total_threads); 1035 1036 usb_autopm_get_interface(intf); /* dropped in the scanning thread */ 1036 1037 wake_up_process(th); 1037 1038 ··· 1092 1103 */ 1093 1104 US_DEBUGP("-- calling usb_deregister()\n"); 1094 1105 usb_deregister(&usb_storage_driver) ; 1095 - 1096 - /* Don't return until all of our control and scanning threads 1097 - * have exited. Since each thread signals threads_gone as its 1098 - * last act, we have to call wait_for_completion the right number 1099 - * of times. 1100 - */ 1101 - while (atomic_read(&total_threads) > 0) { 1102 - wait_for_completion(&threads_gone); 1103 - atomic_dec(&total_threads); 1104 - } 1105 1106 1106 1107 usb_usual_clear_present(USB_US_TYPE_STOR); 1107 1108 }
+1
drivers/usb/storage/usb.h
··· 150 150 struct semaphore sema; /* to sleep thread on */ 151 151 struct completion notify; /* thread begin/end */ 152 152 wait_queue_head_t delay_wait; /* wait during scan, reset */ 153 + struct completion scanning_done; /* wait for scan thread */ 153 154 154 155 /* subdriver information */ 155 156 void *extra; /* Any extra data */