diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2006-02-23 15:27:18 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-02-28 00:37:45 -0500 |
commit | ffedb4522571ac170f941678d138a31bc0884ab4 (patch) | |
tree | 996572da6cecf4295c730b13c959d5d19836a8c5 /drivers/scsi/scsi_lib.c | |
parent | 1fa44ecad2b86475e038aed81b0bf333fa484f8b (diff) |
[SCSI] fix scsi process problems and clean up the target reap issues
In order to use the new execute_in_process_context() API, you have to
provide it with the work storage, which I do in SCSI in scsi_device and
scsi_target, but which also means that we can no longer queue up the
target reaps, so instead I moved the target to a state model which
allows target_alloc to detect if we've received a dying target and wait
for it to be gone. Hopefully, this should also solve the target
namespace race.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r-- | drivers/scsi/scsi_lib.c | 58 |
1 files changed, 0 insertions, 58 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index eab303d148d8..3042520c413c 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -2257,61 +2257,3 @@ scsi_target_unblock(struct device *dev) | |||
2257 | device_for_each_child(dev, NULL, target_unblock); | 2257 | device_for_each_child(dev, NULL, target_unblock); |
2258 | } | 2258 | } |
2259 | EXPORT_SYMBOL_GPL(scsi_target_unblock); | 2259 | EXPORT_SYMBOL_GPL(scsi_target_unblock); |
2260 | |||
2261 | |||
2262 | struct work_queue_work { | ||
2263 | struct work_struct work; | ||
2264 | void (*fn)(void *); | ||
2265 | void *data; | ||
2266 | }; | ||
2267 | |||
2268 | static void execute_in_process_context_work(void *data) | ||
2269 | { | ||
2270 | void (*fn)(void *data); | ||
2271 | struct work_queue_work *wqw = data; | ||
2272 | |||
2273 | fn = wqw->fn; | ||
2274 | data = wqw->data; | ||
2275 | |||
2276 | kfree(wqw); | ||
2277 | |||
2278 | fn(data); | ||
2279 | } | ||
2280 | |||
2281 | /** | ||
2282 | * scsi_execute_in_process_context - reliably execute the routine with user context | ||
2283 | * @fn: the function to execute | ||
2284 | * @data: data to pass to the function | ||
2285 | * | ||
2286 | * Executes the function immediately if process context is available, | ||
2287 | * otherwise schedules the function for delayed execution. | ||
2288 | * | ||
2289 | * Returns: 0 - function was executed | ||
2290 | * 1 - function was scheduled for execution | ||
2291 | * <0 - error | ||
2292 | */ | ||
2293 | int scsi_execute_in_process_context(void (*fn)(void *data), void *data) | ||
2294 | { | ||
2295 | struct work_queue_work *wqw; | ||
2296 | |||
2297 | if (!in_interrupt()) { | ||
2298 | fn(data); | ||
2299 | return 0; | ||
2300 | } | ||
2301 | |||
2302 | wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC); | ||
2303 | |||
2304 | if (unlikely(!wqw)) { | ||
2305 | printk(KERN_ERR "Failed to allocate memory\n"); | ||
2306 | WARN_ON(1); | ||
2307 | return -ENOMEM; | ||
2308 | } | ||
2309 | |||
2310 | INIT_WORK(&wqw->work, execute_in_process_context_work, wqw); | ||
2311 | wqw->fn = fn; | ||
2312 | wqw->data = data; | ||
2313 | schedule_work(&wqw->work); | ||
2314 | |||
2315 | return 1; | ||
2316 | } | ||
2317 | EXPORT_SYMBOL_GPL(scsi_execute_in_process_context); | ||