[1/1] Linux: Add epoll ioctls

Message ID 20240525003814.447806-2-jdamato@fastly.com
State Superseded
Delegated to: Adhemerval Zanella Netto
Headers
Series Linux: Add epoll ioctls |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Testing passed
redhat-pt-bot/TryBot-32bit success Build for i686
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Testing passed

Commit Message

Joe Damato May 25, 2024, 12:38 a.m. UTC
  As of Linux kernel 6.9, some ioctls and a parameters structure have been
introduced which allow user programs to control whether a particular
epoll context will busy poll.

Update the headers to include these for the convenience of user apps.

Signed-off-by: Joe Damato <jdamato@fastly.com>
---
 NEWS                                |  3 ++
 sysdeps/unix/sysv/linux/sys/epoll.h | 13 +++++++
 sysdeps/unix/sysv/linux/tst-epoll.c | 55 +++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)
  

Comments

Adhemerval Zanella Netto May 27, 2024, 5 p.m. UTC | #1
On 24/05/24 21:38, Joe Damato wrote:
> As of Linux kernel 6.9, some ioctls and a parameters structure have been
> introduced which allow user programs to control whether a particular
> epoll context will busy poll.
> 
> Update the headers to include these for the convenience of user apps.
> 
> Signed-off-by: Joe Damato <jdamato@fastly.com>

Look good, I just think this should a newer tests instead of a extra
subtest on current tst-epoll.c.

> ---
>  NEWS                                |  3 ++
>  sysdeps/unix/sysv/linux/sys/epoll.h | 13 +++++++
>  sysdeps/unix/sysv/linux/tst-epoll.c | 55 +++++++++++++++++++++++++++++
>  3 files changed, 71 insertions(+)
> 
> diff --git a/NEWS b/NEWS
> index 84efa46df3..20e263f581 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -33,6 +33,9 @@ Major new features:
>    more extensive verification tests for AT_SECURE programs and not meant to
>    be a security feature.
>  
> +* On Linux, update epoll header to include epoll ioctl definitions and
> +  related structure added in Linux kernel 6.9.
> +
>  Deprecated and removed features, and other changes affecting compatibility:
>  
>  * Architectures which use a 32-bit seconds-since-epoch field in struct
> diff --git a/sysdeps/unix/sysv/linux/sys/epoll.h b/sysdeps/unix/sysv/linux/sys/epoll.h
> index fc8dce45c8..cf04ba55f0 100644
> --- a/sysdeps/unix/sysv/linux/sys/epoll.h
> +++ b/sysdeps/unix/sysv/linux/sys/epoll.h
> @@ -19,6 +19,7 @@
>  #define	_SYS_EPOLL_H	1
>  
>  #include <stdint.h>
> +#include <sys/ioctl.h>
>  #include <sys/types.h>
>  
>  #include <bits/types/sigset_t.h>
> @@ -87,6 +88,18 @@ struct epoll_event
>    epoll_data_t data;	/* User data variable */
>  } __EPOLL_PACKED;
>  
> +struct epoll_params {

The open curly bracket should be in the next line per code guideline. 

> +  uint32_t busy_poll_usecs;
> +  uint16_t busy_poll_budget;
> +  uint8_t prefer_busy_poll;
> +
> +  /* pad the struct to a multiple of 64bits */
> +  uint8_t __pad;
> +};
> +
> +#define EPOLL_IOC_TYPE 0x8A
> +#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
> +#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)

Ok, this follow kernel commit 18e2bf0edf4dd.

>  
>  __BEGIN_DECLS
>  
> diff --git a/sysdeps/unix/sysv/linux/tst-epoll.c b/sysdeps/unix/sysv/linux/tst-epoll.c
> index 545f506faa..961a63c33d 100644
> --- a/sysdeps/unix/sysv/linux/tst-epoll.c
> +++ b/sysdeps/unix/sysv/linux/tst-epoll.c
> @@ -24,6 +24,8 @@
>  #include <support/xunistd.h>
>  #include <support/process_state.h>
>  #include <stdlib.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
>  #include <sys/epoll.h>
>  
>  /* The test focus on checking if the timeout argument is correctly handled
> @@ -177,6 +179,56 @@ epoll_pwait2_check (int epfd, struct epoll_event *ev, int maxev, int tmo,
>    return epoll_pwait2 (epfd, ev, maxev, &(struct timespec) { s, ns }, ss);
>  }
>  
> +static void
> +test_epoll_ioctl (void)
> +{
> +  int efd = epoll_create1 (0);
> +  TEST_VERIFY_EXIT (efd != -1);
> +
> +  struct epoll_params params;
> +
> +  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
> +
> +  /* parameters are all 0 by default */
> +  TEST_COMPARE (params.busy_poll_usecs, 0);
> +  TEST_COMPARE (params.busy_poll_budget, 0);
> +  TEST_COMPARE (params.prefer_busy_poll, 0);
> +  TEST_COMPARE (params.__pad, 0);

I take this field would continue to be zero in future versions.

> +
> +  /* set custom parameters */
> +  params.busy_poll_usecs = 40;
> +  params.busy_poll_budget = 8;
> +  params.prefer_busy_poll = 1;
> +  params.__pad = 0;
> +
> +  TEST_COMPARE (ioctl (efd, EPIOCSPARAMS, &params), 0);
> +
> +  memset (&params, 0, sizeof (params));
> +
> +  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
> +
> +  /* check custom values were retrieved after being set */
> +  TEST_COMPARE (params.busy_poll_usecs, 40);
> +  TEST_COMPARE (params.busy_poll_budget, 8);
> +  TEST_COMPARE (params.prefer_busy_poll, 1);
> +  TEST_COMPARE (params.__pad, 0);
> +
> +  xclose (efd);
> +}
> +
> +static bool
> +ioctl_supported (void)
> +{
> +  int efd = epoll_create1 (0);
> +  TEST_VERIFY_EXIT (efd != -1);
> +
> +  struct epoll_params params;
> +  int r = ioctl (efd, EPIOCGPARAMS, &params);
> +  xclose (efd);
> +
> +  return (r == 0);
> +}
> +
>  static int
>  do_test (void)
>  {
> @@ -207,6 +259,9 @@ do_test (void)
>    if (pwait2_supported)
>      test_epoll_large_timeout (epoll_pwait2_check);
>  
> +  if (ioctl_supported ())
> +    test_epoll_ioctl ();
> +
>    return 0;
>  }
>  

The test look ok, although I think it should be move to a new test so for
the !ioctl_supported it can return TEST_UNSUPPORTED (and tester knows that
some features might not be supported/check on current kernel).
  
Joe Damato May 27, 2024, 6 p.m. UTC | #2
On Mon, May 27, 2024 at 02:00:32PM -0300, Adhemerval Zanella Netto wrote:
> 
> 
> On 24/05/24 21:38, Joe Damato wrote:
> > As of Linux kernel 6.9, some ioctls and a parameters structure have been
> > introduced which allow user programs to control whether a particular
> > epoll context will busy poll.
> > 
> > Update the headers to include these for the convenience of user apps.
> > 
> > Signed-off-by: Joe Damato <jdamato@fastly.com>
> 
> Look good, I just think this should a newer tests instead of a extra
> subtest on current tst-epoll.c.

Thank you very much for your time and energy giving this a review.

I am happy to move the test to a separate test in a v2 if you prefer
that. I wrote the test this way because I saw how (for example)
epoll_pwait2 was tested in tst-epoll.c (with a check that it is
supported and then the real test).

If you'd still prefer that I move the ioctl test to a separate file,
please let me know. In that case, perhaps a future work can be
moving the pwait2 test to its own file, as well.

> > ---
> >  NEWS                                |  3 ++
> >  sysdeps/unix/sysv/linux/sys/epoll.h | 13 +++++++
> >  sysdeps/unix/sysv/linux/tst-epoll.c | 55 +++++++++++++++++++++++++++++
> >  3 files changed, 71 insertions(+)
> > 
> > diff --git a/NEWS b/NEWS
> > index 84efa46df3..20e263f581 100644
> > --- a/NEWS
> > +++ b/NEWS
> > @@ -33,6 +33,9 @@ Major new features:
> >    more extensive verification tests for AT_SECURE programs and not meant to
> >    be a security feature.
> >  
> > +* On Linux, update epoll header to include epoll ioctl definitions and
> > +  related structure added in Linux kernel 6.9.
> > +
> >  Deprecated and removed features, and other changes affecting compatibility:
> >  
> >  * Architectures which use a 32-bit seconds-since-epoch field in struct
> > diff --git a/sysdeps/unix/sysv/linux/sys/epoll.h b/sysdeps/unix/sysv/linux/sys/epoll.h
> > index fc8dce45c8..cf04ba55f0 100644
> > --- a/sysdeps/unix/sysv/linux/sys/epoll.h
> > +++ b/sysdeps/unix/sysv/linux/sys/epoll.h
> > @@ -19,6 +19,7 @@
> >  #define	_SYS_EPOLL_H	1
> >  
> >  #include <stdint.h>
> > +#include <sys/ioctl.h>
> >  #include <sys/types.h>
> >  
> >  #include <bits/types/sigset_t.h>
> > @@ -87,6 +88,18 @@ struct epoll_event
> >    epoll_data_t data;	/* User data variable */
> >  } __EPOLL_PACKED;
> >  
> > +struct epoll_params {
> 
> The open curly bracket should be in the next line per code guideline. 

Thank you. I can fix this in the v2.

Related question: is there a script that checks for minor style nits
like this? Sorry if I missed such a script in the docs somewhere.

FWIW: the kernel has a script that checks for nits like this which
is very helpful.

> > +  uint32_t busy_poll_usecs;
> > +  uint16_t busy_poll_budget;
> > +  uint8_t prefer_busy_poll;
> > +
> > +  /* pad the struct to a multiple of 64bits */
> > +  uint8_t __pad;
> > +};
> > +
> > +#define EPOLL_IOC_TYPE 0x8A
> > +#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
> > +#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
> 
> Ok, this follow kernel commit 18e2bf0edf4dd.

Yes; in the v2 I can mention this kernel commit SHA and link to the
line in gitweb in the commit message to make it easier to check in
the future, if you like.

Please let me know.

> >  
> >  __BEGIN_DECLS
> >  
> > diff --git a/sysdeps/unix/sysv/linux/tst-epoll.c b/sysdeps/unix/sysv/linux/tst-epoll.c
> > index 545f506faa..961a63c33d 100644
> > --- a/sysdeps/unix/sysv/linux/tst-epoll.c
> > +++ b/sysdeps/unix/sysv/linux/tst-epoll.c
> > @@ -24,6 +24,8 @@
> >  #include <support/xunistd.h>
> >  #include <support/process_state.h>
> >  #include <stdlib.h>
> > +#include <string.h>
> > +#include <sys/ioctl.h>
> >  #include <sys/epoll.h>
> >  
> >  /* The test focus on checking if the timeout argument is correctly handled
> > @@ -177,6 +179,56 @@ epoll_pwait2_check (int epfd, struct epoll_event *ev, int maxev, int tmo,
> >    return epoll_pwait2 (epfd, ev, maxev, &(struct timespec) { s, ns }, ss);
> >  }
> >  
> > +static void
> > +test_epoll_ioctl (void)
> > +{
> > +  int efd = epoll_create1 (0);
> > +  TEST_VERIFY_EXIT (efd != -1);
> > +
> > +  struct epoll_params params;
> > +
> > +  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
> > +
> > +  /* parameters are all 0 by default */
> > +  TEST_COMPARE (params.busy_poll_usecs, 0);
> > +  TEST_COMPARE (params.busy_poll_budget, 0);
> > +  TEST_COMPARE (params.prefer_busy_poll, 0);
> > +  TEST_COMPARE (params.__pad, 0);
> 
> I take this field would continue to be zero in future versions.

The __pad field is checked by the kernel to ensure that it is zero
when EPIOCSPARAMS is used (otherwise an error is returned).

It is possible that bits of the __pad field may be used for other
purposes in the future; I don't have any specific plan right now.

Since the kernel always checks that __pad == 0 and sets __pad = 0,
it would potentially be possible to make __pad a bit field of just 1
bit and use the other bits for a different purpose in the future.

That said, I don't think that changes anything about this test.

> > +
> > +  /* set custom parameters */
> > +  params.busy_poll_usecs = 40;
> > +  params.busy_poll_budget = 8;
> > +  params.prefer_busy_poll = 1;
> > +  params.__pad = 0;
> > +
> > +  TEST_COMPARE (ioctl (efd, EPIOCSPARAMS, &params), 0);
> > +
> > +  memset (&params, 0, sizeof (params));
> > +
> > +  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
> > +
> > +  /* check custom values were retrieved after being set */
> > +  TEST_COMPARE (params.busy_poll_usecs, 40);
> > +  TEST_COMPARE (params.busy_poll_budget, 8);
> > +  TEST_COMPARE (params.prefer_busy_poll, 1);
> > +  TEST_COMPARE (params.__pad, 0);
> > +
> > +  xclose (efd);
> > +}
> > +
> > +static bool
> > +ioctl_supported (void)
> > +{
> > +  int efd = epoll_create1 (0);
> > +  TEST_VERIFY_EXIT (efd != -1);
> > +
> > +  struct epoll_params params;
> > +  int r = ioctl (efd, EPIOCGPARAMS, &params);
> > +  xclose (efd);
> > +
> > +  return (r == 0);
> > +}
> > +
> >  static int
> >  do_test (void)
> >  {
> > @@ -207,6 +259,9 @@ do_test (void)
> >    if (pwait2_supported)
> >      test_epoll_large_timeout (epoll_pwait2_check);
> >  
> > +  if (ioctl_supported ())
> > +    test_epoll_ioctl ();
> > +
> >    return 0;
> >  }
> >  
> 
> The test look ok, although I think it should be move to a new test so for
> the !ioctl_supported it can return TEST_UNSUPPORTED (and tester knows that
> some features might not be supported/check on current kernel).

OK, I can do that. As I mentioned above, I was following the pattern
in place in tst-epoll for epoll_pwait2 but if you prefer a separate
test for the ioctl, please let me know.

Thanks again for your time reviewing this.
  
Adhemerval Zanella Netto May 27, 2024, 7:18 p.m. UTC | #3
On 27/05/24 15:00, Joe Damato wrote:
> On Mon, May 27, 2024 at 02:00:32PM -0300, Adhemerval Zanella Netto wrote:
>>
>>
>> On 24/05/24 21:38, Joe Damato wrote:
>>> As of Linux kernel 6.9, some ioctls and a parameters structure have been
>>> introduced which allow user programs to control whether a particular
>>> epoll context will busy poll.
>>>
>>> Update the headers to include these for the convenience of user apps.
>>>
>>> Signed-off-by: Joe Damato <jdamato@fastly.com>
>>
>> Look good, I just think this should a newer tests instead of a extra
>> subtest on current tst-epoll.c.
> 
> Thank you very much for your time and energy giving this a review.
> 
> I am happy to move the test to a separate test in a v2 if you prefer
> that. I wrote the test this way because I saw how (for example)
> epoll_pwait2 was tested in tst-epoll.c (with a check that it is
> supported and then the real test).
> 
> If you'd still prefer that I move the ioctl test to a separate file,
> please let me know. In that case, perhaps a future work can be
> moving the pwait2 test to its own file, as well.

Yeah, I think it was an oversight from my part and I think I will probably
sent a patch to split this test for the epoll_pwait2.  I think it is more
informative to user if he knows when and why tests are either failing or
not run due some kernel limitation.

> 
>>> ---
>>>  NEWS                                |  3 ++
>>>  sysdeps/unix/sysv/linux/sys/epoll.h | 13 +++++++
>>>  sysdeps/unix/sysv/linux/tst-epoll.c | 55 +++++++++++++++++++++++++++++
>>>  3 files changed, 71 insertions(+)
>>>
>>> diff --git a/NEWS b/NEWS
>>> index 84efa46df3..20e263f581 100644
>>> --- a/NEWS
>>> +++ b/NEWS
>>> @@ -33,6 +33,9 @@ Major new features:
>>>    more extensive verification tests for AT_SECURE programs and not meant to
>>>    be a security feature.
>>>  
>>> +* On Linux, update epoll header to include epoll ioctl definitions and
>>> +  related structure added in Linux kernel 6.9.
>>> +
>>>  Deprecated and removed features, and other changes affecting compatibility:
>>>  
>>>  * Architectures which use a 32-bit seconds-since-epoch field in struct
>>> diff --git a/sysdeps/unix/sysv/linux/sys/epoll.h b/sysdeps/unix/sysv/linux/sys/epoll.h
>>> index fc8dce45c8..cf04ba55f0 100644
>>> --- a/sysdeps/unix/sysv/linux/sys/epoll.h
>>> +++ b/sysdeps/unix/sysv/linux/sys/epoll.h
>>> @@ -19,6 +19,7 @@
>>>  #define	_SYS_EPOLL_H	1
>>>  
>>>  #include <stdint.h>
>>> +#include <sys/ioctl.h>
>>>  #include <sys/types.h>
>>>  
>>>  #include <bits/types/sigset_t.h>
>>> @@ -87,6 +88,18 @@ struct epoll_event
>>>    epoll_data_t data;	/* User data variable */
>>>  } __EPOLL_PACKED;
>>>  
>>> +struct epoll_params {
>>
>> The open curly bracket should be in the next line per code guideline. 
> 
> Thank you. I can fix this in the v2.
> 
> Related question: is there a script that checks for minor style nits
> like this? Sorry if I missed such a script in the docs somewhere.
> 
> FWIW: the kernel has a script that checks for nits like this which
> is very helpful.
> 
>>> +  uint32_t busy_poll_usecs;
>>> +  uint16_t busy_poll_budget;
>>> +  uint8_t prefer_busy_poll;
>>> +
>>> +  /* pad the struct to a multiple of 64bits */
>>> +  uint8_t __pad;
>>> +};
>>> +
>>> +#define EPOLL_IOC_TYPE 0x8A
>>> +#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
>>> +#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
>>
>> Ok, this follow kernel commit 18e2bf0edf4dd.
> 
> Yes; in the v2 I can mention this kernel commit SHA and link to the
> line in gitweb in the commit message to make it easier to check in
> the future, if you like.
> 
> Please let me know.
> 
>>>  
>>>  __BEGIN_DECLS
>>>  
>>> diff --git a/sysdeps/unix/sysv/linux/tst-epoll.c b/sysdeps/unix/sysv/linux/tst-epoll.c
>>> index 545f506faa..961a63c33d 100644
>>> --- a/sysdeps/unix/sysv/linux/tst-epoll.c
>>> +++ b/sysdeps/unix/sysv/linux/tst-epoll.c
>>> @@ -24,6 +24,8 @@
>>>  #include <support/xunistd.h>
>>>  #include <support/process_state.h>
>>>  #include <stdlib.h>
>>> +#include <string.h>
>>> +#include <sys/ioctl.h>
>>>  #include <sys/epoll.h>
>>>  
>>>  /* The test focus on checking if the timeout argument is correctly handled
>>> @@ -177,6 +179,56 @@ epoll_pwait2_check (int epfd, struct epoll_event *ev, int maxev, int tmo,
>>>    return epoll_pwait2 (epfd, ev, maxev, &(struct timespec) { s, ns }, ss);
>>>  }
>>>  
>>> +static void
>>> +test_epoll_ioctl (void)
>>> +{
>>> +  int efd = epoll_create1 (0);
>>> +  TEST_VERIFY_EXIT (efd != -1);
>>> +
>>> +  struct epoll_params params;
>>> +
>>> +  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
>>> +
>>> +  /* parameters are all 0 by default */
>>> +  TEST_COMPARE (params.busy_poll_usecs, 0);
>>> +  TEST_COMPARE (params.busy_poll_budget, 0);
>>> +  TEST_COMPARE (params.prefer_busy_poll, 0);
>>> +  TEST_COMPARE (params.__pad, 0);
>>
>> I take this field would continue to be zero in future versions.
> 
> The __pad field is checked by the kernel to ensure that it is zero
> when EPIOCSPARAMS is used (otherwise an error is returned).
> 
> It is possible that bits of the __pad field may be used for other
> purposes in the future; I don't have any specific plan right now.
> 
> Since the kernel always checks that __pad == 0 and sets __pad = 0,
> it would potentially be possible to make __pad a bit field of just 1
> bit and use the other bits for a different purpose in the future.
> 
> That said, I don't think that changes anything about this test.
> 
>>> +
>>> +  /* set custom parameters */
>>> +  params.busy_poll_usecs = 40;
>>> +  params.busy_poll_budget = 8;
>>> +  params.prefer_busy_poll = 1;
>>> +  params.__pad = 0;
>>> +
>>> +  TEST_COMPARE (ioctl (efd, EPIOCSPARAMS, &params), 0);
>>> +
>>> +  memset (&params, 0, sizeof (params));
>>> +
>>> +  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
>>> +
>>> +  /* check custom values were retrieved after being set */
>>> +  TEST_COMPARE (params.busy_poll_usecs, 40);
>>> +  TEST_COMPARE (params.busy_poll_budget, 8);
>>> +  TEST_COMPARE (params.prefer_busy_poll, 1);
>>> +  TEST_COMPARE (params.__pad, 0);
>>> +
>>> +  xclose (efd);
>>> +}
>>> +
>>> +static bool
>>> +ioctl_supported (void)
>>> +{
>>> +  int efd = epoll_create1 (0);
>>> +  TEST_VERIFY_EXIT (efd != -1);
>>> +
>>> +  struct epoll_params params;
>>> +  int r = ioctl (efd, EPIOCGPARAMS, &params);
>>> +  xclose (efd);
>>> +
>>> +  return (r == 0);
>>> +}
>>> +
>>>  static int
>>>  do_test (void)
>>>  {
>>> @@ -207,6 +259,9 @@ do_test (void)
>>>    if (pwait2_supported)
>>>      test_epoll_large_timeout (epoll_pwait2_check);
>>>  
>>> +  if (ioctl_supported ())
>>> +    test_epoll_ioctl ();
>>> +
>>>    return 0;
>>>  }
>>>  
>>
>> The test look ok, although I think it should be move to a new test so for
>> the !ioctl_supported it can return TEST_UNSUPPORTED (and tester knows that
>> some features might not be supported/check on current kernel).
> 
> OK, I can do that. As I mentioned above, I was following the pattern
> in place in tst-epoll for epoll_pwait2 but if you prefer a separate
> test for the ioctl, please let me know.
> 
> Thanks again for your time reviewing this.
  

Patch

diff --git a/NEWS b/NEWS
index 84efa46df3..20e263f581 100644
--- a/NEWS
+++ b/NEWS
@@ -33,6 +33,9 @@  Major new features:
   more extensive verification tests for AT_SECURE programs and not meant to
   be a security feature.
 
+* On Linux, update epoll header to include epoll ioctl definitions and
+  related structure added in Linux kernel 6.9.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * Architectures which use a 32-bit seconds-since-epoch field in struct
diff --git a/sysdeps/unix/sysv/linux/sys/epoll.h b/sysdeps/unix/sysv/linux/sys/epoll.h
index fc8dce45c8..cf04ba55f0 100644
--- a/sysdeps/unix/sysv/linux/sys/epoll.h
+++ b/sysdeps/unix/sysv/linux/sys/epoll.h
@@ -19,6 +19,7 @@ 
 #define	_SYS_EPOLL_H	1
 
 #include <stdint.h>
+#include <sys/ioctl.h>
 #include <sys/types.h>
 
 #include <bits/types/sigset_t.h>
@@ -87,6 +88,18 @@  struct epoll_event
   epoll_data_t data;	/* User data variable */
 } __EPOLL_PACKED;
 
+struct epoll_params {
+  uint32_t busy_poll_usecs;
+  uint16_t busy_poll_budget;
+  uint8_t prefer_busy_poll;
+
+  /* pad the struct to a multiple of 64bits */
+  uint8_t __pad;
+};
+
+#define EPOLL_IOC_TYPE 0x8A
+#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
+#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
 
 __BEGIN_DECLS
 
diff --git a/sysdeps/unix/sysv/linux/tst-epoll.c b/sysdeps/unix/sysv/linux/tst-epoll.c
index 545f506faa..961a63c33d 100644
--- a/sysdeps/unix/sysv/linux/tst-epoll.c
+++ b/sysdeps/unix/sysv/linux/tst-epoll.c
@@ -24,6 +24,8 @@ 
 #include <support/xunistd.h>
 #include <support/process_state.h>
 #include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
 #include <sys/epoll.h>
 
 /* The test focus on checking if the timeout argument is correctly handled
@@ -177,6 +179,56 @@  epoll_pwait2_check (int epfd, struct epoll_event *ev, int maxev, int tmo,
   return epoll_pwait2 (epfd, ev, maxev, &(struct timespec) { s, ns }, ss);
 }
 
+static void
+test_epoll_ioctl (void)
+{
+  int efd = epoll_create1 (0);
+  TEST_VERIFY_EXIT (efd != -1);
+
+  struct epoll_params params;
+
+  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
+
+  /* parameters are all 0 by default */
+  TEST_COMPARE (params.busy_poll_usecs, 0);
+  TEST_COMPARE (params.busy_poll_budget, 0);
+  TEST_COMPARE (params.prefer_busy_poll, 0);
+  TEST_COMPARE (params.__pad, 0);
+
+  /* set custom parameters */
+  params.busy_poll_usecs = 40;
+  params.busy_poll_budget = 8;
+  params.prefer_busy_poll = 1;
+  params.__pad = 0;
+
+  TEST_COMPARE (ioctl (efd, EPIOCSPARAMS, &params), 0);
+
+  memset (&params, 0, sizeof (params));
+
+  TEST_COMPARE (ioctl (efd, EPIOCGPARAMS, &params), 0);
+
+  /* check custom values were retrieved after being set */
+  TEST_COMPARE (params.busy_poll_usecs, 40);
+  TEST_COMPARE (params.busy_poll_budget, 8);
+  TEST_COMPARE (params.prefer_busy_poll, 1);
+  TEST_COMPARE (params.__pad, 0);
+
+  xclose (efd);
+}
+
+static bool
+ioctl_supported (void)
+{
+  int efd = epoll_create1 (0);
+  TEST_VERIFY_EXIT (efd != -1);
+
+  struct epoll_params params;
+  int r = ioctl (efd, EPIOCGPARAMS, &params);
+  xclose (efd);
+
+  return (r == 0);
+}
+
 static int
 do_test (void)
 {
@@ -207,6 +259,9 @@  do_test (void)
   if (pwait2_supported)
     test_epoll_large_timeout (epoll_pwait2_check);
 
+  if (ioctl_supported ())
+    test_epoll_ioctl ();
+
   return 0;
 }