SCSI fixes on 20190601
Six minor fixes to device drivers and one to the multipath alua handler. The most extensive fix is the zfcp port remove prevention one, but it's impact is only s390. Signed-off-by: James E.J. Bottomley <jejb@linux.ibm.com> -----BEGIN PGP SIGNATURE----- iJwEABMIAEQWIQTnYEDbdso9F2cI+arnQslM7pishQUCXPJlASYcamFtZXMuYm90 dG9tbGV5QGhhbnNlbnBhcnRuZXJzaGlwLmNvbQAKCRDnQslM7pishSElAP9A/qo+ mLomrWOPMGqkQKOX7Mp3sP5lMllbvPndrR+9KQD/eDzFp3HCyUO2OFd6aR7/X90H IZ+cd/wJCSHenKMJOX8= =NFnR -----END PGP SIGNATURE----- Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi Pull SCSI fixes from James Bottomley: "Six minor fixes to device drivers and one to the multipath alua handler. The most extensive fix is the zfcp port remove prevention one, but it's impact is only s390" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: libsas: delete sas port if expander discover failed scsi: libsas: only clear phy->in_shutdown after shutdown event done scsi: scsi_dh_alua: Fix possible null-ptr-deref scsi: smartpqi: properly set both the DMA mask and the coherent DMA mask scsi: zfcp: fix to prevent port_remove with pure auto scan LUNs (only sdevs) scsi: zfcp: fix missing zfcp_port reference put on -EBUSY from port_remove scsi: libcxgbi: add a check for NULL pointer in cxgbi_check_route()
This commit is contained in:
commit
1975b337ce
|
@ -167,6 +167,7 @@ extern const struct attribute_group *zfcp_port_attr_groups[];
|
|||
extern struct mutex zfcp_sysfs_port_units_mutex;
|
||||
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
|
||||
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
|
||||
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port);
|
||||
|
||||
/* zfcp_unit.c */
|
||||
extern int zfcp_unit_add(struct zfcp_port *, u64);
|
||||
|
|
|
@ -129,6 +129,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
|
|||
|
||||
zfcp_sdev->erp_action.port = port;
|
||||
|
||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||
if (zfcp_sysfs_port_is_removing(port)) {
|
||||
/* port is already gone */
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
|
||||
return -ENXIO;
|
||||
}
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
|
||||
unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
|
||||
if (unit)
|
||||
put_device(&unit->dev);
|
||||
|
|
|
@ -235,6 +235,53 @@ static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
|
|||
|
||||
DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
|
||||
|
||||
static void zfcp_sysfs_port_set_removing(struct zfcp_port *const port)
|
||||
{
|
||||
lockdep_assert_held(&zfcp_sysfs_port_units_mutex);
|
||||
atomic_set(&port->units, -1);
|
||||
}
|
||||
|
||||
bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port)
|
||||
{
|
||||
lockdep_assert_held(&zfcp_sysfs_port_units_mutex);
|
||||
return atomic_read(&port->units) == -1;
|
||||
}
|
||||
|
||||
static bool zfcp_sysfs_port_in_use(struct zfcp_port *const port)
|
||||
{
|
||||
struct zfcp_adapter *const adapter = port->adapter;
|
||||
unsigned long flags;
|
||||
struct scsi_device *sdev;
|
||||
bool in_use = true;
|
||||
|
||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||
if (atomic_read(&port->units) > 0)
|
||||
goto unlock_port_units_mutex; /* zfcp_unit(s) under port */
|
||||
|
||||
spin_lock_irqsave(adapter->scsi_host->host_lock, flags);
|
||||
__shost_for_each_device(sdev, adapter->scsi_host) {
|
||||
const struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev);
|
||||
|
||||
if (sdev->sdev_state == SDEV_DEL ||
|
||||
sdev->sdev_state == SDEV_CANCEL)
|
||||
continue;
|
||||
if (zsdev->port != port)
|
||||
continue;
|
||||
/* alive scsi_device under port of interest */
|
||||
goto unlock_host_lock;
|
||||
}
|
||||
|
||||
/* port is about to be removed, so no more unit_add or slave_alloc */
|
||||
zfcp_sysfs_port_set_removing(port);
|
||||
in_use = false;
|
||||
|
||||
unlock_host_lock:
|
||||
spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags);
|
||||
unlock_port_units_mutex:
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
return in_use;
|
||||
}
|
||||
|
||||
static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
@ -257,15 +304,11 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
|||
else
|
||||
retval = 0;
|
||||
|
||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||
if (atomic_read(&port->units) > 0) {
|
||||
if (zfcp_sysfs_port_in_use(port)) {
|
||||
retval = -EBUSY;
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */
|
||||
goto out;
|
||||
}
|
||||
/* port is about to be removed, so no more unit_add */
|
||||
atomic_set(&port->units, -1);
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
|
||||
write_lock_irq(&adapter->port_list_lock);
|
||||
list_del(&port->list);
|
||||
|
|
|
@ -124,7 +124,7 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
|||
int retval = 0;
|
||||
|
||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||
if (atomic_read(&port->units) == -1) {
|
||||
if (zfcp_sysfs_port_is_removing(port)) {
|
||||
/* port is already gone */
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
|
@ -168,8 +168,14 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
|||
write_lock_irq(&port->unit_list_lock);
|
||||
list_add_tail(&unit->list, &port->unit_list);
|
||||
write_unlock_irq(&port->unit_list_lock);
|
||||
/*
|
||||
* lock order: shost->scan_mutex before zfcp_sysfs_port_units_mutex
|
||||
* due to zfcp_unit_scsi_scan() => zfcp_scsi_slave_alloc()
|
||||
*/
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
|
||||
zfcp_unit_scsi_scan(unit);
|
||||
return retval;
|
||||
|
||||
out:
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
|
|
|
@ -639,6 +639,10 @@ cxgbi_check_route(struct sockaddr *dst_addr, int ifindex)
|
|||
|
||||
if (ndev->flags & IFF_LOOPBACK) {
|
||||
ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
|
||||
if (!ndev) {
|
||||
err = -ENETUNREACH;
|
||||
goto rel_neigh;
|
||||
}
|
||||
mtu = ndev->mtu;
|
||||
pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
|
||||
n->dev->name, ndev->name, mtu);
|
||||
|
|
|
@ -1160,10 +1160,8 @@ static int __init alua_init(void)
|
|||
int r;
|
||||
|
||||
kaluad_wq = alloc_workqueue("kaluad", WQ_MEM_RECLAIM, 0);
|
||||
if (!kaluad_wq) {
|
||||
/* Temporary failure, bypass */
|
||||
return SCSI_DH_DEV_TEMP_BUSY;
|
||||
}
|
||||
if (!kaluad_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
r = scsi_register_device_handler(&alua_dh);
|
||||
if (r != 0) {
|
||||
|
|
|
@ -1019,6 +1019,8 @@ static struct domain_device *sas_ex_discover_expander(
|
|||
list_del(&child->dev_list_node);
|
||||
spin_unlock_irq(&parent->port->dev_list_lock);
|
||||
sas_put_device(child);
|
||||
sas_port_delete(phy->port);
|
||||
phy->port = NULL;
|
||||
return NULL;
|
||||
}
|
||||
list_add_tail(&child->siblings, &parent->ex_dev.children);
|
||||
|
|
|
@ -35,7 +35,6 @@ static void sas_phye_loss_of_signal(struct work_struct *work)
|
|||
struct asd_sas_event *ev = to_asd_sas_event(work);
|
||||
struct asd_sas_phy *phy = ev->phy;
|
||||
|
||||
phy->in_shutdown = 0;
|
||||
phy->error = 0;
|
||||
sas_deform_port(phy, 1);
|
||||
}
|
||||
|
@ -45,7 +44,6 @@ static void sas_phye_oob_done(struct work_struct *work)
|
|||
struct asd_sas_event *ev = to_asd_sas_event(work);
|
||||
struct asd_sas_phy *phy = ev->phy;
|
||||
|
||||
phy->in_shutdown = 0;
|
||||
phy->error = 0;
|
||||
}
|
||||
|
||||
|
@ -126,6 +124,7 @@ static void sas_phye_shutdown(struct work_struct *work)
|
|||
ret);
|
||||
} else
|
||||
pr_notice("phy%d is not enabled, cannot shutdown\n", phy->id);
|
||||
phy->in_shutdown = 0;
|
||||
}
|
||||
|
||||
/* ---------- Phy class registration ---------- */
|
||||
|
|
|
@ -7291,7 +7291,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info)
|
|||
else
|
||||
mask = DMA_BIT_MASK(32);
|
||||
|
||||
rc = dma_set_mask(&ctrl_info->pci_dev->dev, mask);
|
||||
rc = dma_set_mask_and_coherent(&ctrl_info->pci_dev->dev, mask);
|
||||
if (rc) {
|
||||
dev_err(&ctrl_info->pci_dev->dev, "failed to set DMA mask\n");
|
||||
goto disable_device;
|
||||
|
|
Loading…
Reference in a new issue