* [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test
@ 2025-06-03 15:22 Martin Doucha
2025-06-03 15:22 ` [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec Martin Doucha
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Martin Doucha @ 2025-06-03 15:22 UTC (permalink / raw)
To: ltp
There seems to be a regression in kernel v6.14 where epoll_pwait2()
interprets very small timeout values (~1000ns) as infinity and waits
for events forever. This patchset adds regression test for this bug
and a necessary refactor for do_epoll_pwait() to allow high precision
timeouts.
Martin Doucha (2):
epoll_pwait: Refactor timeout to struct timespec
Add regression test for epoll_pwait2() timeout
runtest/syscalls | 1 +
.../kernel/syscalls/epoll_pwait/.gitignore | 1 +
.../syscalls/epoll_pwait/epoll_pwait01.c | 4 +-
.../syscalls/epoll_pwait/epoll_pwait02.c | 2 +-
.../syscalls/epoll_pwait/epoll_pwait03.c | 9 +-
.../syscalls/epoll_pwait/epoll_pwait04.c | 2 +-
.../syscalls/epoll_pwait/epoll_pwait06.c | 87 +++++++++++++++++++
.../syscalls/epoll_pwait/epoll_pwait_var.h | 22 ++---
8 files changed, 110 insertions(+), 18 deletions(-)
create mode 100644 testcases/kernel/syscalls/epoll_pwait/epoll_pwait06.c
--
2.49.0
--
Mailing list info: https://lists.linux.it/listinfo/ltp
^ permalink raw reply [flat|nested] 10+ messages in thread* [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec 2025-06-03 15:22 [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test Martin Doucha @ 2025-06-03 15:22 ` Martin Doucha 2025-06-04 6:35 ` Petr Vorel 2025-06-04 7:01 ` Andrea Cervesato via ltp 2025-06-03 15:22 ` [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout Martin Doucha 2025-06-04 7:34 ` [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test Petr Vorel 2 siblings, 2 replies; 10+ messages in thread From: Martin Doucha @ 2025-06-03 15:22 UTC (permalink / raw) To: ltp Support higher precision timeout in do_epoll_pwait() by passing struct timespec instead of int value in milliseconds. Only one test actually uses the parameter. Signed-off-by: Martin Doucha <mdoucha@suse.cz> --- Changes since v1: None .../syscalls/epoll_pwait/epoll_pwait01.c | 4 ++-- .../syscalls/epoll_pwait/epoll_pwait02.c | 2 +- .../syscalls/epoll_pwait/epoll_pwait03.c | 9 +++++--- .../syscalls/epoll_pwait/epoll_pwait04.c | 2 +- .../syscalls/epoll_pwait/epoll_pwait_var.h | 22 +++++++++---------- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c index 954e77314..012ba1562 100644 --- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait01.c @@ -30,7 +30,7 @@ static void sighandler(int sig LTP_ATTRIBUTE_UNUSED) {} static void verify_sigmask(void) { - TEST(do_epoll_pwait(efd, &e, 1, -1, &signalset)); + TEST(do_epoll_pwait(efd, &e, 1, NULL, &signalset)); if (TST_RET != 1) { tst_res(TFAIL, "do_epoll_pwait() returned %li, expected 1", @@ -43,7 +43,7 @@ static void verify_sigmask(void) static void verify_nonsigmask(void) { - TST_EXP_FAIL(do_epoll_pwait(efd, &e, 1, -1, NULL), EINTR, + TST_EXP_FAIL(do_epoll_pwait(efd, &e, 1, NULL, NULL), EINTR, "do_epoll_pwait() without sigmask"); } diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c index 069620c5d..a27c7db9e 100644 --- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait02.c @@ -19,7 +19,7 @@ static struct epoll_event e; static void run(void) { - TEST(do_epoll_pwait(efd, &e, 1, -1, NULL)); + TEST(do_epoll_pwait(efd, &e, 1, NULL, NULL)); if (TST_RET == 1) { tst_res(TPASS, "do_epoll_pwait() succeeded"); diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c index 8217f9f80..572d347f1 100644 --- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait03.c @@ -13,17 +13,20 @@ #include "tst_timer_test.h" #include "epoll_pwait_var.h" -#define USEC_PER_MSEC (1000L) +#define USEC_PER_NSEC (1000L) +#define USEC_PER_SEC (1000000L) static int efd, sfd[2]; static struct epoll_event e; int sample_fn(int clk_id, long long usec) { - unsigned int ms = usec / USEC_PER_MSEC; + struct timespec ts; + ts.tv_sec = usec / USEC_PER_SEC; + ts.tv_nsec = (usec % USEC_PER_SEC) * USEC_PER_NSEC; tst_timer_start(clk_id); - TEST(do_epoll_pwait(efd, &e, 1, ms, NULL)); + TEST(do_epoll_pwait(efd, &e, 1, &ts, NULL)); tst_timer_stop(); tst_timer_sample(); diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c index cc1d04e6b..b399225b9 100644 --- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait04.c @@ -20,7 +20,7 @@ static void *bad_addr; static void run(void) { - TST_EXP_FAIL(do_epoll_pwait(efd, &e, 1, -1, bad_addr), + TST_EXP_FAIL(do_epoll_pwait(efd, &e, 1, NULL, bad_addr), EFAULT, "with an invalid sigmask pointer"); } diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait_var.h b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait_var.h index 58a3f15a2..454e80a87 100644 --- a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait_var.h +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait_var.h @@ -14,22 +14,22 @@ #define NSEC_PER_MSEC (1000000L) static int do_epoll_pwait(int epfd, struct epoll_event *events, int - maxevents, int timeout, const sigset_t *sigmask) + maxevents, struct timespec *timeout, const sigset_t *sigmask) { - if (tst_variant == 0) - return epoll_pwait(epfd, events, maxevents, timeout, sigmask); + if (tst_variant == 0) { + int timeout_ms = -1; - struct timespec ts; + if (timeout) { + timeout_ms = timeout->tv_sec * MSEC_PER_SEC; + timeout_ms += (timeout->tv_nsec + NSEC_PER_MSEC - 1) / + NSEC_PER_MSEC; + } - if (timeout < 0) { - return epoll_pwait2(epfd, events, maxevents, NULL, sigmask); - } else { - ts.tv_sec = timeout / MSEC_PER_SEC; - ts.tv_nsec = NSEC_PER_MSEC * (timeout % MSEC_PER_SEC); + return epoll_pwait(epfd, events, maxevents, timeout_ms, + sigmask); } - return epoll_pwait2(epfd, events, maxevents, &ts, sigmask); - + return epoll_pwait2(epfd, events, maxevents, timeout, sigmask); } static void epoll_pwait_init(void) -- 2.49.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec 2025-06-03 15:22 ` [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec Martin Doucha @ 2025-06-04 6:35 ` Petr Vorel 2025-06-04 12:10 ` Martin Doucha 2025-06-04 7:01 ` Andrea Cervesato via ltp 1 sibling, 1 reply; 10+ messages in thread From: Petr Vorel @ 2025-06-04 6:35 UTC (permalink / raw) To: Martin Doucha; +Cc: ltp Hi Martin, > Support higher precision timeout in do_epoll_pwait() by passing struct > timespec instead of int value in milliseconds. Only one test actually > uses the parameter. Ah, you mean epoll_pwait03.c. Reviewed-by: Petr Vorel <pvorel@suse.cz> ... > +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait_var.h > @@ -14,22 +14,22 @@ > #define NSEC_PER_MSEC (1000000L) > static int do_epoll_pwait(int epfd, struct epoll_event *events, int > - maxevents, int timeout, const sigset_t *sigmask) > + maxevents, struct timespec *timeout, const sigset_t *sigmask) > { > - if (tst_variant == 0) > - return epoll_pwait(epfd, events, maxevents, timeout, sigmask); > + if (tst_variant == 0) { > + int timeout_ms = -1; very nit: I would reverse the condition to save indent for tst_variant == 0: if (tst_variant != 0) return epoll_pwait2(epfd, events, maxevents, timeout, sigmask); ... Kind regards, Petr > - struct timespec ts; > + if (timeout) { > + timeout_ms = timeout->tv_sec * MSEC_PER_SEC; > + timeout_ms += (timeout->tv_nsec + NSEC_PER_MSEC - 1) / > + NSEC_PER_MSEC; > + } > - if (timeout < 0) { > - return epoll_pwait2(epfd, events, maxevents, NULL, sigmask); > - } else { > - ts.tv_sec = timeout / MSEC_PER_SEC; > - ts.tv_nsec = NSEC_PER_MSEC * (timeout % MSEC_PER_SEC); > + return epoll_pwait(epfd, events, maxevents, timeout_ms, > + sigmask); > } > - return epoll_pwait2(epfd, events, maxevents, &ts, sigmask); > - > + return epoll_pwait2(epfd, events, maxevents, timeout, sigmask); > } > static void epoll_pwait_init(void) -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec 2025-06-04 6:35 ` Petr Vorel @ 2025-06-04 12:10 ` Martin Doucha 2025-06-05 6:28 ` Petr Vorel 0 siblings, 1 reply; 10+ messages in thread From: Martin Doucha @ 2025-06-04 12:10 UTC (permalink / raw) To: Petr Vorel; +Cc: ltp Hi! On 04. 06. 25 8:35, Petr Vorel wrote: > Hi Martin, > >> Support higher precision timeout in do_epoll_pwait() by passing struct >> timespec instead of int value in milliseconds. Only one test actually >> uses the parameter. > > Ah, you mean epoll_pwait03.c. Yes. > Reviewed-by: Petr Vorel <pvorel@suse.cz> > > ... >> +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait_var.h >> @@ -14,22 +14,22 @@ >> #define NSEC_PER_MSEC (1000000L) > >> static int do_epoll_pwait(int epfd, struct epoll_event *events, int >> - maxevents, int timeout, const sigset_t *sigmask) >> + maxevents, struct timespec *timeout, const sigset_t *sigmask) >> { >> - if (tst_variant == 0) >> - return epoll_pwait(epfd, events, maxevents, timeout, sigmask); >> + if (tst_variant == 0) { >> + int timeout_ms = -1; > > very nit: I would reverse the condition to save indent for tst_variant == 0: Feel free to do it during merge, but it'd be better to check (tst_variant == 1) instead in case there will be epoll_pwait3() in the future. > > if (tst_variant != 0) > return epoll_pwait2(epfd, events, maxevents, timeout, sigmask); > ... -- Martin Doucha mdoucha@suse.cz SW Quality Engineer SUSE LINUX, s.r.o. CORSO IIa Krizikova 148/34 186 00 Prague 8 Czech Republic -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec 2025-06-04 12:10 ` Martin Doucha @ 2025-06-05 6:28 ` Petr Vorel 0 siblings, 0 replies; 10+ messages in thread From: Petr Vorel @ 2025-06-05 6:28 UTC (permalink / raw) To: Martin Doucha; +Cc: ltp Hi Martin, ... > > > +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait_var.h > > > @@ -14,22 +14,22 @@ > > > #define NSEC_PER_MSEC (1000000L) > > > static int do_epoll_pwait(int epfd, struct epoll_event *events, int > > > - maxevents, int timeout, const sigset_t *sigmask) > > > + maxevents, struct timespec *timeout, const sigset_t *sigmask) > > > { > > > - if (tst_variant == 0) > > > - return epoll_pwait(epfd, events, maxevents, timeout, sigmask); > > > + if (tst_variant == 0) { > > > + int timeout_ms = -1; > > very nit: I would reverse the condition to save indent for tst_variant == 0: > Feel free to do it during merge, but it'd be better to check (tst_variant == > 1) instead in case there will be epoll_pwait3() in the future. Thanks for your ack + good point, changed as tst_variant == 1. Patchset merged, thanks! Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec 2025-06-03 15:22 ` [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec Martin Doucha 2025-06-04 6:35 ` Petr Vorel @ 2025-06-04 7:01 ` Andrea Cervesato via ltp 1 sibling, 0 replies; 10+ messages in thread From: Andrea Cervesato via ltp @ 2025-06-04 7:01 UTC (permalink / raw) To: Martin Doucha, ltp Reviewed-by: Andrea Cervesato <andrea.cevesato@suse.com> -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 10+ messages in thread
* [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout 2025-06-03 15:22 [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test Martin Doucha 2025-06-03 15:22 ` [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec Martin Doucha @ 2025-06-03 15:22 ` Martin Doucha 2025-06-04 7:01 ` Andrea Cervesato via ltp 2025-06-04 7:29 ` Petr Vorel 2025-06-04 7:34 ` [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test Petr Vorel 2 siblings, 2 replies; 10+ messages in thread From: Martin Doucha @ 2025-06-03 15:22 UTC (permalink / raw) To: ltp Signed-off-by: Martin Doucha <mdoucha@suse.cz> --- Changes since v1: - Added kernel fix reference - Use SAFE_EPOLL_*() functions runtest/syscalls | 1 + .../kernel/syscalls/epoll_pwait/.gitignore | 1 + .../syscalls/epoll_pwait/epoll_pwait06.c | 87 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_pwait/epoll_pwait06.c diff --git a/runtest/syscalls b/runtest/syscalls index e7bc7b27b..2a968099a 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -192,6 +192,7 @@ epoll_pwait02 epoll_pwait02 epoll_pwait03 epoll_pwait03 epoll_pwait04 epoll_pwait04 epoll_pwait05 epoll_pwait05 +epoll_pwait06 epoll_pwait06 eventfd01 eventfd01 eventfd02 eventfd02 diff --git a/testcases/kernel/syscalls/epoll_pwait/.gitignore b/testcases/kernel/syscalls/epoll_pwait/.gitignore index fafb2d782..81e77b8d0 100644 --- a/testcases/kernel/syscalls/epoll_pwait/.gitignore +++ b/testcases/kernel/syscalls/epoll_pwait/.gitignore @@ -3,3 +3,4 @@ epoll_pwait02 epoll_pwait03 epoll_pwait04 epoll_pwait05 +epoll_pwait06 diff --git a/testcases/kernel/syscalls/epoll_pwait/epoll_pwait06.c b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait06.c new file mode 100644 index 000000000..3bedc2cf5 --- /dev/null +++ b/testcases/kernel/syscalls/epoll_pwait/epoll_pwait06.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2025 SUSE LLC <mdoucha@suse.cz> + */ + +/*\ + * Verify that various timeout values don't get misinterpreted as infinity + * by epoll_pwait() and epoll_pwait2(). Regression fixed in: + * + * commit d9ec73301099ec5975505e1c3effbe768bab9490 + * Author: Max Kellermann <max.kellermann@ionos.com> + * Date: Tue Apr 29 20:58:27 2025 +0200 + * + * fs/eventpoll: fix endless busy loop after timeout has expired + */ + +#include "tst_test.h" +#include "tst_timer.h" +#include "tst_epoll.h" +#include "epoll_pwait_var.h" + +static int efd = -1; + +static void run(void) +{ + struct timespec timeout = {}; + struct epoll_event e = {}; + + e.events = EPOLLIN; + + TST_FD_FOREACH(fd_in) { + /* File descriptor types not supported by epoll */ + switch (fd_in.type) { + case TST_FD_FILE: + case TST_FD_PATH: + case TST_FD_DIR: + case TST_FD_DEV_ZERO: + case TST_FD_PROC_MAPS: + case TST_FD_FSOPEN: + case TST_FD_FSPICK: + case TST_FD_OPEN_TREE: + case TST_FD_MEMFD: + case TST_FD_MEMFD_SECRET: + continue; + default: + break; + } + + tst_res(TINFO, "Testing %s", tst_fd_desc(&fd_in)); + timeout.tv_nsec = 1000000000; + SAFE_EPOLL_CTL(efd, EPOLL_CTL_ADD, fd_in.fd, &e); + + do { + alarm(1); + timeout.tv_nsec /= 10; + do_epoll_pwait(efd, &e, 1, &timeout, NULL); + alarm(0); + } while (timeout.tv_nsec); + + SAFE_EPOLL_CTL(efd, EPOLL_CTL_DEL, fd_in.fd, &e); + } + + tst_res(TPASS, "Timeout works correctly"); +} + +static void setup(void) +{ + epoll_pwait_init(); + efd = SAFE_EPOLL_CREATE1(0); +} + +static void cleanup(void) +{ + if (efd >= 0) + SAFE_CLOSE(efd); +} + +static struct tst_test test = { + .test_all = run, + .setup = setup, + .cleanup = cleanup, + .test_variants = TEST_VARIANTS, + .tags = (const struct tst_tag[]) { + {"linux-git", "d9ec73301099"}, + {} + } +}; -- 2.49.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout 2025-06-03 15:22 ` [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout Martin Doucha @ 2025-06-04 7:01 ` Andrea Cervesato via ltp 2025-06-04 7:29 ` Petr Vorel 1 sibling, 0 replies; 10+ messages in thread From: Andrea Cervesato via ltp @ 2025-06-04 7:01 UTC (permalink / raw) To: Martin Doucha, ltp Reviewed-by: Andrea Cervesato <andrea.cervesato@suse.com> -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout 2025-06-03 15:22 ` [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout Martin Doucha 2025-06-04 7:01 ` Andrea Cervesato via ltp @ 2025-06-04 7:29 ` Petr Vorel 1 sibling, 0 replies; 10+ messages in thread From: Petr Vorel @ 2025-06-04 7:29 UTC (permalink / raw) To: Martin Doucha; +Cc: ltp Hi Martin, LGTM, thanks for this regression test! Reviewed-by: Petr Vorel <pvorel@suse.cz> Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test 2025-06-03 15:22 [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test Martin Doucha 2025-06-03 15:22 ` [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec Martin Doucha 2025-06-03 15:22 ` [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout Martin Doucha @ 2025-06-04 7:34 ` Petr Vorel 2 siblings, 0 replies; 10+ messages in thread From: Petr Vorel @ 2025-06-04 7:34 UTC (permalink / raw) To: Martin Doucha; +Cc: ltp Hi Martin, > There seems to be a regression in kernel v6.14 where epoll_pwait2() > interprets very small timeout values (~1000ns) as infinity and waits > for events forever. This patchset adds regression test for this bug > and a necessary refactor for do_epoll_pwait() to allow high precision > timeouts. Good catch! BTW it looks to me 0a65bc27bd64 is from v6.15-rc3 (e.g. 6.15 development cycle), but it was backported to 6.14 stable as 99a0ad16dfd11 to v6.14.4. Obviously fixing commit d9ec73301099 has also been backported (to v6.14.8). Kind regards, Petr -- Mailing list info: https://lists.linux.it/listinfo/ltp ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-06-05 6:28 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-06-03 15:22 [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test Martin Doucha 2025-06-03 15:22 ` [LTP] [PATCH v2 1/2] epoll_pwait: Refactor timeout to struct timespec Martin Doucha 2025-06-04 6:35 ` Petr Vorel 2025-06-04 12:10 ` Martin Doucha 2025-06-05 6:28 ` Petr Vorel 2025-06-04 7:01 ` Andrea Cervesato via ltp 2025-06-03 15:22 ` [LTP] [PATCH v2 2/2] Add regression test for epoll_pwait2() timeout Martin Doucha 2025-06-04 7:01 ` Andrea Cervesato via ltp 2025-06-04 7:29 ` Petr Vorel 2025-06-04 7:34 ` [LTP] [PATCH v2 0/2] epoll_pwait2() timeout regression test Petr Vorel
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox