diff options
author | James Bottomley <James.Bottomley@steeleye.com> | 2006-02-23 21:27:18 +0100 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-02-28 06:37:45 +0100 |
commit | ffedb4522571ac170f941678d138a31bc0884ab4 (patch) | |
tree | 996572da6cecf4295c730b13c959d5d19836a8c5 /drivers/scsi/scsi_lib.c | |
parent | [SCSI] add execute_in_process_context() API (diff) | |
download | linux-ffedb4522571ac170f941678d138a31bc0884ab4.tar.xz linux-ffedb4522571ac170f941678d138a31bc0884ab4.zip |
[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) device_for_each_child(dev, NULL, target_unblock); } EXPORT_SYMBOL_GPL(scsi_target_unblock); - - -struct work_queue_work { - struct work_struct work; - void (*fn)(void *); - void *data; -}; - -static void execute_in_process_context_work(void *data) -{ - void (*fn)(void *data); - struct work_queue_work *wqw = data; - - fn = wqw->fn; - data = wqw->data; - - kfree(wqw); - - fn(data); -} - -/** - * scsi_execute_in_process_context - reliably execute the routine with user context - * @fn: the function to execute - * @data: data to pass to the function - * - * Executes the function immediately if process context is available, - * otherwise schedules the function for delayed execution. - * - * Returns: 0 - function was executed - * 1 - function was scheduled for execution - * <0 - error - */ -int scsi_execute_in_process_context(void (*fn)(void *data), void *data) -{ - struct work_queue_work *wqw; - - if (!in_interrupt()) { - fn(data); - return 0; - } - - wqw = kmalloc(sizeof(struct work_queue_work), GFP_ATOMIC); - - if (unlikely(!wqw)) { - printk(KERN_ERR "Failed to allocate memory\n"); - WARN_ON(1); - return -ENOMEM; - } - - INIT_WORK(&wqw->work, execute_in_process_context_work, wqw); - wqw->fn = fn; - wqw->data = data; - schedule_work(&wqw->work); - - return 1; -} -EXPORT_SYMBOL_GPL(scsi_execute_in_process_context); |