Commit 7eae626e authored by Xingui Yang's avatar Xingui Yang Committed by Slim6882
Browse files

[Backport]scsi: libsas: Fix disk not being scanned in after being removed

mainline inclusion
from mainline-v6.8-rc1
commit 8e68a458bcf5b5cb9c3624598bae28f08251601f
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB18PN
CVE: NA

Reference: https://lore.kernel.org/r/20240307141413.48049-3-yangxingui@huawei.com



------------------------------------------------------------------

As of commit d8649fc1 ("scsi: libsas: Do discovery on empty PHY to
update PHY info"), do discovery will send a new SMP_DISCOVER and update
phy->phy_change_count. We found that if the disk is reconnected and phy
change_count changes at this time, the disk scanning process will not be
triggered.

Therefore, call sas_set_ex_phy() to update the PHY info with the results of
the last query. And because the previous phy info will be used when calling
sas_unregister_devs_sas_addr(), sas_unregister_devs_sas_addr() should be
called before sas_set_ex_phy().

Fixes: d8649fc1 ("scsi: libsas: Do discovery on empty PHY to update PHY info")
Signed-off-by: default avatarXingui Yang <yangxingui@huawei.com>
Link: https://lore.kernel.org/r/20240307141413.48049-3-yangxingui@huawei.com


Reviewed-by: default avatarJohn Garry <john.g.garry@oracle.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: default avatarSlim6882 <yangjunshuo@huawei.com>
parent b12a21e0
Loading
Loading
Loading
Loading
+22 −10
Original line number Diff line number Diff line
@@ -2023,6 +2023,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
	struct expander_device *ex = &dev->ex_dev;
	struct ex_phy *phy = &ex->ex_phy[phy_id];
	enum sas_device_type type = SAS_PHY_UNUSED;
	struct smp_disc_resp *disc_resp;
	u8 sas_addr[SAS_ADDR_SIZE];
	char msg[80] = "";
	int res;
@@ -2034,33 +2035,41 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
		 SAS_ADDR(dev->sas_addr), phy_id, msg);

	memset(sas_addr, 0, SAS_ADDR_SIZE);
	res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
	disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
	if (!disc_resp)
		return -ENOMEM;

	res = sas_get_phy_discover(dev, phy_id, disc_resp);
	switch (res) {
	case SMP_RESP_NO_PHY:
		phy->phy_state = PHY_NOT_PRESENT;
		sas_unregister_devs_sas_addr(dev, phy_id, last);
		return res;
		goto out_free_resp;
	case SMP_RESP_PHY_VACANT:
		phy->phy_state = PHY_VACANT;
		sas_unregister_devs_sas_addr(dev, phy_id, last);
		return res;
		goto out_free_resp;
	case SMP_RESP_FUNC_ACC:
		break;
	case -ECOMM:
		break;
	default:
		return res;
		goto out_free_resp;
	}

	if (res == 0)
		sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, &type);

	if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {
		phy->phy_state = PHY_EMPTY;
		sas_unregister_devs_sas_addr(dev, phy_id, last);
		/*
		 * Even though the PHY is empty, for convenience we discover
		 * the PHY to update the PHY info, like negotiated linkrate.
		 * Even though the PHY is empty, for convenience we update
		 * the PHY info, like negotiated linkrate.
		 */
		sas_ex_phy_discover(dev, phy_id);
		return res;
		if (res == 0)
			sas_set_ex_phy(dev, phy_id, disc_resp);
		goto out_free_resp;
	} else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
		   dev_type_flutter(type, phy->attached_dev_type)) {
		struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
@@ -2072,7 +2081,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
			action = ", needs recovery";
		pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
			 SAS_ADDR(dev->sas_addr), phy_id, action);
		return res;
		goto out_free_resp;
	}

	/* we always have to delete the old device when we went here */
@@ -2081,7 +2090,10 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
		SAS_ADDR(phy->attached_sas_addr));
	sas_unregister_devs_sas_addr(dev, phy_id, last);

	return sas_discover_new(dev, phy_id);
	res = sas_discover_new(dev, phy_id);
out_free_resp:
	kfree(disc_resp);
	return res;
}

/**