Commit eec217eb authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley

[PATCH] target code updates to support scanned targets

* add scsi_target_block() and scsi_target_unblock() routines which
  take a generic-device.  Side note:  there are mixture of
  scsi_<object>_<action>() and scsi_<action>_<noun>() functions defined
  in the scsi APIs -- going forward are there any 'guides' or
  suggestions on which to choose?
* modify scsi_remove_target() to take a generic-device.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 995f8ecf
...@@ -1935,3 +1935,55 @@ scsi_internal_device_unblock(struct scsi_device *sdev) ...@@ -1935,3 +1935,55 @@ scsi_internal_device_unblock(struct scsi_device *sdev)
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(scsi_internal_device_unblock); EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
static void
device_block(struct scsi_device *sdev, void *data)
{
scsi_internal_device_block(sdev);
}
static int
target_block(struct device *dev, void *data)
{
if (scsi_is_target_device(dev))
starget_for_each_device(to_scsi_target(dev), NULL,
device_block);
return 0;
}
void
scsi_target_block(struct device *dev)
{
if (scsi_is_target_device(dev))
starget_for_each_device(to_scsi_target(dev), NULL,
device_block);
else
device_for_each_child(dev, NULL, target_block);
}
EXPORT_SYMBOL_GPL(scsi_target_block);
static void
device_unblock(struct scsi_device *sdev, void *data)
{
scsi_internal_device_unblock(sdev);
}
static int
target_unblock(struct device *dev, void *data)
{
if (scsi_is_target_device(dev))
starget_for_each_device(to_scsi_target(dev), NULL,
device_unblock);
return 0;
}
void
scsi_target_unblock(struct device *dev)
{
if (scsi_is_target_device(dev))
starget_for_each_device(to_scsi_target(dev), NULL,
device_unblock);
else
device_for_each_child(dev, NULL, target_unblock);
}
EXPORT_SYMBOL_GPL(scsi_target_unblock);
...@@ -1399,7 +1399,7 @@ void scsi_forget_host(struct Scsi_Host *shost) ...@@ -1399,7 +1399,7 @@ void scsi_forget_host(struct Scsi_Host *shost)
spin_lock_irqsave(shost->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) { list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
spin_unlock_irqrestore(shost->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
scsi_remove_target(starget); scsi_remove_target(&starget->dev);
spin_lock_irqsave(shost->host_lock, flags); spin_lock_irqsave(shost->host_lock, flags);
} }
spin_unlock_irqrestore(shost->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
......
...@@ -652,15 +652,7 @@ void scsi_remove_device(struct scsi_device *sdev) ...@@ -652,15 +652,7 @@ void scsi_remove_device(struct scsi_device *sdev)
} }
EXPORT_SYMBOL(scsi_remove_device); EXPORT_SYMBOL(scsi_remove_device);
/** void __scsi_remove_target(struct scsi_target *starget)
* scsi_remove_target - try to remove a target and all its devices
* @starget: the target to remove
*
* Note: This is slightly racy. It is possible that if the user
* requests the addition of another device then the target won't be
* removed.
*/
void scsi_remove_target(struct scsi_target *starget)
{ {
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags; unsigned long flags;
...@@ -679,6 +671,31 @@ void scsi_remove_target(struct scsi_target *starget) ...@@ -679,6 +671,31 @@ void scsi_remove_target(struct scsi_target *starget)
spin_unlock_irqrestore(shost->host_lock, flags); spin_unlock_irqrestore(shost->host_lock, flags);
scsi_target_reap(starget); scsi_target_reap(starget);
} }
/**
* scsi_remove_target - try to remove a target and all its devices
* @dev: generic starget or parent of generic stargets to be removed
*
* Note: This is slightly racy. It is possible that if the user
* requests the addition of another device then the target won't be
* removed.
*/
void scsi_remove_target(struct device *dev)
{
struct device *rdev, *idev, *next;
if (scsi_is_target_device(dev)) {
__scsi_remove_target(to_scsi_target(dev));
return;
}
rdev = get_device(dev);
list_for_each_entry_safe(idev, next, &dev->children, node) {
if (scsi_is_target_device(idev))
__scsi_remove_target(to_scsi_target(idev));
}
put_device(rdev);
}
EXPORT_SYMBOL(scsi_remove_target); EXPORT_SYMBOL(scsi_remove_target);
int scsi_register_driver(struct device_driver *drv) int scsi_register_driver(struct device_driver *drv)
......
...@@ -236,7 +236,9 @@ extern void scsi_target_resume(struct scsi_target *); ...@@ -236,7 +236,9 @@ extern void scsi_target_resume(struct scsi_target *);
extern void scsi_scan_target(struct device *parent, unsigned int channel, extern void scsi_scan_target(struct device *parent, unsigned int channel,
unsigned int id, unsigned int lun, int rescan); unsigned int id, unsigned int lun, int rescan);
extern void scsi_target_reap(struct scsi_target *); extern void scsi_target_reap(struct scsi_target *);
extern void scsi_remove_target(struct scsi_target *); extern void scsi_target_block(struct device *);
extern void scsi_target_unblock(struct device *);
extern void scsi_remove_target(struct device *);
extern const char *scsi_device_state_name(enum scsi_device_state); extern const char *scsi_device_state_name(enum scsi_device_state);
extern int scsi_is_sdev_device(const struct device *); extern int scsi_is_sdev_device(const struct device *);
extern int scsi_is_target_device(const struct device *); extern int scsi_is_target_device(const struct device *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment