* [PATCH v3 0/2] libsas: rediscover improvements for linkrate/sas_addr changes
@ 2026-05-15 8:45 Xingui Yang
2026-05-15 8:45 ` [PATCH v3 1/2] scsi: libsas: refactor sas_ex_to_ata() using new helper sas_ex_to_dev() Xingui Yang
2026-05-15 8:45 ` [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover Xingui Yang
0 siblings, 2 replies; 10+ messages in thread
From: Xingui Yang @ 2026-05-15 8:45 UTC (permalink / raw)
To: john.g.garry, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, yangxingui,
liuyonglong, kangfenglong
When a device attached to an expander phy experiences a linkrate change
(e.g., due to cable reconnection or negotiation), the current code in
sas_rediscover_dev() treats it as "broadcast flutter" and takes no action
if the SAS address and device type remain unchanged.
This series is a new version based on John Garry's suggestion [1] to
check the linkrate and mark the device as gone and rediscover when
flutter occurs, replacing the previous v2 patch series that used lldd
callbacks.
The previous v2 approach added lldd_dev_info_update callback which John
commented as "seem fragile and too specialized" [2]. This v3 series adopts
a simpler approach that directly checks linkrate/sas_addr changes in
sas_rediscover_dev() and triggers rediscovery using libsas's standard
async discovery pattern.
This aligns with Jason Yan's earlier work [3] which was verified to
solve the linkrate change issue.
Changes from v2:
- Drop lldd_dev_info_update callback approach per John Garry's suggestion
- Drop hisi_sas specific changes (no longer needed without callback)
- Use libsas's async discovery pattern for rediscovery
- Add sas_addr change detection alongside linkrate change
[1] https://lore.kernel.org/linux-scsi/c4e4c99f-a13c-4e28-8650-48be1f96d7cf@oracle.com/
[2] https://lore.kernel.org/linux-scsi/28bd9d5b-f597-0aae-5340-bd951b2083aa@huawei.com/
[3] https://lore.kernel.org/linux-scsi/20190130082412.9357-6-yanaijie@huawei.com/
Your Name (2):
scsi: libsas: refactor sas_ex_to_ata() using new helper
sas_ex_to_dev()
scsi: libsas: Add linkrate and sas_addr change detection in rediscover
drivers/scsi/libsas/sas_expander.c | 44 ++++++++++++++++++++++++------
drivers/scsi/libsas/sas_internal.h | 1 +
2 files changed, 37 insertions(+), 8 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 1/2] scsi: libsas: refactor sas_ex_to_ata() using new helper sas_ex_to_dev()
2026-05-15 8:45 [PATCH v3 0/2] libsas: rediscover improvements for linkrate/sas_addr changes Xingui Yang
@ 2026-05-15 8:45 ` Xingui Yang
2026-05-21 8:04 ` John Garry
2026-05-15 8:45 ` [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover Xingui Yang
1 sibling, 1 reply; 10+ messages in thread
From: Xingui Yang @ 2026-05-15 8:45 UTC (permalink / raw)
To: john.g.garry, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, yangxingui,
liuyonglong, kangfenglong
The sas_ex_to_ata() function checks for an attached ATA device on an
expander phy. Refactor it to use a new helper function sas_ex_to_dev()
which returns any device type attached to an expander phy, improving code
reuse and allowing other code paths to find attached devices regardless
of type.
No functional changes intended.
Reviewed-by: Jason Yan <yanaijie@huawei.com>
Signed-off-by: Xingui Yang <yangxingui@huawei.com>
---
drivers/scsi/libsas/sas_expander.c | 12 ++++++++----
drivers/scsi/libsas/sas_internal.h | 1 +
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index f471ab464a78..f55ae9a979cd 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -345,11 +345,9 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
SAS_ADDR(phy->attached_sas_addr), type);
}
-/* check if we have an existing attached ata device on this expander phy */
-struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
+struct domain_device *sas_ex_to_dev(struct domain_device *ex_dev, int phy_id)
{
struct ex_phy *ex_phy = &ex_dev->ex_dev.ex_phy[phy_id];
- struct domain_device *dev;
struct sas_rphy *rphy;
if (!ex_phy->port)
@@ -359,7 +357,13 @@ struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
if (!rphy)
return NULL;
- dev = sas_find_dev_by_rphy(rphy);
+ return sas_find_dev_by_rphy(rphy);
+}
+
+/* check if we have an existing attached ata device on this expander phy */
+struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id)
+{
+ struct domain_device *dev = sas_ex_to_dev(ex_dev, phy_id);
if (dev && dev_is_sata(dev))
return dev;
diff --git a/drivers/scsi/libsas/sas_internal.h b/drivers/scsi/libsas/sas_internal.h
index 7dce0f587149..350a70484bde 100644
--- a/drivers/scsi/libsas/sas_internal.h
+++ b/drivers/scsi/libsas/sas_internal.h
@@ -91,6 +91,7 @@ int sas_smp_get_phy_events(struct sas_phy *phy);
void sas_device_set_phy(struct domain_device *dev, struct sas_port *port);
struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
+struct domain_device *sas_ex_to_dev(struct domain_device *ex_dev, int phy_id);
struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
int sas_ex_phy_discover(struct domain_device *dev, int single);
int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover
2026-05-15 8:45 [PATCH v3 0/2] libsas: rediscover improvements for linkrate/sas_addr changes Xingui Yang
2026-05-15 8:45 ` [PATCH v3 1/2] scsi: libsas: refactor sas_ex_to_ata() using new helper sas_ex_to_dev() Xingui Yang
@ 2026-05-15 8:45 ` Xingui Yang
2026-05-21 8:13 ` John Garry
1 sibling, 1 reply; 10+ messages in thread
From: Xingui Yang @ 2026-05-15 8:45 UTC (permalink / raw)
To: john.g.garry, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, yangxingui,
liuyonglong, kangfenglong
In sas_rediscover_dev(), when detecting a "flutter" condition (same SAS
address and compatible device type), the code assumes the device remains
unchanged and only handles SATA pending state recovery. However, this
approach misses two important scenarios:
First, the flutter detection only compares SAS address and device type,
ignoring potential linkrate changes that may have already occurred.
Second, after sas_ex_phy_discover() re-queries the expander phy, both
linkrate and attached SAS address may be updated. The current code does
not validate these changes against the existing child device.
Add validation checks after sas_ex_phy_discover() to detect linkrate and
sas_addr changes. When changes are detected, mark the device as gone and
schedule rediscovery via libsas's async discovery pattern:
- Set phy_change_count and ex_change_count to -1 to force revalidation
- Unregister the device and schedule DISCE_REVALIDATE_DOMAIN event
- The old device is destroyed by sas_destruct_devices()
- New event triggers discovery via sas_discover_new() since
attached_sas_addr is cleared
Suggested-by: John Garry <john.g.garry@oracle.com>
Signed-off-by: Xingui Yang <yangxingui@huawei.com>
---
drivers/scsi/libsas/sas_expander.c | 32 ++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index f55ae9a979cd..720db4128727 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -2017,15 +2017,39 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
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);
+ struct domain_device *child_dev = sas_ex_to_dev(dev, phy_id);
+ bool need_rediscover = false;
char *action = "";
sas_ex_phy_discover(dev, phy_id);
- if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING)
+ if (child_dev && dev_is_sata(child_dev) &&
+ phy->attached_dev_type == SAS_SATA_PENDING) {
action = ", needs recovery";
- pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
- SAS_ADDR(dev->sas_addr), phy_id, action);
+ } else if (child_dev && phy->linkrate != child_dev->linkrate) {
+ pr_info("ex %016llx phy%02d linkrate changed from %d to %d\n",
+ SAS_ADDR(dev->sas_addr), phy_id,
+ child_dev->linkrate, phy->linkrate);
+ need_rediscover = true;
+ } else if (child_dev &&
+ SAS_ADDR(child_dev->sas_addr) != SAS_ADDR(phy->attached_sas_addr)) {
+ pr_info("ex %016llx phy%02d sas_addr changed from %016llx to %016llx\n",
+ SAS_ADDR(dev->sas_addr), phy_id,
+ SAS_ADDR(child_dev->sas_addr),
+ SAS_ADDR(phy->attached_sas_addr));
+ need_rediscover = true;
+ }
+
+ if (need_rediscover) {
+ set_bit(SAS_DEV_GONE, &child_dev->state);
+ phy->phy_change_count = -1;
+ ex->ex_change_count = -1;
+ sas_unregister_devs_sas_addr(dev, phy_id, true);
+ sas_discover_event(dev->port, DISCE_REVALIDATE_DOMAIN);
+ } else {
+ pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
+ SAS_ADDR(dev->sas_addr), phy_id, action);
+ }
goto out_free_resp;
}
--
2.43.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 1/2] scsi: libsas: refactor sas_ex_to_ata() using new helper sas_ex_to_dev()
2026-05-15 8:45 ` [PATCH v3 1/2] scsi: libsas: refactor sas_ex_to_ata() using new helper sas_ex_to_dev() Xingui Yang
@ 2026-05-21 8:04 ` John Garry
0 siblings, 0 replies; 10+ messages in thread
From: John Garry @ 2026-05-21 8:04 UTC (permalink / raw)
To: Xingui Yang, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, liuyonglong, kangfenglong
On 15/05/2026 09:45, Xingui Yang wrote:
> The sas_ex_to_ata() function checks for an attached ATA device on an
> expander phy. Refactor it to use a new helper function sas_ex_to_dev()
> which returns any device type attached to an expander phy, improving code
> reuse
I think you mean that later we can improve code reuse. You imply that
code reuse improves now in this change.
> and allowing other code paths to find attached devices regardless
> of type.
>
> No functional changes intended.
>
> Reviewed-by: Jason Yan<yanaijie@huawei.com>
> Signed-off-by: Xingui Yang<yangxingui@huawei.com>
Reviewed-by: John Garry <john.g.garry@oracle.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover
2026-05-15 8:45 ` [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover Xingui Yang
@ 2026-05-21 8:13 ` John Garry
2026-05-21 9:04 ` yangxingui
0 siblings, 1 reply; 10+ messages in thread
From: John Garry @ 2026-05-21 8:13 UTC (permalink / raw)
To: Xingui Yang, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, liuyonglong, kangfenglong
On 15/05/2026 09:45, Xingui Yang wrote:
> In sas_rediscover_dev(), when detecting a "flutter" condition (same SAS
> address and compatible device type), the code assumes the device remains
> unchanged and only handles SATA pending state recovery. However, this
> approach misses two important scenarios:
>
> First, the flutter detection only compares SAS address and device type,
> ignoring potential linkrate changes that may have already occurred.
>
> Second, after sas_ex_phy_discover() re-queries the expander phy, both
> linkrate and attached SAS address may be updated. The current code does
> not validate these changes against the existing child device.
>
> Add validation checks after sas_ex_phy_discover() to detect linkrate and
> sas_addr changes. When changes are detected, mark the device as gone and
> schedule rediscovery via libsas's async discovery pattern:
> - Set phy_change_count and ex_change_count to -1 to force revalidation
> - Unregister the device and schedule DISCE_REVALIDATE_DOMAIN event
> - The old device is destroyed by sas_destruct_devices()
> - New event triggers discovery via sas_discover_new() since
> attached_sas_addr is cleared
>
> Suggested-by: John Garry <john.g.garry@oracle.com>
> Signed-off-by: Xingui Yang <yangxingui@huawei.com>
> ---
> drivers/scsi/libsas/sas_expander.c | 32 ++++++++++++++++++++++++++----
> 1 file changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
> index f55ae9a979cd..720db4128727 100644
> --- a/drivers/scsi/libsas/sas_expander.c
> +++ b/drivers/scsi/libsas/sas_expander.c
> @@ -2017,15 +2017,39 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
> 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);
> + struct domain_device *child_dev = sas_ex_to_dev(dev, phy_id);
> + bool need_rediscover = false;
> char *action = "";
>
> sas_ex_phy_discover(dev, phy_id);
>
> - if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING)
> + if (child_dev && dev_is_sata(child_dev) &&
> + phy->attached_dev_type == SAS_SATA_PENDING) {
> action = ", needs recovery";
> - pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
> - SAS_ADDR(dev->sas_addr), phy_id, action);
> + } else if (child_dev && phy->linkrate != child_dev->linkrate) {
> + pr_info("ex %016llx phy%02d linkrate changed from %d to %d\n",
> + SAS_ADDR(dev->sas_addr), phy_id,
> + child_dev->linkrate, phy->linkrate);
> + need_rediscover = true;
> + } else if (child_dev &&
> + SAS_ADDR(child_dev->sas_addr) != SAS_ADDR(phy->attached_sas_addr)) {
> + pr_info("ex %016llx phy%02d sas_addr changed from %016llx to %016llx\n",
> + SAS_ADDR(dev->sas_addr), phy_id,
> + SAS_ADDR(child_dev->sas_addr),
> + SAS_ADDR(phy->attached_sas_addr));
> + need_rediscover = true;
> + }
> +
> + if (need_rediscover) {
> + set_bit(SAS_DEV_GONE, &child_dev->state);
> + phy->phy_change_count = -1;
> + ex->ex_change_count = -1;
the current code has following:
/* we always have to delete the old device when we went here */
pr_info("ex %016llx phy%02d replace %016llx\n",
SAS_ADDR(dev->sas_addr), phy_id,
SAS_ADDR(phy->attached_sas_addr));
sas_unregister_devs_sas_addr(dev, phy_id, last);
res = sas_discover_new(dev, phy_id);
Can this be reused (to lose and find the device with updated info)? Or
why not good enough?
I don't know why you need full revalidation.
> + sas_unregister_devs_sas_addr(dev, phy_id, true);
> + sas_discover_event(dev->port, DISCE_REVALIDATE_DOMAIN);
> + } else {
> + pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
> + SAS_ADDR(dev->sas_addr), phy_id, action);
> + }
> goto out_free_resp;
> }
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover
2026-05-21 8:13 ` John Garry
@ 2026-05-21 9:04 ` yangxingui
2026-05-22 9:16 ` John Garry
0 siblings, 1 reply; 10+ messages in thread
From: yangxingui @ 2026-05-21 9:04 UTC (permalink / raw)
To: John Garry, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, liuyonglong, kangfenglong
On 2026/5/21 16:13, John Garry wrote:
> On 15/05/2026 09:45, Xingui Yang wrote:
>> In sas_rediscover_dev(), when detecting a "flutter" condition (same SAS
>> address and compatible device type), the code assumes the device remains
>> unchanged and only handles SATA pending state recovery. However, this
>> approach misses two important scenarios:
>>
>> First, the flutter detection only compares SAS address and device type,
>> ignoring potential linkrate changes that may have already occurred.
>>
>> Second, after sas_ex_phy_discover() re-queries the expander phy, both
>> linkrate and attached SAS address may be updated. The current code does
>> not validate these changes against the existing child device.
>>
>> Add validation checks after sas_ex_phy_discover() to detect linkrate and
>> sas_addr changes. When changes are detected, mark the device as gone and
>> schedule rediscovery via libsas's async discovery pattern:
>> - Set phy_change_count and ex_change_count to -1 to force revalidation
>> - Unregister the device and schedule DISCE_REVALIDATE_DOMAIN event
>> - The old device is destroyed by sas_destruct_devices()
>> - New event triggers discovery via sas_discover_new() since
>> attached_sas_addr is cleared
>>
>> Suggested-by: John Garry <john.g.garry@oracle.com>
>> Signed-off-by: Xingui Yang <yangxingui@huawei.com>
>> ---
>> drivers/scsi/libsas/sas_expander.c | 32 ++++++++++++++++++++++++++----
>> 1 file changed, 28 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/scsi/libsas/sas_expander.c
>> b/drivers/scsi/libsas/sas_expander.c
>> index f55ae9a979cd..720db4128727 100644
>> --- a/drivers/scsi/libsas/sas_expander.c
>> +++ b/drivers/scsi/libsas/sas_expander.c
>> @@ -2017,15 +2017,39 @@ static int sas_rediscover_dev(struct
>> domain_device *dev, int phy_id,
>> 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);
>> + struct domain_device *child_dev = sas_ex_to_dev(dev, phy_id);
>> + bool need_rediscover = false;
>> char *action = "";
>> sas_ex_phy_discover(dev, phy_id);
>> - if (ata_dev && phy->attached_dev_type == SAS_SATA_PENDING)
>> + if (child_dev && dev_is_sata(child_dev) &&
>> + phy->attached_dev_type == SAS_SATA_PENDING) {
>> action = ", needs recovery";
>> - pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
>> - SAS_ADDR(dev->sas_addr), phy_id, action);
>> + } else if (child_dev && phy->linkrate != child_dev->linkrate) {
>> + pr_info("ex %016llx phy%02d linkrate changed from %d to
>> %d\n",
>> + SAS_ADDR(dev->sas_addr), phy_id,
>> + child_dev->linkrate, phy->linkrate);
>> + need_rediscover = true;
>> + } else if (child_dev &&
>> + SAS_ADDR(child_dev->sas_addr) !=
>> SAS_ADDR(phy->attached_sas_addr)) {
>> + pr_info("ex %016llx phy%02d sas_addr changed from %016llx
>> to %016llx\n",
>> + SAS_ADDR(dev->sas_addr), phy_id,
>> + SAS_ADDR(child_dev->sas_addr),
>> + SAS_ADDR(phy->attached_sas_addr));
>> + need_rediscover = true;
>> + }
>> +
>> + if (need_rediscover) {
>> + set_bit(SAS_DEV_GONE, &child_dev->state);
>> + phy->phy_change_count = -1;
>> + ex->ex_change_count = -1;
>
> the current code has following:
>
>
> /* we always have to delete the old device when we went here */
> pr_info("ex %016llx phy%02d replace %016llx\n",
> SAS_ADDR(dev->sas_addr), phy_id,
> SAS_ADDR(phy->attached_sas_addr));
> sas_unregister_devs_sas_addr(dev, phy_id, last);
>
> res = sas_discover_new(dev, phy_id);
>
> Can this be reused (to lose and find the device with updated info)? Or
> why not good enough?
>
> I don't know why you need full revalidation.
Hi, John
As the commit log. The existing pattern (unregister + sas_discover_new)
handles the "replace" case where the SAS address changes completely,
implying a different device.
For the flutter case where we detect linkrate/sas_addr changes, we
cannot reuse this synchronous pattern because:
sas_unregister_devs_sas_addr() only marks the device as gone (sets
SAS_DEV_GONE) and adds it to port->destroy_list. The actual sysfs
cleanup (sas_rphy_delete) happens later in sas_destruct_devices() called
at the end of sas_revalidate_domain() in sas_discover.c.
I did try the approach you suggested (unregister + sas_discover_new),
but it produces sysfs duplicate directory errors:
Workqueue: 0000:74:02.0_disco_q sas_revalidate_domain
Call trace:
dump_backtrace+0x0/0x18c
show_stack+0x14/0x1c
dump_stack+0x88/0xac
sysfs_warn_dup+0x64/0x7c
sysfs_create_dir_ns+0x90/0xa0
kobject_add_internal+0xa0/0x284
kobject_add+0xb8/0x11c
device_add+0xe8/0x598
sas_port_add+0x24/0x50
sas_ex_discover_devices+0xb10/0xc30
The async pattern with DISCE_REVALIDATE_DOMAIN ensures proper ordering:
1. Old device added to destroy_list
2. Current revalidate work completes → sas_destruct_devices() truly
deletes old device's sysfs
3. New DISCE_REVALIDATE_DOMAIN event triggers → discovery starts with
clean sysfs state
This follows libsas's async design pattern similar to sas_resume_devices
in sas_port.c.
Thanks,
Xingui
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover
2026-05-21 9:04 ` yangxingui
@ 2026-05-22 9:16 ` John Garry
2026-05-25 2:25 ` yangxingui
0 siblings, 1 reply; 10+ messages in thread
From: John Garry @ 2026-05-22 9:16 UTC (permalink / raw)
To: yangxingui, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, liuyonglong, kangfenglong
On 21/05/2026 10:04, yangxingui wrote:
>>
>> Can this be reused (to lose and find the device with updated info)? Or
>> why not good enough?
>>
>> I don't know why you need full revalidation.
>
> Hi, John
> As the commit log. The existing pattern (unregister + sas_discover_new)
> handles the "replace" case where the SAS address changes completely,
> implying a different device.
> For the flutter case where we detect linkrate/sas_addr changes,
Can you please clarify this: you say that the existing pattern handles
"replace" case where the SAS address changes completely, and then
flutter case covers sas_addr changes.
What is the difference in the SAS address changes between the two cases?
we
> cannot reuse this synchronous pattern because:
> sas_unregister_devs_sas_addr() only marks the device as gone (sets
> SAS_DEV_GONE) and adds it to port->destroy_list. The actual sysfs
> cleanup (sas_rphy_delete) happens later in sas_destruct_devices() called
> at the end of sas_revalidate_domain() in sas_discover.c.
> I did try the approach you suggested (unregister + sas_discover_new),
> but it produces sysfs duplicate directory errors:
> Workqueue: 0000:74:02.0_disco_q sas_revalidate_domain
> Call trace:
> dump_backtrace+0x0/0x18c
> show_stack+0x14/0x1c
> dump_stack+0x88/0xac
> sysfs_warn_dup+0x64/0x7c
> sysfs_create_dir_ns+0x90/0xa0
> kobject_add_internal+0xa0/0x284
> kobject_add+0xb8/0x11c
> device_add+0xe8/0x598
> sas_port_add+0x24/0x50
> sas_ex_discover_devices+0xb10/0xc30
>
> The async pattern with DISCE_REVALIDATE_DOMAIN ensures proper ordering:
> 1. Old device added to destroy_list
> 2. Current revalidate work completes → sas_destruct_devices() truly
> deletes old device's sysfs
> 3. New DISCE_REVALIDATE_DOMAIN event triggers → discovery starts with
> clean sysfs state
> This follows libsas's async design pattern similar to sas_resume_devices
> in sas_port.c.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover
2026-05-22 9:16 ` John Garry
@ 2026-05-25 2:25 ` yangxingui
2026-05-27 9:42 ` John Garry
0 siblings, 1 reply; 10+ messages in thread
From: yangxingui @ 2026-05-25 2:25 UTC (permalink / raw)
To: John Garry, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, liuyonglong, kangfenglong
On 2026/5/22 17:16, John Garry wrote:
> On 21/05/2026 10:04, yangxingui wrote:
>>>
>>> Can this be reused (to lose and find the device with updated info)?
>>> Or why not good enough?
>>>
>>> I don't know why you need full revalidation.
>>
>> Hi, John
>> As the commit log. The existing pattern (unregister +
>> sas_discover_new) handles the "replace" case where the SAS address
>> changes completely, implying a different device.
>> For the flutter case where we detect linkrate/sas_addr changes,
>
> Can you please clarify this: you say that the existing pattern handles
> "replace" case where the SAS address changes completely, and then
> flutter case covers sas_addr changes.
>
> What is the difference in the SAS address changes between the two cases?
>
Hi, John
The difference is in when the SAS address change is detected:
Replace case:
- Detected immediately by the initial SMP DISCOVER response
- New SAS address differs from stored phy->attached_sas_addr
Flutter case:
- Initial SMP DISCOVER shows SAS address matching stored
phy->attached_sas_addr
- Linkrate may change
- After sas_ex_phy_discover() refreshes phy info, child device address
and linkrate may mismatched with refreshed phy info
Additional issue with Replace flow:
The existing replace code path also suffers from the same sysfs_warn_dup
issue I mentioned earlier. sas_unregister_devs_sas_addr() only marks the
device as gone and adds it to destroy_list. The actual sysfs cleanup
happens later in sas_destruct_devices(). Calling sas_discover_new()
immediately after unregister causes sysfs duplicate directory errors.
We need to optimize the replace process.
Thanks,
Xingui
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover
2026-05-25 2:25 ` yangxingui
@ 2026-05-27 9:42 ` John Garry
2026-05-28 2:40 ` yangxingui
0 siblings, 1 reply; 10+ messages in thread
From: John Garry @ 2026-05-27 9:42 UTC (permalink / raw)
To: yangxingui, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, liuyonglong, kangfenglong
On 25/05/2026 03:25, yangxingui wrote:
>>>
>>> Hi, John
>>> As the commit log. The existing pattern (unregister +
>>> sas_discover_new) handles the "replace" case where the SAS address
>>> changes completely, implying a different device.
>>> For the flutter case where we detect linkrate/sas_addr changes,
>>
>> Can you please clarify this: you say that the existing pattern handles
>> "replace" case where the SAS address changes completely, and then
>> flutter case covers sas_addr changes.
>>
>> What is the difference in the SAS address changes between the two cases?
>>
> Hi, John
>
> The difference is in when the SAS address change is detected:
> Replace case:
> - Detected immediately by the initial SMP DISCOVER response
> - New SAS address differs from stored phy->attached_sas_addr
>
> Flutter case:
> - Initial SMP DISCOVER shows SAS address matching stored phy-
> >attached_sas_addr
> - Linkrate may change
> - After sas_ex_phy_discover() refreshes phy info, child device address
> and linkrate may mismatched with refreshed phy info
>
> Additional issue with Replace flow:
> The existing replace code path also suffers from the same sysfs_warn_dup
> issue I mentioned earlier. sas_unregister_devs_sas_addr() only marks the
> device as gone and adds it to destroy_list. The actual sysfs cleanup
> happens later in sas_destruct_devices(). Calling sas_discover_new()
> immediately after unregister causes sysfs duplicate directory errors.
>
So can you actually recreate this issue? Or is it just theoretical?
About this following code:
+ if (need_rediscover) {
+ set_bit(SAS_DEV_GONE, &child_dev->state);
+ phy->phy_change_count = -1;
+ ex->ex_change_count = -1;
+ sas_unregister_devs_sas_addr(dev, phy_id, true);
+ sas_discover_event(dev->port, DISCE_REVALIDATE_DOMAIN);
+ } else {
Can we factor it out with other code? AFAICR, this can pattern can be
seen elsewhere.
Thanks
> We need to optimize the replace process.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover
2026-05-27 9:42 ` John Garry
@ 2026-05-28 2:40 ` yangxingui
0 siblings, 0 replies; 10+ messages in thread
From: yangxingui @ 2026-05-28 2:40 UTC (permalink / raw)
To: John Garry, yanaijie, jejb, martin.petersen
Cc: linux-scsi, linux-kernel, linuxarm, liyihang9, liuyonglong, kangfenglong
On 2026/5/27 17:42, John Garry wrote:
> On 25/05/2026 03:25, yangxingui wrote:
>>>>
>>>> Hi, John
>>>> As the commit log. The existing pattern (unregister +
>>>> sas_discover_new) handles the "replace" case where the SAS address
>>>> changes completely, implying a different device.
>>>> For the flutter case where we detect linkrate/sas_addr changes,
>>>
>>> Can you please clarify this: you say that the existing pattern
>>> handles "replace" case where the SAS address changes completely, and
>>> then flutter case covers sas_addr changes.
>>>
>>> What is the difference in the SAS address changes between the two cases?
>>>
>> Hi, John
>>
>> The difference is in when the SAS address change is detected:
>> Replace case:
>> - Detected immediately by the initial SMP DISCOVER response
>> - New SAS address differs from stored phy->attached_sas_addr
>>
>> Flutter case:
>> - Initial SMP DISCOVER shows SAS address matching stored phy-
>> >attached_sas_addr
>> - Linkrate may change
>> - After sas_ex_phy_discover() refreshes phy info, child device address
>> and linkrate may mismatched with refreshed phy info
>>
>> Additional issue with Replace flow:
>> The existing replace code path also suffers from the same
>> sysfs_warn_dup issue I mentioned earlier.
>> sas_unregister_devs_sas_addr() only marks the device as gone and adds
>> it to destroy_list. The actual sysfs cleanup happens later in
>> sas_destruct_devices(). Calling sas_discover_new() immediately after
>> unregister causes sysfs duplicate directory errors.
>>
>
> So can you actually recreate this issue? Or is it just theoretical?
Yes, it can recreate, such as quickly replacing a disk or swapping two
disk. However, during normal use, we recommend that customers wait for
one minute before inserting a new disk when replacing a disk to avoid
this issue.
The following are example of similar exception logs:
log1:
[ 7957.283194][T67794] sas: ex 500e004aaaaaaa1f phy19 replace
5001882016000000
[ 7957.290960][T67794] sysfs: cannot create duplicate filename
'/devices/pci0000:74/0000:74:02.0/host1/port-1:2/expander-1:2/port-1:2:19'
[ 7957.317973][T67794] Hardware name: Huawei Technologies Co., Ltd.
EVBCS/EVBCS, BIOS CS B055 2P TA 02/19/2020
[ 7957.328900][T67794] Workqueue: 0000:74:02.0_disco_q
sas_revalidate_domain [libsas]
[ 7957.337636][T67794] Call trace:
[ 7957.341419][T67794] dump_backtrace+0x0/0x200
[ 7957.346317][T67794] show_stack+0x20/0x30
[ 7957.350887][T67794] dump_stack+0xf0/0x138
[ 7957.355511][T67794] sysfs_warn_dup+0x6c/0x90
[ 7957.360410][T67794] sysfs_create_dir_ns+0xf8/0x11c
[ 7957.365795][T67794] create_dir+0x30/0x18c
[ 7957.370416][T67794] kobject_add_internal+0x5c/0x190
[ 7957.375877][T67794] kobject_add+0x98/0x110
[ 7957.380566][T67794] device_add+0x100/0x4a0
[ 7957.385255][T67794] sas_port_add+0x30/0x74 [scsi_transport_sas]
[ 7957.391722][T67794] sas_ex_discover_end_dev+0x328/0x630 [libsas]
[ 7957.398328][T67794] sas_ex_discover_dev+0x230/0x320 [libsas]
[ 7957.404599][T67794] sas_ex_discover_devices+0x60/0x100 [libsas]
[ 7957.411116][T67794] sas_discover_new+0xa4/0x150 [libsas]
[ 7957.416986][T67794] sas_rediscover_dev+0x198/0x260 [libsas]
[ 7957.423125][T67794] sas_rediscover+0xb8/0x100 [libsas]
[ 7957.428854][T67794] sas_ex_revalidate_domain+0x5c/0xe0 [libsas]
[ 7957.435320][T67794] sas_revalidate_domain+0x1ac/0x1b4 [libsas]
[ 7957.441714][T67794] process_one_work+0x1d8/0x4cc
[ 7957.446884][T67794] worker_thread+0x158/0x410
[ 7957.451769][T67794] kthread+0x108/0x13c
[ 7957.456089][T67794] ret_from_fork+0x10/0x18
[ 7957.460800][T67794] kobject_add_internal failed for port-1:2:19 with
-EEXIST, don't try to register things with the same name in the same
directory.
[ 7957.474864][T67794] sas: ex 500e004aaaaaaa1f phy19 failed to discover
log2:
[ 8608.766031][T66335] sas: ex 500e004aaaaaaa1f phy17 change count has
changed
[ 8608.774390][T66335] sysfs: cannot create duplicate filename
'/devices/pci0000:74/0000:74:02.0/host1/port-1:2/expander-1:3/port-1:3:17'
[ 8608.800667][T66335] Hardware name: Huawei Technologies Co., Ltd.
EVBCS/EVBCS, BIOS CS B055 2P TA 02/19/2020
[ 8608.811270][T66335] Workqueue: 0000:74:02.0_disco_q
sas_revalidate_domain [libsas]
[ 8608.819685][T66335] Call trace:
[ 8608.823235][T66335] dump_backtrace+0x0/0x200
[ 8608.827990][T66335] show_stack+0x20/0x30
[ 8608.832387][T66335] dump_stack+0xf0/0x138
[ 8608.836858][T66335] sysfs_warn_dup+0x6c/0x90
[ 8608.841580][T66335] sysfs_create_dir_ns+0xf8/0x11c
[ 8608.846814][T66335] create_dir+0x30/0x18c
[ 8608.851257][T66335] kobject_add_internal+0x5c/0x190
[ 8608.856566][T66335] kobject_add+0x98/0x110
[ 8608.861083][T66335] device_add+0x100/0x4a0
[ 8608.865588][T66335] sas_port_add+0x30/0x74 [scsi_transport_sas]
[ 8608.871919][T66335] sas_ex_discover_end_dev+0x328/0x630 [libsas]
[ 8608.878345][T66335] sas_ex_discover_dev+0x230/0x320 [libsas]
[ 8608.884430][T66335] sas_ex_discover_devices+0x60/0x100 [libsas]
[ 8608.890768][T66335] sas_discover_new+0xa4/0x150 [libsas]
[ 8608.896506][T66335] sas_rediscover+0xd8/0x100 [libsas]
[ 8608.902075][T66335] sas_ex_revalidate_domain+0x5c/0xe0 [libsas]
[ 8608.908438][T66335] sas_revalidate_domain+0x1ac/0x1b4 [libsas]
[ 8608.914708][T66335] process_one_work+0x1d8/0x4cc
[ 8608.919757][T66335] worker_thread+0x158/0x410
[ 8608.924533][T66335] kthread+0x108/0x13c
[ 8608.928778][T66335] ret_from_fork+0x10/0x18
[ 8608.933377][T66335] kobject_add_internal failed for port-1:3:17 with
-EEXIST, don't try to register things with the same name in the same
directory.
[ 8608.947364][T66335] sas: ex 500e004aaaaaaa1f phy17 failed to discover
> About this following code:
>
> + if (need_rediscover) {
> + set_bit(SAS_DEV_GONE, &child_dev->state);
> + phy->phy_change_count = -1;
> + ex->ex_change_count = -1;
> + sas_unregister_devs_sas_addr(dev, phy_id, true);
> + sas_discover_event(dev->port, DISCE_REVALIDATE_DOMAIN);
> + } else {
>
>
> Can we factor it out with other code? AFAICR, this can pattern can be
> seen elsewhere.
Yes, in the updated v4 version, I refined it into a function.
In the v4 test log, the disk is gone and then connected again.
test case:
phy=phy-10:0:0
echo 1.5 Gbit > /sys/class/sas_phy/$phy/maximum_linkrate
The details are as follows:
[ 541.880156] sas: broadcast received: 0
[ 541.880712] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.882509] sas: ex 500e004aaaaaaa1f phy00 change count has changed
[ 541.883680] sas: ex 500e004aaaaaaa1f phy00 originated BROADCAST(CHANGE)
[ 541.883703] sas: ex 500e004aaaaaaa1f rediscovering phy00
[ 541.884838] sas: ex 500e004aaaaaaa1f phy00:U:8 attached:
500e004aaaaaaa00 (stp pending)
[ 541.884844] sas: ex 500e004aaaaaaa1f phy00 broadcast flutter, needs
recovery
[ 541.898893] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.899444] sas: broadcast received: 0
[ 541.899506] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.899659] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.900213] sas: broadcast received: 0
[ 541.900282] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.900367] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.900992] sas: broadcast received: 0
[ 541.901041] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.901132] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.901160] sas: broadcast received: 0
[ 541.901195] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.901278] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.901887] sas: broadcast received: 0
[ 541.901948] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.902035] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.902673] sas: broadcast received: 0
[ 541.902741] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.902836] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.903467] sas: broadcast received: 0
[ 541.903536] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.903625] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 541.919967] sas: broadcast received: 0
[ 541.920036] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 541.920385] sas: ex 500e004aaaaaaa1f phy00 change count has changed
[ 541.920494] sas: ex 500e004aaaaaaa1f phy00 originated BROADCAST(CHANGE)
[ 541.920504] sas: ex 500e004aaaaaaa1f rediscovering phy00
[ 541.920687] sas: ex 500e004aaaaaaa1f phy00:U:8 attached:
500e004aaaaaaa00 (stp)
[ 541.920697] sas: ex 500e004aaaaaaa1f phy00 linkrate changed from 9 to 8
[ 541.920710] sas: ex 500e004aaaaaaa1f phy00 replace 500e004aaaaaaa00
[ 541.922648] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 542.007031] sd 10:0:0:0: [sdd] Stopping disk
[ 542.007122] sd 10:0:0:0: [sdd] Start/Stop Unit failed: Result:
hostbyte=0x04 driverbyte=DRIVER_OK
[ 542.027347] hisi_sas_v3_hw 0000:70:04.0: dev[2:5] is gone
[ 542.039000] sas: REVALIDATING DOMAIN on port 0, pid:8995
[ 542.039358] sas: ex 500e004aaaaaaa1f phy00 change count has changed
[ 542.039436] sas: broadcast received: 0
[ 542.039470] sas: ex 500e004aaaaaaa1f phy00 originated BROADCAST(CHANGE)
[ 542.039482] sas: ex 500e004aaaaaaa1f phy00 new device attached
[ 542.039569] sas: ex 500e004aaaaaaa1f phy00:U:8 attached:
500e004aaaaaaa00 (stp)
[ 542.040152] hisi_sas_v3_hw 0000:70:04.0: dev[15:5] found
[ 542.042112] sas: done REVALIDATING DOMAIN on port 0, pid:8995, res 0x0
[ 542.153137] sas: Enter sas_scsi_recover_host busy: 0 failed: 0
[ 542.153900] sas: ata10: end_device-10:0:1: dev error handler
[ 542.153972] sas: ata11: end_device-10:0:2: dev error handler
[ 542.153994] sas: ata12: end_device-10:0:5: dev error handler
[ 542.154010] sas: ata13: end_device-10:0:6: dev error handler
[ 542.154021] sas: ata14: end_device-10:0:9: dev error handler
[ 542.154032] sas: ata15: end_device-10:0:10: dev error handler
[ 542.154044] sas: ata9: end_device-10:0:0: dev error handler
[ 542.519243] ata9.00: ATA-10: ST4000NM0035-1V4107, TN03, max UDMA/133
[ 542.522538] ata9.00: 7814037168 sectors, multi 0: LBA48 NCQ (depth 32)
[ 542.522561] ata9.00: Features: DIPM NCQ-sndrcv
[ 542.527315] ata9.00: configured for UDMA/133
[ 542.527976] sas: --- Exit sas_scsi_recover_host: busy: 0 failed: 0
tries: 1
[ 542.570193] scsi 10:0:13:0: Direct-Access ATA
ST4000NM0035-1V4 TN03 PQ: 0 ANSI: 5
[ 542.571771] scsi 10:0:13:0: Attached scsi generic sg3 type 0
Thanks,
Xingui
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-05-28 2:40 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-05-15 8:45 [PATCH v3 0/2] libsas: rediscover improvements for linkrate/sas_addr changes Xingui Yang
2026-05-15 8:45 ` [PATCH v3 1/2] scsi: libsas: refactor sas_ex_to_ata() using new helper sas_ex_to_dev() Xingui Yang
2026-05-21 8:04 ` John Garry
2026-05-15 8:45 ` [PATCH v3 2/2] scsi: libsas: Add linkrate and sas_addr change detection in rediscover Xingui Yang
2026-05-21 8:13 ` John Garry
2026-05-21 9:04 ` yangxingui
2026-05-22 9:16 ` John Garry
2026-05-25 2:25 ` yangxingui
2026-05-27 9:42 ` John Garry
2026-05-28 2:40 ` yangxingui
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®