[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>
This commit is contained in:
James Bottomley
2006-02-23 14:27:18 -06:00
committed by James Bottomley
parent 1fa44ecad2
commit ffedb45225
5 changed files with 46 additions and 77 deletions

View File

@@ -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);