Given that the kernel has exponential backoff to cover the lack of
interrupts for scrub completion status there is a reasonable likelihood
that 'ndctl start-scrub' is issued while the hardware/platform scrub-state
is idle, but the kernel engine poll timer has not fired.

Trigger at least one poll cycle for the kernel to re-read the scrub-state
before reporting that ARS is busy.

Reported-by: Krzysztof Rusocki <[email protected]>
Signed-off-by: Dan Williams <[email protected]>
---
 ndctl/lib/libndctl.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index e5641feec23d..536e142cf6af 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -1354,8 +1354,18 @@ static int __ndctl_bus_get_scrub_state(struct ndctl_bus 
*bus,
 NDCTL_EXPORT int ndctl_bus_start_scrub(struct ndctl_bus *bus)
 {
        struct ndctl_ctx *ctx = ndctl_bus_get_ctx(bus);
+       int rc;
+
+       rc = sysfs_write_attr(ctx, bus->scrub_path, "1\n");
 
-       return sysfs_write_attr(ctx, bus->scrub_path, "1\n");
+       /*
+        * Try at least 1 poll cycle before reporting busy in case this
+        * request hits the kernel's exponential backoff while the
+        * hardware/platform scrub state is idle.
+        */
+       if (rc == -EBUSY && ndctl_bus_poll_scrub_completion(bus, 1, 1) == 0)
+               return sysfs_write_attr(ctx, bus->scrub_path, "1\n");
+       return rc;
 }
 
 NDCTL_EXPORT int ndctl_bus_get_scrub_state(struct ndctl_bus *bus)


Reply via email to