* [LTP] [PATCH] lib: Use exponential-backoff polling to wait for loop device nodes
@ 2026-08-03 15:27 Wake Liu via ltp
2026-08-03 16:28 ` [LTP] " linuxtestproject.agent
2026-08-04 1:59 ` [LTP] [PATCH v2] lib: Use backoff " Wake Liu via ltp
0 siblings, 2 replies; 17+ messages in thread
From: Wake Liu via ltp @ 2026-08-03 15:27 UTC (permalink / raw)
To: ltp; +Cc: wakel
On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.
Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.
This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.
Signed-off-by: Wake Liu <wakel@google.com>
---
lib/tst_device.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffef..6e3c6fef21 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
int tst_find_free_loopdev(char *path, size_t path_len)
{
- int ctl_fd, dev_fd, rc, i;
+ int ctl_fd, dev_fd, rc, i, path_set;
struct loop_info loopinfo;
char buf[PATH_MAX];
@@ -93,8 +93,20 @@ int tst_find_free_loopdev(char *path, size_t path_len)
rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
close(ctl_fd);
if (rc >= 0) {
- if (path && set_dev_loop_path(rc, path, path_len))
- tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ if (path) {
+ unsigned int usec = 1000; /* start with 1ms */
+
+ for (i = 0; i < 50; i++) {
+ path_set = set_dev_loop_path(rc, path, path_len);
+ if (!path_set)
+ break;
+ usleep(usec);
+ if (usec < 100000) /* cap backoff at 100ms */
+ usec *= 2;
+ }
+ if (path_set)
+ tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ }
tst_resm(TINFO, "Found free device %d '%s'",
rc, path ?: "");
return rc;
@@ -155,13 +167,22 @@ int tst_attach_device(const char *dev, const char *file)
{
int dev_fd, file_fd;
struct loop_info loopinfo;
+ int attach_tries = 20;
+ unsigned int usec = 1000; /* start with 1ms */
if (strlen(file) >= LO_NAME_SIZE) {
tst_brkm(TBROK, NULL, "Device name can't be longer than %u chars",
LO_NAME_SIZE);
}
- dev_fd = open(dev, O_RDWR);
+ while (attach_tries--) {
+ dev_fd = open(dev, O_RDWR);
+ if (dev_fd >= 0)
+ break;
+ usleep(usec);
+ if (usec < 100000) /* cap backoff at 100ms */
+ usec *= 2;
+ }
if (dev_fd < 0) {
tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
return 1;
--
2.55.0.508.g3f0d502094-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [LTP] lib: Use exponential-backoff polling to wait for loop device nodes
2026-08-03 15:27 [LTP] [PATCH] lib: Use exponential-backoff polling to wait for loop device nodes Wake Liu via ltp
@ 2026-08-03 16:28 ` linuxtestproject.agent
2026-08-04 1:59 ` [LTP] [PATCH v2] lib: Use backoff " Wake Liu via ltp
1 sibling, 0 replies; 17+ messages in thread
From: linuxtestproject.agent @ 2026-08-03 16:28 UTC (permalink / raw)
To: Wake Liu; +Cc: ltp
Hi Wake,
On Aug 3, 2026, Wake Liu wrote:
> lib: Use exponential-backoff polling to wait for loop device nodes
> usleep(usec);
> if (usec < 100000) /* cap backoff at 100ms */
> usec *= 2;
Could this clamp the doubled value to 100000 and only sleep when another
attempt remains? When usec is 64000, this condition doubles it to 128000, so
the advertised 100 ms cap is exceeded. The loops also sleep after the final
failed probe. As a result, the 50-attempt stat path can sleep for 5.631
seconds and the 20-attempt open path for 1.791 seconds.
Verdict - Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2] lib: Use backoff polling to wait for loop device nodes
2026-08-03 15:27 [LTP] [PATCH] lib: Use exponential-backoff polling to wait for loop device nodes Wake Liu via ltp
2026-08-03 16:28 ` [LTP] " linuxtestproject.agent
@ 2026-08-04 1:59 ` Wake Liu via ltp
2026-08-04 3:58 ` Li Wang
1 sibling, 1 reply; 17+ messages in thread
From: Wake Liu via ltp @ 2026-08-04 1:59 UTC (permalink / raw)
To: ltp; +Cc: wakel
From: Wake Liu via ltp <ltp@lists.linux.it>
On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.
Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.
This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.
Link: https://lore.kernel.org/ltp/20260803152754.3991113-1-wakel@google.com/
Signed-off-by: Wake Liu <wakel@google.com>
---
v1 -> v2:
- Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
- Skip usleep on final loop iteration to avoid unnecessary idle delay.
- Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.
lib/tst_device.c | 32 +++++++++++++++++++++++++++-----
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffef..19e1a8a25c 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_loop_path(int rc, char *path, size_t path_len)
int tst_find_free_loopdev(char *path, size_t path_len)
{
- int ctl_fd, dev_fd, rc, i;
+ int ctl_fd, dev_fd, rc, i, path_set;
struct loop_info loopinfo;
char buf[PATH_MAX];
@@ -94,8 +94,18 @@ int tst_find_free_loopdev(char *path, size_t path_len)
if (rc >= 0) {
if (path) {
- if (set_dev_loop_path(rc, path, path_len))
- tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ unsigned int usec = 1000; /* start with 1ms */
+
+ for (i = 0; i < 30; i++) {
+ path_set = set_dev_loop_path(rc, path, path_len);
+ if (!path_set)
+ break;
+ if (i < 29) {
+ usleep(usec);
+ usec = usec * 2 < 100000 ? usec * 2 : 100000;
+ }
+ }
+ if (path_set)
+ tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
}
tst_resm(TINFO, "Found free device %d '%s'",
rc, path ?: "");
@@ -166,9 +176,8 @@ int tst_find_free_loopdev(char *path, size_t path_len)
int tst_attach_device(const char *dev, const char *file)
{
- int dev_fd, file_fd;
- struct loop_info loopinfo;
- int attach_tries = 20;
+ int dev_fd, file_fd, i;
+ struct loop_info loopinfo;
unsigned int usec = 1000; /* start with 1ms */
if (strlen(file) >= LO_NAME_SIZE) {
@@ -175,13 +184,14 @@ int tst_attach_device(const char *dev, const char *file)
LO_NAME_SIZE);
}
- while (attach_tries--) {
+ for (i = 0; i < 15; i++) {
dev_fd = open(dev, O_RDWR);
if (dev_fd >= 0)
break;
- usleep(usec);
- if (usec < 100000) /* cap backoff at 100ms */
- usec *= 2;
+ if (i < 14) {
+ usleep(usec);
+ usec = usec * 2 < 100000 ? usec * 2 : 100000;
+ }
}
if (dev_fd < 0) {
tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [LTP] [PATCH v2] lib: Use backoff polling to wait for loop device nodes
2026-08-04 1:59 ` [LTP] [PATCH v2] lib: Use backoff " Wake Liu via ltp
@ 2026-08-04 3:58 ` Li Wang
2026-08-04 15:24 ` [LTP] [PATCH v3] " Wake Liu via ltp
0 siblings, 1 reply; 17+ messages in thread
From: Li Wang @ 2026-08-04 3:58 UTC (permalink / raw)
To: Wake Liu; +Cc: ltp
Hi Wake,
Wake Liu via ltp wrote:
> From: Wake Liu via ltp <ltp@lists.linux.it>
>
> On systems where loop device node creation is asynchronous (such as Android
> containers or systems with slow udev startup), calling stat() or open()
> immediately after LOOP_CTL_GET_FREE can transiently fail because the
> device file (e.g. /dev/loopX) has not been fully populated in time.
>
> Introduce an exponential-backoff retry loop in both
> tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> doubling each try, capped at 100ms) to wait for the device node to be
> successfully populated.
>
> This improves the robustness of loop device allocations on asynchronous
> virtualized environments while minimizing unnecessary delays on responsive
> systems.
>
> Link: https://lore.kernel.org/ltp/20260803152754.3991113-1-wakel@google.com/
> Signed-off-by: Wake Liu <wakel@google.com>
> ---
> v1 -> v2:
> - Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
> - Skip usleep on final loop iteration to avoid unnecessary idle delay.
> - Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.
>
> lib/tst_device.c | 32 +++++++++++++++++++++++++++-----
>
> diff --git a/lib/tst_device.c b/lib/tst_device.c
> index 744173ffef..19e1a8a25c 100644
> --- a/lib/tst_device.c
> +++ b/lib/tst_device.c
> @@ -82,7 +82,7 @@ static int set_dev_loop_path(int rc, char *path, size_t path_len)
>
> int tst_find_free_loopdev(char *path, size_t path_len)
> {
> - int ctl_fd, dev_fd, rc, i;
> + int ctl_fd, dev_fd, rc, i, path_set;
> struct loop_info loopinfo;
> char buf[PATH_MAX];
>
> @@ -94,8 +94,18 @@ int tst_find_free_loopdev(char *path, size_t path_len)
> if (rc >= 0) {
> if (path) {
> - if (set_dev_loop_path(rc, path, path_len))
> - tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
> + unsigned int usec = 1000; /* start with 1ms */
> +
> + for (i = 0; i < 30; i++) {
> + path_set = set_dev_loop_path(rc, path, path_len);
> + if (!path_set)
> + break;
> + if (i < 29) {
> + usleep(usec);
> + usec = usec * 2 < 100000 ? usec * 2 : 100000;
> + }
> + }
LTP has already provided the exponential-backoff macro in tst_common.h
TST_RETRY_FN_EXP_BACKOFF()
Maybe you can reuse it directly?
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread* [LTP] [PATCH v3] lib: Use backoff polling to wait for loop device nodes
2026-08-04 3:58 ` Li Wang
@ 2026-08-04 15:24 ` Wake Liu via ltp
2026-08-05 2:24 ` Li Wang
0 siblings, 1 reply; 17+ messages in thread
From: Wake Liu via ltp @ 2026-08-04 15:24 UTC (permalink / raw)
To: ltp; +Cc: wakel
On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.
Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.
This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.
Link: https://lore.kernel.org/ltp/20260803152754.3991113-1-wakel@google.com/
Signed-off-by: Wake Liu <wakel@google.com>
---
v2 -> v3:
- Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.
v1 -> v2:
- Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
- Skip usleep on final loop iteration to avoid unnecessary idle delay.
- Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.
lib/tst_device.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/lib/tst_device.c b/lib/tst_device.c
index d3c53a1a1..a3c0992e0 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
int tst_find_free_loopdev(char *path, size_t path_len)
{
- int ctl_fd, dev_fd, rc, i;
+ int ctl_fd, dev_fd, rc, i, path_set;
struct loop_info loopinfo;
char buf[PATH_MAX];
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
close(ctl_fd);
if (rc >= 0) {
- if (path && set_dev_loop_path(rc, path, path_len))
- tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ if (path) {
+ path_set = TST_RETRY_FN_EXP_BACKOFF(
+ set_dev_loop_path(rc, path, path_len),
+ TST_RETVAL_EQ0, 1);
+ if (path_set)
+ tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ }
tst_resm(TINFO, "Found free device %d '%s'",
rc, path ?: "");
return rc;
@@ -156,7 +161,7 @@ int tst_attach_device(const char *dev, const char *file)
int dev_fd, file_fd;
struct loop_info loopinfo;
- dev_fd = open(dev, O_RDWR);
+ dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
if (dev_fd < 0) {
tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
return 1;
--
2.55.0.571.g244d577d93-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [LTP] [PATCH v3] lib: Use backoff polling to wait for loop device nodes
2026-08-04 15:24 ` [LTP] [PATCH v3] " Wake Liu via ltp
@ 2026-08-05 2:24 ` Li Wang
2026-08-05 2:54 ` [LTP] [PATCH v4] " Wake Liu via ltp
0 siblings, 1 reply; 17+ messages in thread
From: Li Wang @ 2026-08-05 2:24 UTC (permalink / raw)
To: Wake Liu; +Cc: ltp
Hi Wake,
v3 looks good overall, but it needs a rebase onto the latest LTP
HEAD, otherwise it doesn't apply cleanly here.
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v4] lib: Use backoff polling to wait for loop device nodes
2026-08-05 2:24 ` Li Wang
@ 2026-08-05 2:54 ` Wake Liu via ltp
2026-08-05 4:09 ` [LTP] " linuxtestproject.agent
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Wake Liu via ltp @ 2026-08-05 2:54 UTC (permalink / raw)
To: ltp; +Cc: wakel
On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.
Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.
This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.
Signed-off-by: Wake Liu <wakel@google.com>
---
v3 -> v4:
- Rebase onto the latest LTP HEAD.
- Remove self-referencing Link in commit message.
v2 -> v3:
- Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.
v1 -> v2:
- Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
- Skip usleep on final loop iteration to avoid unnecessary idle delay.
- Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.
lib/tst_device.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffe..00304711b 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
int tst_find_free_loopdev(char *path, size_t path_len)
{
- int ctl_fd, dev_fd, rc, i;
+ int ctl_fd, dev_fd, rc, i, path_set;
struct loop_info loopinfo;
char buf[PATH_MAX];
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
close(ctl_fd);
if (rc >= 0) {
- if (path && set_dev_loop_path(rc, path, path_len))
- tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ if (path) {
+ path_set = TST_RETRY_FN_EXP_BACKOFF(
+ set_dev_loop_path(rc, path, path_len),
+ TST_RETVAL_EQ0, 1);
+ if (path_set)
+ tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ }
tst_resm(TINFO, "Found free device %d '%s'",
rc, path ?: "");
return rc;
@@ -161,7 +166,7 @@ int tst_attach_device(const char *dev, const char *file)
LO_NAME_SIZE);
}
- dev_fd = open(dev, O_RDWR);
+ dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
if (dev_fd < 0) {
tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
return 1;
--
2.55.0.571.g244d577d93-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [LTP] lib: Use backoff polling to wait for loop device nodes
2026-08-05 2:54 ` [LTP] [PATCH v4] " Wake Liu via ltp
@ 2026-08-05 4:09 ` linuxtestproject.agent
2026-08-05 6:53 ` Li Wang
2026-08-05 6:35 ` [LTP] [PATCH v4] " Li Wang
` (2 subsequent siblings)
3 siblings, 1 reply; 17+ messages in thread
From: linuxtestproject.agent @ 2026-08-05 4:09 UTC (permalink / raw)
To: Wake Liu; +Cc: ltp
Hi Wake,
On Aug 5, 2026, Wake Liu wrote:
> lib: Use backoff polling to wait for loop device nodes
> + path_set = TST_RETRY_FN_EXP_BACKOFF(
> + set_dev_loop_path(rc, path, path_len),
> + TST_RETVAL_EQ0, 1);
Could the declaration of tst_multiply_timeout() be made available to this
legacy-API library, or could polling avoid this macro? The macro expands to a
call to tst_multiply_timeout(), but test.h does not declare it. GCC reports an
implicit declaration and Clang rejects both new call sites under C99:
> error: call to undeclared function 'tst_multiply_timeout'; ISO C99 and later do not support implicit function declarations
> tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> doubling each try, capped at 100ms) to wait for the device node to be
> successfully populated.
Could this timing description be corrected or the requested timing be
implemented? TST_RETRY_FN_EXP_BACKOFF(..., 1) starts at one microsecond and
uses one second as its maximum-delay threshold, subject to
tst_multiply_timeout().
Verdict - Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [LTP] lib: Use backoff polling to wait for loop device nodes
2026-08-05 4:09 ` [LTP] " linuxtestproject.agent
@ 2026-08-05 6:53 ` Li Wang
0 siblings, 0 replies; 17+ messages in thread
From: Li Wang @ 2026-08-05 6:53 UTC (permalink / raw)
To: linuxtestproject.agent; +Cc: Wake Liu, ltp
Hi Wake,
The AI comments make sense, I overlooked them before ack your patch.
TST_RETRY_FN_EXP_BACKOFF() is not a drop-in replacement here: it
depends on tst_multiply_timeout(), which is not declared by test.h
for legacy-API users, and its timing semantics do not match the
commit message. In particular, the argument 1 is 1us, not 1ms,
and the cap is the macro's own timeout-adjusted threshold rather
than 100ms.
On Wed, Aug 05, 2026 at 04:09:54AM +0000, linuxtestproject.agent@gmail.com wrote:
> Hi Wake,
>
> On Aug 5, 2026, Wake Liu wrote:
> > lib: Use backoff polling to wait for loop device nodes
>
> > + path_set = TST_RETRY_FN_EXP_BACKOFF(
> > + set_dev_loop_path(rc, path, path_len),
> > + TST_RETVAL_EQ0, 1);
>
> Could the declaration of tst_multiply_timeout() be made available to this
> legacy-API library, or could polling avoid this macro? The macro expands to a
> call to tst_multiply_timeout(), but test.h does not declare it. GCC reports an
> implicit declaration and Clang rejects both new call sites under C99:
>
> > error: call to undeclared function 'tst_multiply_timeout'; ISO C99 and later do not support implicit function declarations
>
> > tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> > doubling each try, capped at 100ms) to wait for the device node to be
> > successfully populated.
>
> Could this timing description be corrected or the requested timing be
> implemented? TST_RETRY_FN_EXP_BACKOFF(..., 1) starts at one microsecond and
> uses one second as its maximum-delay threshold, subject to
> tst_multiply_timeout().
>
> Verdict - Needs revision
>
> ---
> Note:
>
> The agent can sometimes produce false positives although often its
> findings are genuine. If you find issues with the review, please
> comment this email or ignore the suggestions.
>
> Regards,
> LTP AI Reviewer
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop device nodes
2026-08-05 2:54 ` [LTP] [PATCH v4] " Wake Liu via ltp
2026-08-05 4:09 ` [LTP] " linuxtestproject.agent
@ 2026-08-05 6:35 ` Li Wang
2026-08-05 6:52 ` Andrea Cervesato via ltp
2026-08-05 6:55 ` Andrea Cervesato via ltp
3 siblings, 0 replies; 17+ messages in thread
From: Li Wang @ 2026-08-05 6:35 UTC (permalink / raw)
To: Wake Liu; +Cc: ltp
Reviewed-by: Li Wang <li.wang@linux.dev>
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop device nodes
2026-08-05 2:54 ` [LTP] [PATCH v4] " Wake Liu via ltp
2026-08-05 4:09 ` [LTP] " linuxtestproject.agent
2026-08-05 6:35 ` [LTP] [PATCH v4] " Li Wang
@ 2026-08-05 6:52 ` Andrea Cervesato via ltp
2026-08-05 6:55 ` Andrea Cervesato via ltp
3 siblings, 0 replies; 17+ messages in thread
From: Andrea Cervesato via ltp @ 2026-08-05 6:52 UTC (permalink / raw)
To: Wake Liu via ltp; +Cc: wakel, ltp
Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com>
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop device nodes
2026-08-05 2:54 ` [LTP] [PATCH v4] " Wake Liu via ltp
` (2 preceding siblings ...)
2026-08-05 6:52 ` Andrea Cervesato via ltp
@ 2026-08-05 6:55 ` Andrea Cervesato via ltp
2026-08-05 7:10 ` Li Wang
3 siblings, 1 reply; 17+ messages in thread
From: Andrea Cervesato via ltp @ 2026-08-05 6:55 UTC (permalink / raw)
To: Wake Liu via ltp; +Cc: wakel, ltp, Li Wang
Hi Wake,
I sent the Reviewed-by tag to the wrong email. @Li the agent review is
correct and backoff polling is not working with old API. We need to find
an another way for that.
As you can see the CI is failing everywhere in v4:
https://patchwork.kernel.org/project/ltp/patch/20260805025418.1249003-1-wakel@google.com/
Regards
--
Andrea Cervesato
SUSE QE Automation Engineer Linux
andrea.cervesato@suse.com
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [LTP] [PATCH v4] lib: Use backoff polling to wait for loop device nodes
2026-08-05 6:55 ` Andrea Cervesato via ltp
@ 2026-08-05 7:10 ` Li Wang
2026-08-07 10:04 ` [LTP] [PATCH v5] " Wake Liu via ltp
0 siblings, 1 reply; 17+ messages in thread
From: Li Wang @ 2026-08-05 7:10 UTC (permalink / raw)
To: Andrea Cervesato, wakel; +Cc: Wake Liu via ltp, Li Wang
Andrea Cervesato via ltp wrote:
> Hi Wake,
>
> I sent the Reviewed-by tag to the wrong email. @Li the agent review is
> correct and backoff polling is not working with old API. We need to find
> an another way for that.
>
> As you can see the CI is failing everywhere in v4:
> https://patchwork.kernel.org/project/ltp/patch/20260805025418.1249003-1-wakel@google.com/
Yes, a simple way to fix it is to declare the tst_multiply_timeout()
in tst_common.h directly, then the lib can build successfully.
--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -26,6 +26,8 @@
#define LTP_ALIGN(x, a) __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
#define __LTP_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+unsigned int tst_multiply_timeout(unsigned int timeout);
+
/**
* TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
* @FUNC - The function which will be retried
--
Regards,
Li Wang
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v5] lib: Use backoff polling to wait for loop device nodes
2026-08-05 7:10 ` Li Wang
@ 2026-08-07 10:04 ` Wake Liu via ltp
2026-08-07 11:05 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 17+ messages in thread
From: Wake Liu via ltp @ 2026-08-07 10:04 UTC (permalink / raw)
To: ltp; +Cc: wakel
On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.
Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
doubling each try, capped at 100ms) to wait for the device node to be
successfully populated.
This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.
Signed-off-by: Wake Liu <wakel@google.com>
---
v4 -> v5:
- Declare tst_multiply_timeout() in tst_common.h to fix old API build failures in CI.
v3 -> v4:
- Rebase onto the latest LTP HEAD.
- Remove self-referencing Link in commit message.
v2 -> v3:
- Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.
v1 -> v2:
- Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
- Skip usleep on final loop iteration to avoid unnecessary idle delay.
- Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.
include/tst_common.h | 2 ++
lib/tst_device.c | 13 +++++++++----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/include/tst_common.h b/include/tst_common.h
index e1f7c7907..d09edbbbe 100644
--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -26,6 +26,8 @@
#define LTP_ALIGN(x, a) __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
#define __LTP_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+unsigned int tst_multiply_timeout(unsigned int timeout);
+
/**
* TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
* @FUNC - The function which will be retried
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffe..00304711b 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
int tst_find_free_loopdev(char *path, size_t path_len)
{
- int ctl_fd, dev_fd, rc, i;
+ int ctl_fd, dev_fd, rc, i, path_set;
struct loop_info loopinfo;
char buf[PATH_MAX];
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
close(ctl_fd);
if (rc >= 0) {
- if (path && set_dev_loop_path(rc, path, path_len))
- tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ if (path) {
+ path_set = TST_RETRY_FN_EXP_BACKOFF(
+ set_dev_loop_path(rc, path, path_len),
+ TST_RETVAL_EQ0, 1);
+ if (path_set)
+ tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ }
tst_resm(TINFO, "Found free device %d '%s'",
rc, path ?: "");
return rc;
@@ -161,7 +166,7 @@ int tst_attach_device(const char *dev, const char *file)
LO_NAME_SIZE);
}
- dev_fd = open(dev, O_RDWR);
+ dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
if (dev_fd < 0) {
tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
return 1;
--
2.55.0.654.g21b8a5bc05-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [LTP] lib: Use backoff polling to wait for loop device nodes
2026-08-07 10:04 ` [LTP] [PATCH v5] " Wake Liu via ltp
@ 2026-08-07 11:05 ` linuxtestproject.agent
2026-08-07 23:49 ` [LTP] [PATCH v6] " Wake Liu via ltp
0 siblings, 1 reply; 17+ messages in thread
From: linuxtestproject.agent @ 2026-08-07 11:05 UTC (permalink / raw)
To: Wake Liu; +Cc: ltp
Hi Wake,
On Aug 7, 2026, Wake Liu wrote:
> lib: Use backoff polling to wait for loop device nodes
> Introduce an exponential-backoff retry loop in both
> tst_find_free_loopdev() and tst_attach_device() (starting at 1ms delay,
> doubling each try, capped at 100ms) to wait for the device node to be
> successfully populated.
Could the timing description be corrected, or the implementation changed to
match it? TST_RETRY_FN_EXP_BACKOFF() starts tst_delay_ at 1 and passes it to
usleep(), so the first delay is 1 microsecond. MAX_DELAY is converted from
seconds to microseconds, so passing 1 retries for about one second before LTP
timeout scaling, not 100 ms.
Verdict - Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v6] lib: Use backoff polling to wait for loop device nodes
2026-08-07 11:05 ` [LTP] " linuxtestproject.agent
@ 2026-08-07 23:49 ` Wake Liu via ltp
2026-08-08 1:32 ` [LTP] " linuxtestproject.agent
0 siblings, 1 reply; 17+ messages in thread
From: Wake Liu via ltp @ 2026-08-07 23:49 UTC (permalink / raw)
To: ltp; +Cc: wakel
On systems where loop device node creation is asynchronous (such as Android
containers or systems with slow udev startup), calling stat() or open()
immediately after LOOP_CTL_GET_FREE can transiently fail because the
device file (e.g. /dev/loopX) has not been fully populated in time.
Introduce an exponential-backoff retry loop in both
tst_find_free_loopdev() and tst_attach_device() by reusing the LTP native
TST_RETRY_FN_EXP_BACKOFF() macro (starting at 1us delay, doubling each try,
with a base timeout limit of 1 second that scales automatically with
LTP_TIMEOUT_MUL) to wait for the device node to be successfully populated.
This improves the robustness of loop device allocations on asynchronous
virtualized environments while minimizing unnecessary delays on responsive
systems.
Signed-off-by: Wake Liu <wakel@google.com>
---
v5 -> v6:
- Correct timing descriptions in commit message to match the actual behavior of TST_RETRY_FN_EXP_BACKOFF() macro (1us initial delay, 1s base timeout).
v4 -> v5:
- Declare tst_multiply_timeout() in tst_common.h to fix old API build failures in CI.
v3 -> v4:
- Rebase onto the latest LTP HEAD.
- Remove self-referencing Link in commit message.
v2 -> v3:
- Reuse LTP native TST_RETRY_FN_EXP_BACKOFF() macro in tst_common.h to simplify code.
v1 -> v2:
- Strictly clamp backoff delay to 100ms (prevent overflow exceeding cap).
- Skip usleep on final loop iteration to avoid unnecessary idle delay.
- Reduce max attempts to 30 (stat) and 15 (open) to bound worst-case timeout.
include/tst_common.h | 2 ++
lib/tst_device.c | 13 +++++++++----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/include/tst_common.h b/include/tst_common.h
index e1f7c7907..d09edbbbe 100644
--- a/include/tst_common.h
+++ b/include/tst_common.h
@@ -26,6 +26,8 @@
#define LTP_ALIGN(x, a) __LTP_ALIGN_MASK(x, (typeof(x))(a) - 1)
#define __LTP_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+unsigned int tst_multiply_timeout(unsigned int timeout);
+
/**
* TST_RETRY_FUNC() - Repeatedly retry a function with an increasing delay.
* @FUNC - The function which will be retried
diff --git a/lib/tst_device.c b/lib/tst_device.c
index 744173ffe..00304711b 100644
--- a/lib/tst_device.c
+++ b/lib/tst_device.c
@@ -82,7 +82,7 @@ static int set_dev_path(char *dev, char *path, size_t path_len)
int tst_find_free_loopdev(char *path, size_t path_len)
{
- int ctl_fd, dev_fd, rc, i;
+ int ctl_fd, dev_fd, rc, i, path_set;
struct loop_info loopinfo;
char buf[PATH_MAX];
@@ -93,8 +93,13 @@ int tst_find_free_loopdev(char *path, size_t path_len)
rc = ioctl(ctl_fd, LOOP_CTL_GET_FREE);
close(ctl_fd);
if (rc >= 0) {
- if (path && set_dev_loop_path(rc, path, path_len))
- tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ if (path) {
+ path_set = TST_RETRY_FN_EXP_BACKOFF(
+ set_dev_loop_path(rc, path, path_len),
+ TST_RETVAL_EQ0, 1);
+ if (path_set)
+ tst_brkm(TBROK, NULL, "Could not stat loop device %i", rc);
+ }
tst_resm(TINFO, "Found free device %d '%s'",
rc, path ?: "");
return rc;
@@ -161,7 +166,7 @@ int tst_attach_device(const char *dev, const char *file)
LO_NAME_SIZE);
}
- dev_fd = open(dev, O_RDWR);
+ dev_fd = TST_RETRY_FN_EXP_BACKOFF(open(dev, O_RDWR), TST_RETVAL_GE0, 1);
if (dev_fd < 0) {
tst_resm(TWARN | TERRNO, "open('%s', O_RDWR) failed", dev);
return 1;
--
2.55.0.654.g21b8a5bc05-goog
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [LTP] lib: Use backoff polling to wait for loop device nodes
2026-08-07 23:49 ` [LTP] [PATCH v6] " Wake Liu via ltp
@ 2026-08-08 1:32 ` linuxtestproject.agent
0 siblings, 0 replies; 17+ messages in thread
From: linuxtestproject.agent @ 2026-08-08 1:32 UTC (permalink / raw)
To: Wake Liu; +Cc: ltp
Hi Wake,
On Fri, 7 Aug 2026, Wake Liu wrote:
> lib: Use backoff polling to wait for loop device nodes
> + path_set = TST_RETRY_FN_EXP_BACKOFF(
> + set_dev_loop_path(rc, path, path_len),
> + TST_RETVAL_EQ0, 1);
Could the backoff arithmetic be made overflow-safe before these two new
uses?
LTP_TIMEOUT_MUL=3000 is accepted by parse_mul(), which makes
tst_max_delay_ 3,000,000,000. The unsigned int tst_delay_ reaches
2,147,483,648, still compares less than tst_max_delay_, and then doubles
to zero. If the device node does not appear, both new paths then retry
forever instead of honoring the multiplied timeout.
Verdict - Needs revision
---
Note:
The agent can sometimes produce false positives although often its
findings are genuine. If you find issues with the review, please
comment this email or ignore the suggestions.
Regards,
LTP AI Reviewer
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-08-08 1:33 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-03 15:27 [LTP] [PATCH] lib: Use exponential-backoff polling to wait for loop device nodes Wake Liu via ltp
2026-08-03 16:28 ` [LTP] " linuxtestproject.agent
2026-08-04 1:59 ` [LTP] [PATCH v2] lib: Use backoff " Wake Liu via ltp
2026-08-04 3:58 ` Li Wang
2026-08-04 15:24 ` [LTP] [PATCH v3] " Wake Liu via ltp
2026-08-05 2:24 ` Li Wang
2026-08-05 2:54 ` [LTP] [PATCH v4] " Wake Liu via ltp
2026-08-05 4:09 ` [LTP] " linuxtestproject.agent
2026-08-05 6:53 ` Li Wang
2026-08-05 6:35 ` [LTP] [PATCH v4] " Li Wang
2026-08-05 6:52 ` Andrea Cervesato via ltp
2026-08-05 6:55 ` Andrea Cervesato via ltp
2026-08-05 7:10 ` Li Wang
2026-08-07 10:04 ` [LTP] [PATCH v5] " Wake Liu via ltp
2026-08-07 11:05 ` [LTP] " linuxtestproject.agent
2026-08-07 23:49 ` [LTP] [PATCH v6] " Wake Liu via ltp
2026-08-08 1:32 ` [LTP] " linuxtestproject.agent
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox