Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1975b337 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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()
parents 7b3064f0 3b054179
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+9 −0
Original line number Diff line number Diff line
@@ -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);
+49 −6
Original line number Diff line number Diff line
@@ -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);
+7 −1
Original line number Diff line number Diff line
@@ -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);
+4 −0
Original line number Diff line number Diff line
@@ -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);
Loading