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

Commit d224fe0d authored by Calvin Owens's avatar Calvin Owens Committed by James Bottomley
Browse files

mpt2sas: Refcount sas_device objects and fix unsafe list usage



These 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.

Signed-off-by: default avatarCalvin Owens <calvinowens@fb.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
Tested-by: default avatarChaitra Basappa <chaitra.basappa@avagotech.com>
Acked-by: default avatarSreekanth Reddy <sreekanth.reddy@avagotech.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Odin.com>
parent 710105fd
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@
 * @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 MPT2SAS_TARGET {
	struct scsi_target *starget;
@@ -248,6 +249,7 @@ struct MPT2SAS_TARGET {
	u32	flags;
	u8	deleted;
	u8	tm_busy;
	struct _sas_device *sdev;
};


@@ -376,8 +378,24 @@ struct _sas_device {
	u8	phy;
	u8	responding;
	u8	pfa_led_on;
	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
@@ -1095,7 +1113,9 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *
    u16 handle);
struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
    *ioc, u64 sas_address);
struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address(
struct _sas_device *mpt2sas_get_sdev_by_addr(
    struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
struct _sas_device *__mpt2sas_get_sdev_by_addr(
    struct MPT2SAS_ADAPTER *ioc, u64 sas_address);

void mpt2sas_port_enable_complete(struct MPT2SAS_ADAPTER *ioc);
+331 −149

File changed.

Preview size limit exceeded, changes collapsed.

+8 −4
Original line number Diff line number Diff line
@@ -1323,15 +1323,17 @@ _transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
	int rc;

	spin_lock_irqsave(&ioc->sas_device_lock, flags);
	sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
	sas_device = __mpt2sas_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;
}
@@ -1351,12 +1353,14 @@ _transport_get_bay_identifier(struct sas_rphy *rphy)
	int rc;

	spin_lock_irqsave(&ioc->sas_device_lock, flags);
	sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
	sas_device = __mpt2sas_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;
}