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

Commit d5da3040 authored by Brian King's avatar Brian King Committed by James Bottomley
Browse files

[SCSI] ibmvfc: Fix rport add/delete race resulting in oops



Commit 43c8da90 introduced a race
condition which can occur when adding/deleting rports. There are
two possible threads now that can be deleting rports in the ibmvfc
driver, which can result in list_del being called twice, resulting
in an oops. This patch adds a new state to the ibmvfc_target struct
to indicate the target has been removed from the list and is in
the process of being deleted.

Signed-off-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 16115551
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -433,6 +433,9 @@ static void ibmvfc_set_tgt_action(struct ibmvfc_target *tgt,
{
	switch (tgt->action) {
	case IBMVFC_TGT_ACTION_DEL_RPORT:
		if (action == IBMVFC_TGT_ACTION_DELETED_RPORT)
			tgt->action = action;
	case IBMVFC_TGT_ACTION_DELETED_RPORT:
		break;
	default:
		if (action == IBMVFC_TGT_ACTION_DEL_RPORT)
@@ -4193,11 +4196,15 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
	if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
		tgt_dbg(tgt, "Deleting rport\n");
		list_del(&tgt->queue);
		ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT);
		spin_unlock_irqrestore(vhost->host->host_lock, flags);
		fc_remote_port_delete(rport);
		del_timer_sync(&tgt->timer);
		kref_put(&tgt->kref, ibmvfc_release_tgt);
		return;
	} else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) {
		spin_unlock_irqrestore(vhost->host->host_lock, flags);
		return;
	}

	if (rport) {
@@ -4297,6 +4304,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
				rport = tgt->rport;
				tgt->rport = NULL;
				list_del(&tgt->queue);
				ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT);
				spin_unlock_irqrestore(vhost->host->host_lock, flags);
				if (rport)
					fc_remote_port_delete(rport);
+1 −0
Original line number Diff line number Diff line
@@ -597,6 +597,7 @@ enum ibmvfc_target_action {
	IBMVFC_TGT_ACTION_INIT,
	IBMVFC_TGT_ACTION_INIT_WAIT,
	IBMVFC_TGT_ACTION_DEL_RPORT,
	IBMVFC_TGT_ACTION_DELETED_RPORT,
};

struct ibmvfc_target {