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

Commit d1cb5e49 authored by Sreekanth Reddy's avatar Sreekanth Reddy Committed by Martin K. Petersen
Browse files

mpt3sas: Refcount sas_device objects and fix unsafe list usage



sas_device objects can be referenced concurrently throughout the driver.
We need a way to make sure threads can't delete them out from under each
other. This patch adds the refcount and refactors the code to use it.

Additionally, we cannot iterate over the sas_device_list without holding
the lock or we risk corrupting random memory if items are added or
deleted as we iterate. This patch refactors _scsih_probe_sas() to use
the sas_device_list in a safe way.

This patch is ported from the following mpt2sas driver commit
d224fe0d ("mpt2sas: Refcount sas_device objects and fix unsafe list
usage").

Signed-off-by: default avatarSreekanth Reddy <Sreekanth.Reddy@avagotech.com>
Acked-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 42263095
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ struct Mpi2ManufacturingPage11_t {
 * @flags: MPT_TARGET_FLAGS_XXX flags
 * @deleted: target flaged for deletion
 * @tm_busy: target is busy with TM request.
 * @sdev: The sas_device associated with this target
 */
struct MPT3SAS_TARGET {
	struct scsi_target *starget;
@@ -283,6 +284,7 @@ struct MPT3SAS_TARGET {
	u32	flags;
	u8	deleted;
	u8	tm_busy;
	struct _sas_device *sdev;
};


@@ -389,8 +391,24 @@ struct _sas_device {
	u8	pend_sas_rphy_add;
	u8	enclosure_level;
	u8	connector_name[4];
	struct kref refcount;
};

static inline void sas_device_get(struct _sas_device *s)
{
	kref_get(&s->refcount);
}

static inline void sas_device_free(struct kref *r)
{
	kfree(container_of(r, struct _sas_device, refcount));
}

static inline void sas_device_put(struct _sas_device *s)
{
	kref_put(&s->refcount, sas_device_free);
}

/**
 * struct _raid_device - raid volume link list
 * @list: sas device list
@@ -1148,7 +1166,9 @@ struct _sas_node *mpt3sas_scsih_expander_find_by_handle(
	struct MPT3SAS_ADAPTER *ioc, u16 handle);
struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address(
	struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_device *mpt3sas_scsih_sas_device_find_by_sas_address(
struct _sas_device *mpt3sas_get_sdev_by_addr(
	 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_device *__mpt3sas_get_sdev_by_addr(
	 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);

void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
+331 −149

File changed.

Preview size limit exceeded, changes collapsed.

+12 −6
Original line number Diff line number Diff line
@@ -734,7 +734,7 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
	rphy->identify = mpt3sas_port->remote_identify;

	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
		sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
		sas_device = mpt3sas_get_sdev_by_addr(ioc,
				    mpt3sas_port->remote_identify.sas_address);
		if (!sas_device) {
			dfailprintk(ioc, printk(MPT3SAS_FMT
@@ -750,8 +750,10 @@ mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle,
		    ioc->name, __FILE__, __LINE__, __func__);
	}

	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE)
	if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) {
		sas_device->pend_sas_rphy_add = 0;
		sas_device_put(sas_device);
	}

	if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
		dev_printk(KERN_INFO, &rphy->dev,
@@ -1324,15 +1326,17 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
	int rc;

	spin_lock_irqsave(&ioc->sas_device_lock, flags);
	sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
	    rphy->identify.sas_address);
	if (sas_device) {
		*identifier = sas_device->enclosure_logical_id;
		rc = 0;
		sas_device_put(sas_device);
	} else {
		*identifier = 0;
		rc = -ENXIO;
	}

	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
	return rc;
}
@@ -1352,12 +1356,14 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
	int rc;

	spin_lock_irqsave(&ioc->sas_device_lock, flags);
	sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc,
	sas_device = __mpt3sas_get_sdev_by_addr(ioc,
	    rphy->identify.sas_address);
	if (sas_device)
	if (sas_device) {
		rc = sas_device->slot;
	else
		sas_device_put(sas_device);
	} else {
		rc = -ENXIO;
	}
	spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
	return rc;
}