RFC: avoid cancellable I/O primitives in ld.so

Message ID 20180404014319.7339-1-zackw@panix.com
State Superseded
Headers

Commit Message

Zack Weinberg April 4, 2018, 1:43 a.m. UTC
  Neither the <dlfcn.h> entry points, nor lazy symbol resolution, nor
initial shared library load-up, are cancellation points, so ld.so
should exclusively use I/O primitives that are not cancellable; in
addition to streamlining low-level operations, this means we do not
require a copy of nptl/unwind.c in ld.so.

The bulk of the change is splitting up the files that define the
_nocancel I/O functions, so they don't also define the variants that
*are* cancellation points; after which, the existing logic for picking
out the bits of libc that need to be recompiled as part of ld.so Just
Works.  I did this for all of the _nocancel functions, not just the
ones used by ld.so, for consistency.

fcntl was a little tricky because it's only a cancellation point for
certain opcodes (F_SETLKW(64), which can block), so there's a chunk of
code to share between fcntl and __fcntl_nocancel.  The only nontrivial
definition of FCNTL_ADJUST_CMD needed to move from
sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c to .../sysdep.h so
that both fcntl.c and fcntl_nocancel.c could see it, and I also
changed it from a clever arithmetic expression to a chain of ternaries
to make it more obviously idempotent.

Right now, it appears that Hurd does not implement _nocancel I/O, so
sysdeps/generic/not-cancel.h will forward everything back to the
regular functions.

I attempted to make sure this stays fixed by making libc-cancellation.c
issue an #error if IS_IN(rtld), but I'm not sure that part works.

(Yes, this is still in the chain of yaks needing to be shaved in order
to finish the C99-scanf patches.  Don't ask.)

zw

	* elf/dl-load.c, elf/dl-misc.c, elf/dl-profile.c, elf/rtld.c
	* sysdeps/unix/sysv/linux/dl-sysdep.c
	Include not-cancel.h.  Use __close_nocancel instead of __close,
	__open_nocancel instead of __open, __read_nocancel instead of
	__libc_read, and __write_nocancel instead of __libc_write.
	* csu/check_fds/c (check_one_fd): Use __fcntl_nocancel.
	* sysdeps/posix/fdopendir.c (__fdopendir): Likewise.
	* sysdeps/posix/opendir.c (__alloc_dir): Likewise.

	* sysdeps/unix/sysv/linux/not-cancel.h: Move all of the
	hidden_proto declarations to the end and issue them if either
	IS_IN(libc) or IS_IN(rtld).
	* sysdeps/unix/sysv/linux/Makefile [subdir=io] (sysdep_routines):
	Add close_nocancel, fcntl_nocancel, nanosleep_nocancel,
	open_nocancel, open64_nocancel, openat_nocancel, pause_nocancel,
	read_nocancel, waitpid_nocancel, write_nocancel.

	* sysdeps/unix/sysv/linux/fcntl.c (__libc_fcntl): Call
	__fcntl_nocancel, not fcntl_common.
	(fcntl_common, __fcntl_nocancel): Combine and move to ...
	* sysdeps/unix/sysv/linux/fcntl_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c: Remove file.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h:
	Define FCNTL_ADJUST_CMD here.

	* sysdeps/unix/sysv/linux/close.c: Move __close_nocancel to...
	* sysdeps/unix/sysv/linux/close_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/nanosleep.c: Move __nanosleep_nocancel to...
	* sysdeps/unix/sysv/linux/nanosleep_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/open.c: Move __open_nocancel to...
	* sysdeps/unix/sysv/linux/open_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/open64.c: Move __open64_nocancel to...
	* sysdeps/unix/sysv/linux/open64_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/openat.c: Move __openat_nocancel to...
	* sysdeps/unix/sysv/linux/openat_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/openat64.c: Move __openat64_nocancel to...
	* sysdeps/unix/sysv/linux/openat64_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/pause.c: Move __pause_nocancel to...
	* sysdeps/unix/sysv/linux/pause_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/read.c: Move __read_nocancel to...
	* sysdeps/unix/sysv/linux/read_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/waitpid.c: Move __waitpid_nocancel to...
	* sysdeps/unix/sysv/linux/waitpid_nocancel.c: ...this new file.
	* sysdeps/unix/sysv/linux/write.c: Move __write_nocancel to...
	* sysdeps/unix/sysv/linux/write_nocancel.c: ...this new file.
---
 csu/check_fds.c                                    |  6 ++-
 elf/dl-load.c                                      | 35 ++++++-------
 elf/dl-misc.c                                      |  6 +--
 elf/dl-profile.c                                   | 14 +++---
 elf/rtld.c                                         |  3 +-
 nptl/libc-cancellation.c                           |  3 ++
 sysdeps/posix/fdopendir.c                          |  7 ++-
 sysdeps/posix/opendir.c                            |  7 ++-
 sysdeps/unix/sysv/linux/Makefile                   |  7 ++-
 sysdeps/unix/sysv/linux/close.c                    | 11 ----
 .../powerpc64/fcntl.c => close_nocancel.c}         | 20 +++-----
 sysdeps/unix/sysv/linux/dl-sysdep.c                |  7 +--
 sysdeps/unix/sysv/linux/fcntl.c                    | 38 +-------------
 sysdeps/unix/sysv/linux/fcntl_nocancel.c           | 58 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/nanosleep.c                |  8 ---
 sysdeps/unix/sysv/linux/nanosleep_nocancel.c       | 29 +++++++++++
 sysdeps/unix/sysv/linux/not-cancel.h               | 25 ++++++----
 sysdeps/unix/sysv/linux/open.c                     | 22 --------
 sysdeps/unix/sysv/linux/open64.c                   | 27 +---------
 sysdeps/unix/sysv/linux/open64_nocancel.c          | 53 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/open_nocancel.c            | 46 +++++++++++++++++
 sysdeps/unix/sysv/linux/openat.c                   | 21 --------
 sysdeps/unix/sysv/linux/openat64.c                 | 24 ---------
 sysdeps/unix/sysv/linux/openat64_nocancel.c        | 50 +++++++++++++++++++
 sysdeps/unix/sysv/linux/openat_nocancel.c          | 42 ++++++++++++++++
 sysdeps/unix/sysv/linux/pause.c                    | 12 -----
 sysdeps/unix/sysv/linux/pause_nocancel.c           | 33 ++++++++++++
 sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h |  9 ++++
 sysdeps/unix/sysv/linux/read.c                     | 12 -----
 sysdeps/unix/sysv/linux/read_nocancel.c            | 28 +++++++++++
 sysdeps/unix/sysv/linux/waitpid.c                  | 12 -----
 sysdeps/unix/sysv/linux/waitpid_nocancel.c         | 33 ++++++++++++
 sysdeps/unix/sysv/linux/write.c                    | 12 -----
 sysdeps/unix/sysv/linux/write_nocancel.c           | 28 +++++++++++
 34 files changed, 490 insertions(+), 258 deletions(-)
 rename sysdeps/unix/sysv/linux/{powerpc/powerpc64/fcntl.c => close_nocancel.c} (70%)
 create mode 100644 sysdeps/unix/sysv/linux/fcntl_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/nanosleep_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/open64_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/open_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/openat64_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/openat_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/pause_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/read_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/waitpid_nocancel.c
 create mode 100644 sysdeps/unix/sysv/linux/write_nocancel.c
  

Comments

Adhemerval Zanella April 4, 2018, 2:18 a.m. UTC | #1
On 03/04/2018 22:43, Zack Weinberg wrote:
> Neither the <dlfcn.h> entry points, nor lazy symbol resolution, nor
> initial shared library load-up, are cancellation points, so ld.so
> should exclusively use I/O primitives that are not cancellable; in
> addition to streamlining low-level operations, this means we do not
> require a copy of nptl/unwind.c in ld.so.
> 
> The bulk of the change is splitting up the files that define the
> _nocancel I/O functions, so they don't also define the variants that
> *are* cancellation points; after which, the existing logic for picking
> out the bits of libc that need to be recompiled as part of ld.so Just
> Works.  I did this for all of the _nocancel functions, not just the
> ones used by ld.so, for consistency.
> 

There is no need to call *_cancel primitives in loader, rtld-* objects
will built with both LIBC_CANCEL_ASYNC and LIBC_CANCEL_RESET being dummy
values:

nptl/pthreadP.h:
334 # define LIBC_CANCEL_ASYNC()    0 /* Just a dummy value.  */
335 # define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it.  */
336 # define LIBC_CANCEL_HANDLED()  /* Nothing.  */

For instance, 'io/rtld-close.os' is really what you expect for a
non-cancellable syscall:

$ objdump -d ./io/rtld-close.os
[...]
0000000000000000 <__close>:
   0:   b8 03 00 00 00          mov    $0x3,%eax
   5:   0f 05                   syscall 
   7:   48 3d 00 f0 ff ff       cmp    $0xfffffffffffff000,%rax
   d:   77 09                   ja     18 <__close+0x18>
   f:   f3 c3                   repz retq 
  11:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  18:   f7 d8                   neg    %eax
  1a:   89 05 00 00 00 00       mov    %eax,0x0(%rip)        # 20 <__close+0x20>
  20:   b8 ff ff ff ff          mov    $0xffffffff,%eax
  25:   c3                      retq   

So why do you need to explicit call *_cancel symbols?
  
Zack Weinberg April 4, 2018, 2:35 a.m. UTC | #2
On Tue, Apr 3, 2018 at 10:18 PM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> On 03/04/2018 22:43, Zack Weinberg wrote:
>> Neither the <dlfcn.h> entry points, nor lazy symbol resolution, nor
>> initial shared library load-up, are cancellation points, so ld.so
>> should exclusively use I/O primitives that are not cancellable; in
>> addition to streamlining low-level operations, this means we do not
>> require a copy of nptl/unwind.c in ld.so.
>>
>> The bulk of the change is splitting up the files that define the
>> _nocancel I/O functions, so they don't also define the variants that
>> *are* cancellation points; after which, the existing logic for picking
>> out the bits of libc that need to be recompiled as part of ld.so Just
>> Works.  I did this for all of the _nocancel functions, not just the
>> ones used by ld.so, for consistency.
>>
>
> There is no need to call *_cancel primitives in loader, rtld-* objects
> will built with both LIBC_CANCEL_ASYNC and LIBC_CANCEL_RESET being dummy
> values:
...
> So why do you need to explicit call *_cancel symbols?

The Makefile logic for deciding which libc objects will be recompiled
as part of librtld.a does not know this, so libc-cancellation.c,
unwind.c, and unwind-forcedunwind.c get dragged into ld.so
unnecessarily.  It's nearly 2KB of dead machine code on x86-64 and
it's also interfering with my attempts to minimize the number of
symbols defined in more than one of ld.so, libc.so, and libpthread.so.

If we stick to using explicit _nocancel symbols in the loader, and
they are all defined in their own files, then these unnecessary
objects are not included.

zw
  
Andreas Schwab April 4, 2018, 7:47 a.m. UTC | #3
On Apr 03 2018, Zack Weinberg <zackw@panix.com> wrote:

> The Makefile logic for deciding which libc objects will be recompiled
> as part of librtld.a does not know this, so libc-cancellation.c,
> unwind.c, and unwind-forcedunwind.c get dragged into ld.so
> unnecessarily.

Are they?  I don't see that here, they are just needlessly compiled.

Andreas.
  
Zack Weinberg April 4, 2018, 12:32 p.m. UTC | #4
On Wed, Apr 4, 2018 at 3:47 AM, Andreas Schwab <schwab@suse.de> wrote:
> On Apr 03 2018, Zack Weinberg <zackw@panix.com> wrote:
>
>> The Makefile logic for deciding which libc objects will be recompiled
>> as part of librtld.a does not know this, so libc-cancellation.c,
>> unwind.c, and unwind-forcedunwind.c get dragged into ld.so
>> unnecessarily.
>
> Are they?  I don't see that here, they are just needlessly compiled.

You seem to be right about that.  They are included in rtld-libc.a,
but not in librtld.os (the last partial link stage before we actually
create ld.so).

I still think the patch is worthwhile.  It makes the design goal (no
cancellation within ld.so) evident in the source code, it avoids the
needless compilation of files that aren't going to be used, and
splitting the nocancel functions into their own source files means we
don't need messy #ifdeffage in every single one.

zw
  
Adhemerval Zanella April 5, 2018, 12:32 p.m. UTC | #5
On 03/04/2018 22:43, Zack Weinberg wrote:
> Neither the <dlfcn.h> entry points, nor lazy symbol resolution, nor
> initial shared library load-up, are cancellation points, so ld.so
> should exclusively use I/O primitives that are not cancellable; in
> addition to streamlining low-level operations, this means we do not
> require a copy of nptl/unwind.c in ld.so.
> 
> The bulk of the change is splitting up the files that define the
> _nocancel I/O functions, so they don't also define the variants that
> *are* cancellation points; after which, the existing logic for picking
> out the bits of libc that need to be recompiled as part of ld.so Just
> Works.  I did this for all of the _nocancel functions, not just the
> ones used by ld.so, for consistency.
> 
> fcntl was a little tricky because it's only a cancellation point for
> certain opcodes (F_SETLKW(64), which can block), so there's a chunk of
> code to share between fcntl and __fcntl_nocancel.  The only nontrivial
> definition of FCNTL_ADJUST_CMD needed to move from
> sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c to .../sysdep.h so
> that both fcntl.c and fcntl_nocancel.c could see it, and I also
> changed it from a clever arithmetic expression to a chain of ternaries
> to make it more obviously idempotent.
> 
> Right now, it appears that Hurd does not implement _nocancel I/O, so
> sysdeps/generic/not-cancel.h will forward everything back to the
> regular functions.
> 
> I attempted to make sure this stays fixed by making libc-cancellation.c
> issue an #error if IS_IN(rtld), but I'm not sure that part works.
> 
> (Yes, this is still in the chain of yaks needing to be shaved in order
> to finish the C99-scanf patches.  Don't ask.)

I agree that splitting not-cancel implementation in their own files is a
good refactor for the same reasons (explict stating the desired semantic,
ld will pull only the specific implementation and less preprocessor 
tikering on default implementations).

> 
> zw
> 
> 	* elf/dl-load.c, elf/dl-misc.c, elf/dl-profile.c, elf/rtld.c
> 	* sysdeps/unix/sysv/linux/dl-sysdep.c
> 	Include not-cancel.h.  Use __close_nocancel instead of __close,
> 	__open_nocancel instead of __open, __read_nocancel instead of
> 	__libc_read, and __write_nocancel instead of __libc_write.
> 	* csu/check_fds/c (check_one_fd): Use __fcntl_nocancel.
> 	* sysdeps/posix/fdopendir.c (__fdopendir): Likewise.
> 	* sysdeps/posix/opendir.c (__alloc_dir): Likewise.
> 
> 	* sysdeps/unix/sysv/linux/not-cancel.h: Move all of the
> 	hidden_proto declarations to the end and issue them if either
> 	IS_IN(libc) or IS_IN(rtld).
> 	* sysdeps/unix/sysv/linux/Makefile [subdir=io] (sysdep_routines):
> 	Add close_nocancel, fcntl_nocancel, nanosleep_nocancel,
> 	open_nocancel, open64_nocancel, openat_nocancel, pause_nocancel,
> 	read_nocancel, waitpid_nocancel, write_nocancel.
> 
> 	* sysdeps/unix/sysv/linux/fcntl.c (__libc_fcntl): Call
> 	__fcntl_nocancel, not fcntl_common.
> 	(fcntl_common, __fcntl_nocancel): Combine and move to ...
> 	* sysdeps/unix/sysv/linux/fcntl_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c: Remove file.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h:
> 	Define FCNTL_ADJUST_CMD here.
> 
> 	* sysdeps/unix/sysv/linux/close.c: Move __close_nocancel to...
> 	* sysdeps/unix/sysv/linux/close_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/nanosleep.c: Move __nanosleep_nocancel to...
> 	* sysdeps/unix/sysv/linux/nanosleep_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/open.c: Move __open_nocancel to...
> 	* sysdeps/unix/sysv/linux/open_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/open64.c: Move __open64_nocancel to...
> 	* sysdeps/unix/sysv/linux/open64_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/openat.c: Move __openat_nocancel to...
> 	* sysdeps/unix/sysv/linux/openat_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/openat64.c: Move __openat64_nocancel to...
> 	* sysdeps/unix/sysv/linux/openat64_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/pause.c: Move __pause_nocancel to...
> 	* sysdeps/unix/sysv/linux/pause_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/read.c: Move __read_nocancel to...
> 	* sysdeps/unix/sysv/linux/read_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/waitpid.c: Move __waitpid_nocancel to...
> 	* sysdeps/unix/sysv/linux/waitpid_nocancel.c: ...this new file.
> 	* sysdeps/unix/sysv/linux/write.c: Move __write_nocancel to...
> 	* sysdeps/unix/sysv/linux/write_nocancel.c: ...this new file.
> ---
>  csu/check_fds.c                                    |  6 ++-
>  elf/dl-load.c                                      | 35 ++++++-------
>  elf/dl-misc.c                                      |  6 +--
>  elf/dl-profile.c                                   | 14 +++---
>  elf/rtld.c                                         |  3 +-
>  nptl/libc-cancellation.c                           |  3 ++
>  sysdeps/posix/fdopendir.c                          |  7 ++-
>  sysdeps/posix/opendir.c                            |  7 ++-
>  sysdeps/unix/sysv/linux/Makefile                   |  7 ++-
>  sysdeps/unix/sysv/linux/close.c                    | 11 ----
>  .../powerpc64/fcntl.c => close_nocancel.c}         | 20 +++-----
>  sysdeps/unix/sysv/linux/dl-sysdep.c                |  7 +--
>  sysdeps/unix/sysv/linux/fcntl.c                    | 38 +-------------
>  sysdeps/unix/sysv/linux/fcntl_nocancel.c           | 58 ++++++++++++++++++++++
>  sysdeps/unix/sysv/linux/nanosleep.c                |  8 ---
>  sysdeps/unix/sysv/linux/nanosleep_nocancel.c       | 29 +++++++++++
>  sysdeps/unix/sysv/linux/not-cancel.h               | 25 ++++++----
>  sysdeps/unix/sysv/linux/open.c                     | 22 --------
>  sysdeps/unix/sysv/linux/open64.c                   | 27 +---------
>  sysdeps/unix/sysv/linux/open64_nocancel.c          | 53 ++++++++++++++++++++
>  sysdeps/unix/sysv/linux/open_nocancel.c            | 46 +++++++++++++++++
>  sysdeps/unix/sysv/linux/openat.c                   | 21 --------
>  sysdeps/unix/sysv/linux/openat64.c                 | 24 ---------
>  sysdeps/unix/sysv/linux/openat64_nocancel.c        | 50 +++++++++++++++++++
>  sysdeps/unix/sysv/linux/openat_nocancel.c          | 42 ++++++++++++++++
>  sysdeps/unix/sysv/linux/pause.c                    | 12 -----
>  sysdeps/unix/sysv/linux/pause_nocancel.c           | 33 ++++++++++++
>  sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h |  9 ++++
>  sysdeps/unix/sysv/linux/read.c                     | 12 -----
>  sysdeps/unix/sysv/linux/read_nocancel.c            | 28 +++++++++++
>  sysdeps/unix/sysv/linux/waitpid.c                  | 12 -----
>  sysdeps/unix/sysv/linux/waitpid_nocancel.c         | 33 ++++++++++++
>  sysdeps/unix/sysv/linux/write.c                    | 12 -----
>  sysdeps/unix/sysv/linux/write_nocancel.c           | 28 +++++++++++
>  34 files changed, 490 insertions(+), 258 deletions(-)
>  rename sysdeps/unix/sysv/linux/{powerpc/powerpc64/fcntl.c => close_nocancel.c} (70%)
>  create mode 100644 sysdeps/unix/sysv/linux/fcntl_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/nanosleep_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/open64_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/open_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/openat64_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/openat_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/pause_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/read_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/waitpid_nocancel.c
>  create mode 100644 sysdeps/unix/sysv/linux/write_nocancel.c
> 
> diff --git a/csu/check_fds.c b/csu/check_fds.c
> index 2b181d44ab..108f6d5137 100644
> --- a/csu/check_fds.c
> +++ b/csu/check_fds.c
> @@ -39,8 +39,10 @@
>  static void
>  check_one_fd (int fd, int mode)
>  {
> -  /* Note that fcntl() with this parameter is not a cancellation point.  */
> -  if (__builtin_expect (__libc_fcntl (fd, F_GETFD), 0) == -1
> +  /* fcntl(F_GETFD) is not a cancellation point, but we still use
> +     __fcntl_nocancel so that it is *statically* not a cancellation
> +     point, which matters to the code that constructs ld.so.  */
> +  if (__builtin_expect (__fcntl_nocancel (fd, F_GETFD), 0) == -1
>        && errno == EBADF)
>      {
>        const char *name;

I think we could just omit the comment, the function name is explicit enough. 

> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index a5e3a25462..0f257f51bd 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -44,7 +44,7 @@
>  #include <dl-unmap-segments.h>
>  #include <dl-machine-reject-phdr.h>
>  #include <dl-sysdep-open.h>
> -
> +#include <not-cancel.h>
>  
>  #include <endian.h>
>  #if BYTE_ORDER == BIG_ENDIAN
> @@ -776,7 +776,7 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
>  {
>    /* The file might already be closed.  */
>    if (fd != -1)
> -    (void) __close (fd);
> +    (void) __close_nocancel (fd);
>    if (l != NULL && l->l_origin != (char *) -1l)
>      free ((char *) l->l_origin);
>    free (l);
> @@ -835,7 +835,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>        {
>  	/* The object is already loaded.
>  	   Just bump its reference count and return it.  */
> -	__close (fd);
> +	__close_nocancel (fd);
>  
>  	/* If the name is not in the list of names for this object add
>  	   it.  */
> @@ -863,7 +863,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>  
>        /* No need to bump the refcount of the real object, ld.so will
>  	 never be unloaded.  */
> -      __close (fd);
> +      __close_nocancel (fd);
>  
>        /* Add the map for the mirrored object to the object list.  */
>        _dl_add_to_namespace_list (l, nsid);
> @@ -877,7 +877,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>        /* We are not supposed to load the object unless it is already
>  	 loaded.  So return now.  */
>        free (realname);
> -      __close (fd);
> +      __close_nocancel (fd);
>        return NULL;
>      }
>  
> @@ -896,7 +896,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>        if (_dl_zerofd == -1)
>  	{
>  	  free (realname);
> -	  __close (fd);
> +	  __close_nocancel (fd);
>  	  _dl_signal_error (errno, NULL, NULL,
>  			    N_("cannot open zero fill device"));
>  	}
> @@ -962,7 +962,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>      {
>        phdr = alloca (maplength);
>        __lseek (fd, header->e_phoff, SEEK_SET);
> -      if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
> +      if ((size_t) __read_nocancel (fd, (void *) phdr, maplength) != maplength)
>  	{
>  	  errstring = N_("cannot read file data");
>  	  goto call_lose_errno;
> @@ -1232,7 +1232,7 @@ cannot enable executable stack as shared object requires");
>      l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
>  
>    /* We are done mapping in the file.  We no longer need the descriptor.  */
> -  if (__glibc_unlikely (__close (fd) != 0))
> +  if (__glibc_unlikely (__close_nocancel (fd) != 0))
>      {
>        errstring = N_("cannot close file descriptor");
>        goto call_lose_errno;
> @@ -1447,7 +1447,7 @@ open_verify (const char *name, int fd,
>          {
>            /* An audit library changed what we're supposed to open,
>               so FD no longer matches it.  */
> -          __close (fd);
> +          __close_nocancel (fd);
>            fd = -1;
>          }
>      }
> @@ -1455,7 +1455,7 @@ open_verify (const char *name, int fd,
>  
>    if (fd == -1)
>      /* Open the file.  We always open files read-only.  */
> -    fd = __open (name, O_RDONLY | O_CLOEXEC);
> +    fd = __open_nocancel (name, O_RDONLY | O_CLOEXEC);

I think there is no reason to continue using non-LFS interface on loader, so
change to __open64_nocancel (so eventually we can get rid of non-LFS no cancel
implementations).

>  
>    if (fd != -1)
>      {
> @@ -1473,8 +1473,8 @@ open_verify (const char *name, int fd,
>        /* Read in the header.  */
>        do
>  	{
> -	  ssize_t retlen = __libc_read (fd, fbp->buf + fbp->len,
> -					sizeof (fbp->buf) - fbp->len);
> +	  ssize_t retlen = __read_nocancel (fd, fbp->buf + fbp->len,
> +					    sizeof (fbp->buf) - fbp->len);
>  	  if (retlen <= 0)
>  	    break;
>  	  fbp->len += retlen;
> @@ -1597,7 +1597,8 @@ open_verify (const char *name, int fd,
>  	{
>  	  phdr = alloca (maplength);
>  	  __lseek (fd, ehdr->e_phoff, SEEK_SET);
> -	  if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
> +	  if ((size_t) __read_nocancel (fd, (void *) phdr, maplength)
> +	      != maplength)
>  	    {
>  	    read_error:
>  	      errval = errno;
> @@ -1635,7 +1636,7 @@ open_verify (const char *name, int fd,
>  	      {
>  		abi_note = alloca (size);
>  		__lseek (fd, ph->p_offset, SEEK_SET);
> -		if (__libc_read (fd, (void *) abi_note, size) != size)
> +		if (__read_nocancel (fd, (void *) abi_note, size) != size)
>  		  goto read_error;
>  	      }
>  
> @@ -1664,7 +1665,7 @@ open_verify (const char *name, int fd,
>  		|| (GLRO(dl_osversion) && GLRO(dl_osversion) < osversion))
>  	      {
>  	      close_and_out:
> -		__close (fd);
> +		__close_nocancel (fd);
>  		__set_errno (ENOENT);
>  		fd = -1;
>  	      }
> @@ -1780,7 +1781,7 @@ open_path (const char *name, size_t namelen, int mode,
>  		  /* The shared object cannot be tested for being SUID
>  		     or this bit is not set.  In this case we must not
>  		     use this object.  */
> -		  __close (fd);
> +		  __close_nocancel (fd);
>  		  fd = -1;
>  		  /* We simply ignore the file, signal this by setting
>  		     the error value which would have been set by `open'.  */
> @@ -1801,7 +1802,7 @@ open_path (const char *name, size_t namelen, int mode,
>  	    {
>  	      /* No memory for the name, we certainly won't be able
>  		 to load and link it.  */
> -	      __close (fd);
> +	      __close_nocancel (fd);
>  	      return -1;
>  	    }
>  	}

Ok.

> diff --git a/elf/dl-misc.c b/elf/dl-misc.c
> index b7174994cd..c46281cb0c 100644
> --- a/elf/dl-misc.c
> +++ b/elf/dl-misc.c
> @@ -33,7 +33,7 @@
>  #include <sysdep.h>
>  #include <_itoa.h>
>  #include <dl-writev.h>
> -
> +#include <not-cancel.h>
>  
>  /* Read the whole contents of FILE into new mmap'd space with given
>     protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
> @@ -44,7 +44,7 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
>  {
>    void *result = MAP_FAILED;
>    struct stat64 st;
> -  int fd = __open (file, O_RDONLY | O_CLOEXEC);
> +  int fd = __open_nocancel (file, O_RDONLY | O_CLOEXEC);

Same comment for non-LFS usage.

>    if (fd >= 0)
>      {
>        if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
> @@ -65,7 +65,7 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
>  #endif
>  			     , fd, 0);
>  	}
> -      __close (fd);
> +      __close_nocancel (fd);
>      }
>    return result;
>  }

Ok.

> diff --git a/elf/dl-profile.c b/elf/dl-profile.c
> index 7f15352123..cf9ec2297f 100644
> --- a/elf/dl-profile.c
> +++ b/elf/dl-profile.c
> @@ -35,6 +35,7 @@
>  #include <sys/param.h>
>  #include <sys/stat.h>
>  #include <atomic.h>
> +#include <not-cancel.h>
>  
>  /* The LD_PROFILE feature has to be implemented different to the
>     normal profiling using the gmon/ functions.  The problem is that an
> @@ -324,7 +325,7 @@ _dl_start_profile (void)
>    *cp++ = '/';
>    __stpcpy (__stpcpy (cp, GLRO(dl_profile)), ".profile");
>  
> -  fd = __open (filename, O_RDWR | O_CREAT | O_NOFOLLOW, DEFFILEMODE);
> +  fd = __open_nocancel (filename, O_RDWR | O_CREAT | O_NOFOLLOW, DEFFILEMODE);

Same comment for non-LFS usage.

>    if (fd == -1)
>      {
>        char buf[400];
> @@ -335,7 +336,7 @@ _dl_start_profile (void)
>      print_error:
>        errnum = errno;
>        if (fd != -1)
> -	__close (fd);
> +	__close_nocancel (fd);
>        _dl_error_printf (errstr, filename,
>  			__strerror_r (errnum, buf, sizeof buf));
>        return;
> @@ -364,15 +365,14 @@ _dl_start_profile (void)
>  	  goto print_error;
>  	}
>  
> -      if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size
> -						      & (GLRO(dl_pagesize)
> -							 - 1))))
> +      if (TEMP_FAILURE_RETRY
> +	  (__write_nocancel (fd, buf, (expected_size & (GLRO(dl_pagesize) - 1))))
>  	  < 0)
>  	goto cannot_create;
>      }
>    else if (st.st_size != expected_size)
>      {
> -      __close (fd);
> +      __close_nocancel (fd);
>      wrong_format:
>  
>        if (addr != NULL)
> @@ -392,7 +392,7 @@ _dl_start_profile (void)
>      }
>  
>    /* We don't need the file descriptor anymore.  */
> -  __close (fd);
> +  __close_nocancel (fd);
>  
>    /* Pointer to data after the header.  */
>    hist = (char *) (addr + 1);

Ok.

> diff --git a/elf/rtld.c b/elf/rtld.c
> index f8d9597cdd..bb6fb0fa4c 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -41,6 +41,7 @@
>  #include <tls.h>
>  #include <stap-probe.h>
>  #include <stackinfo.h>
> +#include <not-cancel.h>
>  
>  #include <assert.h>
>  
> @@ -2673,7 +2674,7 @@ process_envvars (enum mode *modep)
>        *--startp = '.';
>        startp = memcpy (startp - name_len, debug_output, name_len);
>  
> -      GLRO(dl_debug_fd) = __open (startp, flags, DEFFILEMODE);
> +      GLRO(dl_debug_fd) = __open_nocancel (startp, flags, DEFFILEMODE);

Same comment for non-LFS usage.

>        if (GLRO(dl_debug_fd) == -1)
>  	/* We use standard output if opening the file failed.  */
>  	GLRO(dl_debug_fd) = STDOUT_FILENO;
> diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
> index aef5b5d321..076c9015b5 100644
> --- a/nptl/libc-cancellation.c
> +++ b/nptl/libc-cancellation.c
> @@ -18,6 +18,9 @@
>  
>  #include "pthreadP.h"
>  
> +#if IS_IN (rtld)
> +# error "Cancellation should not occur within rtld"
> +#endif
>  
>  #define __pthread_enable_asynccancel __libc_enable_asynccancel
>  #define __pthread_disable_asynccancel __libc_disable_asynccancel

Not sure if this check is really required, since cancellation hooks for
enable/disable will be empty definitions for loader.

> diff --git a/sysdeps/posix/fdopendir.c b/sysdeps/posix/fdopendir.c
> index ab4541f7fc..6e235223e5 100644
> --- a/sysdeps/posix/fdopendir.c
> +++ b/sysdeps/posix/fdopendir.c
> @@ -37,8 +37,11 @@ __fdopendir (int fd)
>        return NULL;
>      }
>  
> -  /* Make sure the descriptor allows for reading.  */
> -  int flags = __fcntl (fd, F_GETFL);
> +  /* Make sure the descriptor allows for reading.  fcntl(F_GETFL) is
> +     not a cancellation point, but we still use __fcntl_nocancel so
> +     that it is *statically* not a cancellation point, which matters
> +     to the code constructing ld.so.  */
> +  int flags = __fcntl_nocancel (fd, F_GETFL);
>    if (__glibc_unlikely (flags == -1))
>      return NULL;
>    if (__glibc_unlikely ((flags & O_ACCMODE) == O_WRONLY))

Ok (although I think the symbols name is explicit enough to define the
expected semantic).

> diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
> index dea23b2ff5..bc6a9c94a1 100644
> --- a/sysdeps/posix/opendir.c
> +++ b/sysdeps/posix/opendir.c
> @@ -97,9 +97,12 @@ DIR *
>  __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
>  {
>    /* We have to set the close-on-exit flag if the user provided the
> -     file descriptor.  */
> +     file descriptor.  fcntl(F_SETFD) is not a cancellation point,
> +     but we still use __fcntl_nocancel so that it is *statically*
> +     not a cancellation point, which matters to the code that
> +     constructs ld.so.  */
>    if (!close_fd
> -      && __builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
> +      && __builtin_expect (__fcntl_nocancel (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
>  	goto lose;
>  
>    const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64)

Use __glibc_likely.

> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index 8f19e0efc3..5f99a1c54c 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -167,7 +167,12 @@ endif
>  
>  ifeq ($(subdir),io)
>  sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
> -		   sync_file_range fallocate fallocate64
> +		   sync_file_range fallocate fallocate64 \
> +		   close_nocancel fcntl_nocancel nanosleep_nocancel \
> +		   open_nocancel open64_nocancel \
> +		   openat_nocancel openat64_nocancel \
> +		   pause_nocancel read_nocancel waitpid_nocancel write_nocancel
> +
>  sysdep_headers += bits/fcntl-linux.h
>  
>  tests += tst-fallocate tst-fallocate64

Ok.

> diff --git a/sysdeps/unix/sysv/linux/close.c b/sysdeps/unix/sysv/linux/close.c
> index c832d27a0f..fa0938bd89 100644
> --- a/sysdeps/unix/sysv/linux/close.c
> +++ b/sysdeps/unix/sysv/linux/close.c
> @@ -29,14 +29,3 @@ __close (int fd)
>  libc_hidden_def (__close)
>  strong_alias (__close, __libc_close)
>  weak_alias (__close, close)
> -
> -# if !IS_IN (rtld)
> -int
> -__close_nocancel (int fd)
> -{
> -  return INLINE_SYSCALL_CALL (close, fd);
> -}
> -#else
> -strong_alias (__libc_close, __close_nocancel)
> -#endif
> -libc_hidden_def (__close_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c b/sysdeps/unix/sysv/linux/close_nocancel.c
> similarity index 70%
> rename from sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c
> rename to sysdeps/unix/sysv/linux/close_nocancel.c
> index 48198c1150..21f8b6203c 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c
> +++ b/sysdeps/unix/sysv/linux/close_nocancel.c
> @@ -1,4 +1,5 @@
> -/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
> +/* Linux close syscall implementation.

I think it is worth to add it has no cancellable semantic.

> +   Copyright (C) 2017-2018 Free Software Foundation, Inc.
>     This file is part of the GNU C Library.
>  
>     The GNU C Library is free software; you can redistribute it and/or
> @@ -16,17 +17,12 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <unistd.h>
> -#include <fcntl.h>
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
>  
> -static inline int
> -fcntl_adjust_cmd (int cmd)
> +int
> +__close_nocancel (int fd)
>  {
> -  if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
> -    cmd -= F_GETLK64 - F_GETLK;
> -  return cmd;
> +  return INLINE_SYSCALL_CALL (close, fd);
>  }
> -
> -#define FCNTL_ADJUST_CMD(__cmd) \
> -  fcntl_adjust_cmd (__cmd)
> -
> -#include <sysdeps/unix/sysv/linux/fcntl.c>
> +libc_hidden_def (__close_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
> index b4cda3486a..40eae0d87f 100644
> --- a/sysdeps/unix/sysv/linux/dl-sysdep.c
> +++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
> @@ -25,6 +25,7 @@
>  #include <sys/param.h>
>  #include <sys/utsname.h>
>  #include <ldsodefs.h>
> +#include <not-cancel.h>
>  
>  #ifdef SHARED
>  # define DL_SYSDEP_INIT frob_brk ()
> @@ -87,11 +88,11 @@ _dl_discover_osversion (void)
>    if (__uname (&uts))
>      {
>        /* This was not successful.  Now try reading the /proc filesystem.  */
> -      int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY);
> +      int fd = __open_nocancel ("/proc/sys/kernel/osrelease", O_RDONLY);

Same comment for non-LFS usage.

>        if (fd < 0)
>  	return -1;
> -      ssize_t reslen = __read (fd, bufmem, sizeof (bufmem));
> -      __close (fd);
> +      ssize_t reslen = __read_nocancel (fd, bufmem, sizeof (bufmem));
> +      __close_nocancel (fd);
>        if (reslen <= 0)
>  	/* This also didn't work.  We give up since we cannot
>  	   make sure the library can actually work.  */
> diff --git a/sysdeps/unix/sysv/linux/fcntl.c b/sysdeps/unix/sysv/linux/fcntl.c
> index a3cb2aea10..b5bd045a1b 100644
> --- a/sysdeps/unix/sysv/linux/fcntl.c
> +++ b/sysdeps/unix/sysv/linux/fcntl.c
> @@ -29,24 +29,6 @@
>  # define FCNTL_ADJUST_CMD(__cmd) __cmd
>  #endif
>  
> -static int
> -fcntl_common (int fd, int cmd, void *arg)
> -{
> -  if (cmd == F_GETOWN)
> -    {
> -      INTERNAL_SYSCALL_DECL (err);
> -      struct f_owner_ex fex;
> -      int res = INTERNAL_SYSCALL_CALL (fcntl64, err, fd, F_GETOWN_EX, &fex);
> -      if (!INTERNAL_SYSCALL_ERROR_P (res, err))
> -	return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;
> -
> -      return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (res,
> -								    err));
> -    }
> -
> -  return INLINE_SYSCALL_CALL (fcntl64, fd, cmd, (void *) arg);
> -}
> -
>  int
>  __libc_fcntl (int fd, int cmd, ...)
>  {
> @@ -62,28 +44,10 @@ __libc_fcntl (int fd, int cmd, ...)
>    if (cmd == F_SETLKW || cmd == F_SETLKW64)
>      return SYSCALL_CANCEL (fcntl64, fd, cmd, (void *) arg);
>  
> -  return fcntl_common (fd, cmd, arg);
> +  return __fcntl_nocancel (fd, cmd, arg);
>  }
>  libc_hidden_def (__libc_fcntl)
>  
> -#if !IS_IN (rtld)
> -int
> -__fcntl_nocancel (int fd, int cmd, ...)
> -{
> -  va_list ap;
> -  void *arg;
> -
> -  va_start (ap, cmd);
> -  arg = va_arg (ap, void *);
> -  va_end (ap);
> -
> -  return fcntl_common (fd, cmd, arg);
> -}
> -#else
> -strong_alias (__libc_fcntl, __fcntl_nocancel)
> -#endif
> -libc_hidden_def (__fcntl_nocancel)
> -
>  weak_alias (__libc_fcntl, __fcntl)
>  libc_hidden_weak (__fcntl)
>  weak_alias (__libc_fcntl, fcntl)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/fcntl_nocancel.c b/sysdeps/unix/sysv/linux/fcntl_nocancel.c
> new file mode 100644
> index 0000000000..49f00cb79f
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/fcntl_nocancel.c
> @@ -0,0 +1,58 @@
> +/* Copyright (C) 2000-2018 Free Software Foundation, Inc.

Copyright date and one line comment.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <fcntl.h>
> +#include <stdarg.h>
> +#include <errno.h>
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +#ifndef __NR_fcntl64
> +# define __NR_fcntl64 __NR_fcntl
> +#endif
> +
> +#ifndef FCNTL_ADJUST_CMD
> +# define FCNTL_ADJUST_CMD(__cmd) __cmd
> +#endif
> +
> +int
> +__fcntl_nocancel (int fd, int cmd, ...)
> +{
> +  va_list ap;
> +  void *arg;
> +
> +  va_start (ap, cmd);
> +  arg = va_arg (ap, void *);
> +  va_end (ap);
> +
> +  cmd = FCNTL_ADJUST_CMD (cmd);
> +
> +  if (cmd == F_GETOWN)
> +    {
> +      INTERNAL_SYSCALL_DECL (err);
> +      struct f_owner_ex fex;
> +      int res = INTERNAL_SYSCALL_CALL (fcntl64, err, fd, F_GETOWN_EX, &fex);
> +      if (!INTERNAL_SYSCALL_ERROR_P (res, err))
> +	return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;
> +
> +      return INLINE_SYSCALL_ERROR_RETURN_VALUE
> +        (INTERNAL_SYSCALL_ERRNO (res, err));
> +    }
> +
> +  return INLINE_SYSCALL_CALL (fcntl64, fd, cmd, (void *) arg);
> +}
> +hidden_def (__fcntl_nocancel)
> diff --git a/sysdeps/unix/sysv/linux/nanosleep.c b/sysdeps/unix/sysv/linux/nanosleep.c
> index 8945837407..3cc13a87f9 100644
> --- a/sysdeps/unix/sysv/linux/nanosleep.c
> +++ b/sysdeps/unix/sysv/linux/nanosleep.c
> @@ -29,11 +29,3 @@ __nanosleep (const struct timespec *requested_time,
>  }
>  hidden_def (__nanosleep)
>  weak_alias (__nanosleep, nanosleep)
> -
> -int
> -__nanosleep_nocancel (const struct timespec *requested_time,
> -		      struct timespec *remaining)
> -{
> -  return INLINE_SYSCALL_CALL (nanosleep, requested_time, remaining);
> -}
> -hidden_def (__nanosleep_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/nanosleep_nocancel.c b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
> new file mode 100644
> index 0000000000..1d8bb551b8
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
> @@ -0,0 +1,29 @@
> +/* Linux high resolution nanosleep implementation.

I think it is worth to add it has no cancellable semantic.

> +   Copyright (C) 2017-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <time.h>
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +int
> +__nanosleep_nocancel (const struct timespec *requested_time,
> +		      struct timespec *remaining)
> +{
> +  return INLINE_SYSCALL_CALL (nanosleep, requested_time, remaining);
> +}
> +hidden_def (__nanosleep_nocancel)
> diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h
> index e6cdd144c2..0b5c955989 100644
> --- a/sysdeps/unix/sysv/linux/not-cancel.h
> +++ b/sysdeps/unix/sysv/linux/not-cancel.h
> @@ -30,31 +30,24 @@
>  
>  /* Non cancellable open syscall.  */
>  __typeof (open) __open_nocancel;
> -libc_hidden_proto (__open_nocancel)
>  
>  /* Non cancellable open syscall (LFS version).  */
>  __typeof (open64) __open64_nocancel;
> -libc_hidden_proto (__open64_nocancel)
>  
>  /* Non cancellable openat syscall.  */
>  __typeof (openat) __openat_nocancel;
> -libc_hidden_proto (__openat_nocancel)
>  
>  /* Non cacellable openat syscall (LFS version).  */
>  __typeof (openat64) __openat64_nocancel;
> -libc_hidden_proto (__openat64_nocancel)
>  
>  /* Non cancellable read syscall.  */
>  __typeof (__read) __read_nocancel;
> -libc_hidden_proto (__read_nocancel)
>  
>  /* Uncancelable write.  */
>  __typeof (__write) __write_nocancel;
> -libc_hidden_proto (__write_nocancel)
>  
>  /* Uncancelable close.  */
>  __typeof (__close) __close_nocancel;
> -libc_hidden_proto (__close_nocancel)
>  
>  /* Non cancellable close syscall that does not also set errno in case of
>     failure.  */
> @@ -75,18 +68,28 @@ __writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt)
>  
>  /* Uncancelable waitpid.  */
>  __typeof (waitpid) __waitpid_nocancel;
> -libc_hidden_proto (__waitpid_nocancel)
>  
>  /* Uncancelable pause.  */
>  __typeof (pause) __pause_nocancel;
> -libc_hidden_proto (__pause_nocancel)
>  
>  /* Uncancelable nanosleep.  */
>  __typeof (__nanosleep) __nanosleep_nocancel;
> -hidden_proto (__nanosleep_nocancel)
>  
>  /* Uncancelable fcntl.  */
>  __typeof (__fcntl) __fcntl_nocancel;
> -libc_hidden_proto (__fcntl_nocancel)
> +
> +#if IS_IN (libc) || IS_IN (rtld)
> +hidden_proto (__open_nocancel)
> +hidden_proto (__open64_nocancel)
> +hidden_proto (__openat_nocancel)
> +hidden_proto (__openat64_nocancel)
> +hidden_proto (__read_nocancel)
> +hidden_proto (__write_nocancel)
> +hidden_proto (__close_nocancel)
> +hidden_proto (__waitpid_nocancel)
> +hidden_proto (__pause_nocancel)
> +hidden_proto (__nanosleep_nocancel)
> +hidden_proto (__fcntl_nocancel)
> +#endif
>  
>  #endif /* NOT_CANCEL_H  */

Ok.

> diff --git a/sysdeps/unix/sysv/linux/open.c b/sysdeps/unix/sysv/linux/open.c
> index c189e285c9..6984b272ac 100644
> --- a/sysdeps/unix/sysv/linux/open.c
> +++ b/sysdeps/unix/sysv/linux/open.c
> @@ -22,7 +22,6 @@
>  #include <stdarg.h>
>  
>  #include <sysdep-cancel.h>
> -#include <not-cancel.h>
>  
>  #ifndef __OFF_T_MATCHES_OFF64_T
>  
> @@ -48,25 +47,4 @@ libc_hidden_def (__libc_open)
>  weak_alias (__libc_open, __open)
>  libc_hidden_weak (__open)
>  weak_alias (__libc_open, open)
> -
> -# if !IS_IN (rtld)
> -int
> -__open_nocancel (const char *file, int oflag, ...)
> -{
> -  int mode = 0;
> -
> -  if (__OPEN_NEEDS_MODE (oflag))
> -    {
> -      va_list arg;
> -      va_start (arg, oflag);
> -      mode = va_arg (arg, int);
> -      va_end (arg);
> -    }
> -
> -  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag, mode);
> -}
> -# else
> -strong_alias (__libc_open, __open_nocancel)
> -# endif
> -libc_hidden_def (__open_nocancel)
>  #endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/open64.c b/sysdeps/unix/sysv/linux/open64.c
> index 4af5ee2466..b7dbfa91d6 100644
> --- a/sysdeps/unix/sysv/linux/open64.c
> +++ b/sysdeps/unix/sysv/linux/open64.c
> @@ -21,7 +21,7 @@
>  #include <stdarg.h>
>  
>  #include <sysdep-cancel.h>
> -#include <not-cancel.h>
> +
>  
>  #ifdef __OFF_T_MATCHES_OFF64_T
>  # define EXTRA_OPEN_FLAGS 0
> @@ -52,34 +52,9 @@ strong_alias (__libc_open64, __open64)
>  libc_hidden_weak (__open64)
>  weak_alias (__libc_open64, open64)
>  
> -# if !IS_IN (rtld)
> -int
> -__open64_nocancel (const char *file, int oflag, ...)
> -{
> -  int mode = 0;
> -
> -  if (__OPEN_NEEDS_MODE (oflag))
> -    {
> -      va_list arg;
> -      va_start (arg, oflag);
> -      mode = va_arg (arg, int);
> -      va_end (arg);
> -    }
> -
> -  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag | EXTRA_OPEN_FLAGS,
> -			      mode);
> -}
> -#else
> -strong_alias (__libc_open64, __open64_nocancel)
> -#endif
> -libc_hidden_def (__open64_nocancel)
> -
>  #ifdef __OFF_T_MATCHES_OFF64_T
>  strong_alias (__libc_open64, __libc_open)
>  strong_alias (__libc_open64, __open)
>  libc_hidden_weak (__open)
>  weak_alias (__libc_open64, open)
> -
> -strong_alias (__open64_nocancel, __open_nocancel)
> -libc_hidden_weak (__open_nocancel)
>  #endif

Ok, although it will incur in a slight code increase due __open_nocancel and
__open64_nocancel not being alias anymore for __OFF_T_MATCHES_OFF64_T
architectures (same applies for openat64).

> diff --git a/sysdeps/unix/sysv/linux/open64_nocancel.c b/sysdeps/unix/sysv/linux/open64_nocancel.c
> new file mode 100644
> index 0000000000..ce2229bcf3
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/open64_nocancel.c
> @@ -0,0 +1,53 @@
> +/* Copyright (C) 1991-2018 Free Software Foundation, Inc.

Copyright date and one line comment.

> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <stdarg.h>
> +
> +#include <not-cancel.h>
> +
> +#ifdef __OFF_T_MATCHES_OFF64_T
> +# define EXTRA_OPEN_FLAGS 0
> +#else
> +# define EXTRA_OPEN_FLAGS O_LARGEFILE
> +#endif
> +
> +int
> +__open64_nocancel (const char *file, int oflag, ...)
> +{
> +  int mode = 0;
> +
> +  if (__OPEN_NEEDS_MODE (oflag))
> +    {
> +      va_list arg;
> +      va_start (arg, oflag);
> +      mode = va_arg (arg, int);
> +      va_end (arg);
> +    }
> +
> +  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag | EXTRA_OPEN_FLAGS,
> +			      mode);
> +}
> +
> +hidden_def (__open64_nocancel)
> +
> +#ifdef __OFF_T_MATCHES_OFF64_T
> +strong_alias (__open64_nocancel, __open_nocancel)
> +hidden_def (__open_nocancel)
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/open_nocancel.c b/sysdeps/unix/sysv/linux/open_nocancel.c
> new file mode 100644
> index 0000000000..64dcb0e536
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/open_nocancel.c
> @@ -0,0 +1,46 @@
> +/* Copyright (C) 2017-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.

Copyright date, one line comment, and I think we can omit the 'Contributed by'
now (it quite different than the original generic implementation).

> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <stdarg.h>
> +
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +#ifndef __OFF_T_MATCHES_OFF64_T
> +
> +int
> +__open_nocancel (const char *file, int oflag, ...)
> +{
> +  int mode = 0;
> +
> +  if (__OPEN_NEEDS_MODE (oflag))
> +    {
> +      va_list arg;
> +      va_start (arg, oflag);
> +      mode = va_arg (arg, int);
> +      va_end (arg);
> +    }
> +
> +  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag, mode);
> +}
> +hidden_def (__open_nocancel)
> +
> +#endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c
> index 9601e617db..181cdc6105 100644
> --- a/sysdeps/unix/sysv/linux/openat.c
> +++ b/sysdeps/unix/sysv/linux/openat.c
> @@ -19,7 +19,6 @@
>  #include <stdarg.h>
>  
>  #include <sysdep-cancel.h>
> -#include <not-cancel.h>
>  
>  #ifndef __OFF_T_MATCHES_OFF64_T
>  
> @@ -43,24 +42,4 @@ __libc_openat (int fd, const char *file, int oflag, ...)
>  weak_alias (__libc_openat, __openat)
>  libc_hidden_weak (__openat)
>  weak_alias (__libc_openat, openat)
> -
> -# if !IS_IN (rtld)
> -int
> -__openat_nocancel (int fd, const char *file, int oflag, ...)
> -{
> -  mode_t mode = 0;
> -  if (__OPEN_NEEDS_MODE (oflag))
> -    {
> -      va_list arg;
> -      va_start (arg, oflag);
> -      mode = va_arg (arg, mode_t);
> -      va_end (arg);
> -    }
> -
> -  return INLINE_SYSCALL_CALL (openat, fd, file, oflag, mode);
> -}
> -# else
> -strong_alias (__libc_openat, __openat_nocancel)
> -# endif
> -libc_hidden_weak (__openat_nocancel)
>  #endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/openat64.c b/sysdeps/unix/sysv/linux/openat64.c
> index 6f14711df3..818ddc51f0 100644
> --- a/sysdeps/unix/sysv/linux/openat64.c
> +++ b/sysdeps/unix/sysv/linux/openat64.c
> @@ -19,7 +19,6 @@
>  #include <stdarg.h>
>  
>  #include <sysdep-cancel.h>
> -#include <not-cancel.h>
>  
>  #ifdef __OFF_T_MATCHES_OFF64_T
>  # define EXTRA_OPEN_FLAGS 0
> @@ -49,31 +48,8 @@ strong_alias (__libc_openat64, __openat64)
>  libc_hidden_weak (__openat64)
>  weak_alias (__libc_openat64, openat64)
>  
> -#if !IS_IN (rtld)
> -int
> -__openat64_nocancel (int fd, const char *file, int oflag, ...)
> -{
> -  mode_t mode = 0;
> -  if (__OPEN_NEEDS_MODE (oflag))
> -    {
> -      va_list arg;
> -      va_start (arg, oflag);
> -      mode = va_arg (arg, mode_t);
> -      va_end (arg);
> -    }
> -
> -  return INLINE_SYSCALL_CALL (openat, fd, file, oflag | EXTRA_OPEN_FLAGS,
> -			      mode);
> -}
> -#else
> -strong_alias (__libc_openat64, __openat64_nocancel)
> -#endif
> -libc_hidden_def (__openat64_nocancel)
> -
>  #ifdef __OFF_T_MATCHES_OFF64_T
>  strong_alias (__libc_openat64, __openat)
>  libc_hidden_weak (__openat)
>  weak_alias (__libc_openat64, openat)
> -
> -strong_alias (__openat64_nocancel, __openat_nocancel)
>  #endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/openat64_nocancel.c b/sysdeps/unix/sysv/linux/openat64_nocancel.c
> new file mode 100644
> index 0000000000..ce342dfc0d
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/openat64_nocancel.c
> @@ -0,0 +1,50 @@
> +/* Copyright (C) 2007-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.

Copyright date and one line comment.

> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <fcntl.h>
> +#include <stdarg.h>
> +
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +#ifdef __OFF_T_MATCHES_OFF64_T
> +# define EXTRA_OPEN_FLAGS 0
> +#else
> +# define EXTRA_OPEN_FLAGS O_LARGEFILE
> +#endif
> +
> +int
> +__openat64_nocancel (int fd, const char *file, int oflag, ...)
> +{
> +  mode_t mode = 0;
> +  if (__OPEN_NEEDS_MODE (oflag))
> +    {
> +      va_list arg;
> +      va_start (arg, oflag);
> +      mode = va_arg (arg, mode_t);
> +      va_end (arg);
> +    }
> +
> +  return INLINE_SYSCALL_CALL (openat, fd, file, oflag | EXTRA_OPEN_FLAGS,
> +			      mode);
> +}
> +hidden_def (__openat64_nocancel)
> +
> +#ifdef __OFF_T_MATCHES_OFF64_T
> +strong_alias (__openat64_nocancel, __openat_nocancel)
> +hidden_def (__openat_nocancel)
> +#endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/openat_nocancel.c b/sysdeps/unix/sysv/linux/openat_nocancel.c
> new file mode 100644
> index 0000000000..0cfc94565c
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/openat_nocancel.c
> @@ -0,0 +1,42 @@
> +/* Copyright (C) 2005-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.

Copyright date and one line comment.

> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <fcntl.h>
> +#include <stdarg.h>
> +
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +#ifndef __OFF_T_MATCHES_OFF64_T
> +
> +int
> +__openat_nocancel (int fd, const char *file, int oflag, ...)
> +{
> +  mode_t mode = 0;
> +  if (__OPEN_NEEDS_MODE (oflag))
> +    {
> +      va_list arg;
> +      va_start (arg, oflag);
> +      mode = va_arg (arg, mode_t);
> +      va_end (arg);
> +    }
> +
> +  return INLINE_SYSCALL_CALL (openat, fd, file, oflag, mode);
> +}
> +hidden_def (__openat_nocancel)
> +
> +#endif

Ok.

> diff --git a/sysdeps/unix/sysv/linux/pause.c b/sysdeps/unix/sysv/linux/pause.c
> index 7c8d9f4861..7b90365b98 100644
> --- a/sysdeps/unix/sysv/linux/pause.c
> +++ b/sysdeps/unix/sysv/linux/pause.c
> @@ -19,7 +19,6 @@
>  #include <signal.h>
>  #include <unistd.h>
>  #include <sysdep-cancel.h>
> -#include <not-cancel.h>
>  
>  /* Suspend the process until a signal arrives.
>     This always returns -1 and sets errno to EINTR.  */
> @@ -33,14 +32,3 @@ __libc_pause (void)
>  #endif
>  }
>  weak_alias (__libc_pause, pause)
> -
> -int
> -__pause_nocancel (void)
> -{
> -#ifdef __NR_pause
> -  return INLINE_SYSCALL_CALL (pause);
> -#else
> -  return INLINE_SYSCALL_CALL (ppoll, NULL, 0, NULL, NULL);
> -#endif
> -}
> -libc_hidden_def (__pause_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/pause_nocancel.c b/sysdeps/unix/sysv/linux/pause_nocancel.c
> new file mode 100644
> index 0000000000..58e0445679
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/pause_nocancel.c
> @@ -0,0 +1,33 @@
> +/* Linux pause syscall implementation.

I think it is worth to add it has no cancellable semantic.

> +   Copyright (C) 2017-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library.  If not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <signal.h>
> +#include <unistd.h>
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +int
> +__pause_nocancel (void)
> +{
> +#ifdef __NR_pause
> +  return INLINE_SYSCALL_CALL (pause);
> +#else
> +  return INLINE_SYSCALL_CALL (ppoll, NULL, 0, NULL, NULL);
> +#endif
> +}
> +hidden_def (__pause_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
> index 0fc179a9a1..ba500e5f84 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
> @@ -236,4 +236,13 @@
>  # endif
>  #endif
>  
> +/* In the PowerPC64 ABI, the unadorned F_GETLK* opcodes should be used
> +   even by largefile64 code.  */
> +#define FCNTL_ADJUST_CMD(__cmd)			\
> +  ({ int cmd_ = (__cmd);			\
> +     cmd_ == F_GETLK64 ? F_GETLK :		\
> +       cmd_ == F_SETLK64 ? F_SETLK :		\
> +       cmd_ == F_SETLKW64 ? F_SETLKW : cmd_ })
> +
> +

I am getting a:

error: expected ‘;’ before ‘}’ token
        cmd_ == F_SETLKW64 ? F_SETLKW : cmd_ })

with this snippet and I am not sure it is worth to change this code on this patch.
Also, I think a better option would to place it on kernel-features.h (since it
usually the place to define architecture kernel abi idiossiacrassies).

>  #endif /* linux/powerpc/powerpc64/sysdep.h */
> diff --git a/sysdeps/unix/sysv/linux/read.c b/sysdeps/unix/sysv/linux/read.c
> index 33ce38aaba..26d0bed404 100644
> --- a/sysdeps/unix/sysv/linux/read.c
> +++ b/sysdeps/unix/sysv/linux/read.c
> @@ -18,7 +18,6 @@
>  
>  #include <unistd.h>
>  #include <sysdep-cancel.h>
> -#include <not-cancel.h>
>  
>  /* Read NBYTES into BUF from FD.  Return the number read or -1.  */
>  ssize_t
> @@ -32,14 +31,3 @@ libc_hidden_def (__read)
>  weak_alias (__libc_read, __read)
>  libc_hidden_def (read)
>  weak_alias (__libc_read, read)
> -
> -#if !IS_IN (rtld)
> -ssize_t
> -__read_nocancel (int fd, void *buf, size_t nbytes)
> -{
> -  return INLINE_SYSCALL_CALL (read, fd, buf, nbytes);
> -}
> -#else
> -strong_alias (__libc_read, __read_nocancel)
> -#endif
> -libc_hidden_def (__read_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/read_nocancel.c b/sysdeps/unix/sysv/linux/read_nocancel.c
> new file mode 100644
> index 0000000000..fe3a716639
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/read_nocancel.c
> @@ -0,0 +1,28 @@
> +/* Linux read syscall implementation.

I think it is worth to add it has no cancellable semantic.

> +   Copyright (C) 2017-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <unistd.h>
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +ssize_t
> +__read_nocancel (int fd, void *buf, size_t nbytes)
> +{
> +  return INLINE_SYSCALL_CALL (read, fd, buf, nbytes);
> +}
> +hidden_def (__read_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/waitpid.c b/sysdeps/unix/sysv/linux/waitpid.c
> index d1d30fd431..a05d908c7b 100644
> --- a/sysdeps/unix/sysv/linux/waitpid.c
> +++ b/sysdeps/unix/sysv/linux/waitpid.c
> @@ -19,7 +19,6 @@
>  #include <sysdep-cancel.h>
>  #include <stdlib.h>
>  #include <sys/wait.h>
> -#include <not-cancel.h>
>  
>  __pid_t
>  __waitpid (__pid_t pid, int *stat_loc, int options)
> @@ -32,14 +31,3 @@ __waitpid (__pid_t pid, int *stat_loc, int options)
>  }
>  libc_hidden_def (__waitpid)
>  weak_alias (__waitpid, waitpid)
> -
> -__pid_t
> -__waitpid_nocancel (__pid_t pid, int *stat_loc, int options)
> -{
> -#ifdef __NR_waitpid
> -  return INLINE_SYSCALL_CALL (waitpid, pid, stat_loc, options);
> -#else
> -  return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, NULL);
> -#endif
> -}
> -libc_hidden_def (__waitpid_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/waitpid_nocancel.c b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
> new file mode 100644
> index 0000000000..f8f3231f32
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
> @@ -0,0 +1,33 @@
> +/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.

Copyright date and one line comment.

> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <sysdep-cancel.h>
> +#include <stdlib.h>
> +#include <sys/wait.h>
> +#include <not-cancel.h>
> +
> +__pid_t
> +__waitpid_nocancel (__pid_t pid, int *stat_loc, int options)
> +{
> +#ifdef __NR_waitpid
> +  return INLINE_SYSCALL_CALL (waitpid, pid, stat_loc, options);
> +#else
> +  return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, NULL);
> +#endif
> +}
> +libc_hidden_def (__waitpid_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/write.c b/sysdeps/unix/sysv/linux/write.c
> index c96dc6f397..558639d471 100644
> --- a/sysdeps/unix/sysv/linux/write.c
> +++ b/sysdeps/unix/sysv/linux/write.c
> @@ -18,7 +18,6 @@
>  
>  #include <unistd.h>
>  #include <sysdep-cancel.h>
> -#include <not-cancel.h>
>  
>  /* Write NBYTES of BUF to FD.  Return the number written, or -1.  */
>  ssize_t
> @@ -32,14 +31,3 @@ weak_alias (__libc_write, __write)
>  libc_hidden_weak (__write)
>  weak_alias (__libc_write, write)
>  libc_hidden_weak (write)
> -
> -#if !IS_IN (rtld)
> -ssize_t
> -__write_nocancel (int fd, const void *buf, size_t nbytes)
> -{
> -  return INLINE_SYSCALL_CALL (write, fd, buf, nbytes);
> -}
> -#else
> -strong_alias (__libc_write, __write_nocancel)
> -#endif
> -libc_hidden_def (__write_nocancel)

Ok.

> diff --git a/sysdeps/unix/sysv/linux/write_nocancel.c b/sysdeps/unix/sysv/linux/write_nocancel.c
> new file mode 100644
> index 0000000000..696f40beec
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/write_nocancel.c
> @@ -0,0 +1,28 @@
> +/* Linux write syscall implementation.

I think it is worth to add it has no cancellable semantic.

> +   Copyright (C) 2017-2018 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <unistd.h>
> +#include <sysdep-cancel.h>
> +#include <not-cancel.h>
> +
> +ssize_t
> +__write_nocancel (int fd, const void *buf, size_t nbytes)
> +{
> +  return INLINE_SYSCALL_CALL (write, fd, buf, nbytes);
> +}
> +hidden_def (__write_nocancel)
> 

Ok.
  
Zack Weinberg April 14, 2018, 2:46 p.m. UTC | #6
On Thu, Apr 5, 2018 at 8:32 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:

Thanks for reviewing.  I believe I have addressed all of your
comments, and build-many-glibcs testing found a few more problems
which I have also fixed; revised patch to follow.

>> +  /* fcntl(F_GETFD) is not a cancellation point, but we still use
>> +     __fcntl_nocancel so that it is *statically* not a cancellation
>> +     point, which matters to the code that constructs ld.so.  */
>> +  if (__builtin_expect (__fcntl_nocancel (fd, F_GETFD), 0) == -1
>>        && errno == EBADF)
>>      {
>>        const char *name;
>
> I think we could just omit the comment, the function name is explicit enough.

I dropped the comment (here and elsewhere).

>> -    fd = __open (name, O_RDONLY | O_CLOEXEC);
>> +    fd = __open_nocancel (name, O_RDONLY | O_CLOEXEC);
>
> I think there is no reason to continue using non-LFS interface on loader, so
> change to __open64_nocancel (so eventually we can get rid of non-LFS no cancel
> implementations).

Done (here and elsewhere).

>> +#if IS_IN (rtld)
>> +# error "Cancellation should not occur within rtld"
>> +#endif
>
> Not sure if this check is really required, since cancellation hooks for
> enable/disable will be empty definitions for loader.

I dropped this.

>> -      && __builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
>> +      && __builtin_expect (__fcntl_nocancel (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
>
> Use __glibc_likely.

Done.

>> -/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
>> +/* Linux close syscall implementation.
>
> I think it is worth to add it has no cancellable semantic.

Done (here and elsewhere).  Also I added one-line header comments to
all the files that didn't have them, corrected the copyright dates,
and removed stale 'Contributed by' lines.

> Ok, although it will incur in a slight code increase due __open_nocancel and
> __open64_nocancel not being alias anymore for __OFF_T_MATCHES_OFF64_T
> architectures (same applies for openat64).

No, they are still aliases in that case.

>> +/* In the PowerPC64 ABI, the unadorned F_GETLK* opcodes should be used
>> +   even by largefile64 code.  */
>> +#define FCNTL_ADJUST_CMD(__cmd)                      \
>> +  ({ int cmd_ = (__cmd);                     \
>> +     cmd_ == F_GETLK64 ? F_GETLK :           \
>> +       cmd_ == F_SETLK64 ? F_SETLK :         \
>> +       cmd_ == F_SETLKW64 ? F_SETLKW : cmd_ })
>> +
>> +
>
> I am getting a:
>
> error: expected ‘;’ before ‘}’ token
>         cmd_ == F_SETLKW64 ? F_SETLKW : cmd_ })
>
> with this snippet

Fixed.

> and I am not sure it is worth to change this code on this patch.

I think this is an appropriate change because, with this patch,
FCNTL_ADJUST_CMD is called twice for ordinary fcntl (because fcntl now
calls __fcntl_nocancel, and both of them need to apply
FCNTL_ADJUST_CMD).  So it is important to make it *obviously* an
idempotent operation.  The old code was idempotent but not obviously so.

> Also, I think a better option would to place it on kernel-features.h
> (since it usually the place to define architecture kernel abi
> idiossiacrassies).

Done.

zw
  

Patch

diff --git a/csu/check_fds.c b/csu/check_fds.c
index 2b181d44ab..108f6d5137 100644
--- a/csu/check_fds.c
+++ b/csu/check_fds.c
@@ -39,8 +39,10 @@ 
 static void
 check_one_fd (int fd, int mode)
 {
-  /* Note that fcntl() with this parameter is not a cancellation point.  */
-  if (__builtin_expect (__libc_fcntl (fd, F_GETFD), 0) == -1
+  /* fcntl(F_GETFD) is not a cancellation point, but we still use
+     __fcntl_nocancel so that it is *statically* not a cancellation
+     point, which matters to the code that constructs ld.so.  */
+  if (__builtin_expect (__fcntl_nocancel (fd, F_GETFD), 0) == -1
       && errno == EBADF)
     {
       const char *name;
diff --git a/elf/dl-load.c b/elf/dl-load.c
index a5e3a25462..0f257f51bd 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -44,7 +44,7 @@ 
 #include <dl-unmap-segments.h>
 #include <dl-machine-reject-phdr.h>
 #include <dl-sysdep-open.h>
-
+#include <not-cancel.h>
 
 #include <endian.h>
 #if BYTE_ORDER == BIG_ENDIAN
@@ -776,7 +776,7 @@  lose (int code, int fd, const char *name, char *realname, struct link_map *l,
 {
   /* The file might already be closed.  */
   if (fd != -1)
-    (void) __close (fd);
+    (void) __close_nocancel (fd);
   if (l != NULL && l->l_origin != (char *) -1l)
     free ((char *) l->l_origin);
   free (l);
@@ -835,7 +835,7 @@  _dl_map_object_from_fd (const char *name, const char *origname, int fd,
       {
 	/* The object is already loaded.
 	   Just bump its reference count and return it.  */
-	__close (fd);
+	__close_nocancel (fd);
 
 	/* If the name is not in the list of names for this object add
 	   it.  */
@@ -863,7 +863,7 @@  _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 
       /* No need to bump the refcount of the real object, ld.so will
 	 never be unloaded.  */
-      __close (fd);
+      __close_nocancel (fd);
 
       /* Add the map for the mirrored object to the object list.  */
       _dl_add_to_namespace_list (l, nsid);
@@ -877,7 +877,7 @@  _dl_map_object_from_fd (const char *name, const char *origname, int fd,
       /* We are not supposed to load the object unless it is already
 	 loaded.  So return now.  */
       free (realname);
-      __close (fd);
+      __close_nocancel (fd);
       return NULL;
     }
 
@@ -896,7 +896,7 @@  _dl_map_object_from_fd (const char *name, const char *origname, int fd,
       if (_dl_zerofd == -1)
 	{
 	  free (realname);
-	  __close (fd);
+	  __close_nocancel (fd);
 	  _dl_signal_error (errno, NULL, NULL,
 			    N_("cannot open zero fill device"));
 	}
@@ -962,7 +962,7 @@  _dl_map_object_from_fd (const char *name, const char *origname, int fd,
     {
       phdr = alloca (maplength);
       __lseek (fd, header->e_phoff, SEEK_SET);
-      if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
+      if ((size_t) __read_nocancel (fd, (void *) phdr, maplength) != maplength)
 	{
 	  errstring = N_("cannot read file data");
 	  goto call_lose_errno;
@@ -1232,7 +1232,7 @@  cannot enable executable stack as shared object requires");
     l->l_tls_initimage = (char *) l->l_tls_initimage + l->l_addr;
 
   /* We are done mapping in the file.  We no longer need the descriptor.  */
-  if (__glibc_unlikely (__close (fd) != 0))
+  if (__glibc_unlikely (__close_nocancel (fd) != 0))
     {
       errstring = N_("cannot close file descriptor");
       goto call_lose_errno;
@@ -1447,7 +1447,7 @@  open_verify (const char *name, int fd,
         {
           /* An audit library changed what we're supposed to open,
              so FD no longer matches it.  */
-          __close (fd);
+          __close_nocancel (fd);
           fd = -1;
         }
     }
@@ -1455,7 +1455,7 @@  open_verify (const char *name, int fd,
 
   if (fd == -1)
     /* Open the file.  We always open files read-only.  */
-    fd = __open (name, O_RDONLY | O_CLOEXEC);
+    fd = __open_nocancel (name, O_RDONLY | O_CLOEXEC);
 
   if (fd != -1)
     {
@@ -1473,8 +1473,8 @@  open_verify (const char *name, int fd,
       /* Read in the header.  */
       do
 	{
-	  ssize_t retlen = __libc_read (fd, fbp->buf + fbp->len,
-					sizeof (fbp->buf) - fbp->len);
+	  ssize_t retlen = __read_nocancel (fd, fbp->buf + fbp->len,
+					    sizeof (fbp->buf) - fbp->len);
 	  if (retlen <= 0)
 	    break;
 	  fbp->len += retlen;
@@ -1597,7 +1597,8 @@  open_verify (const char *name, int fd,
 	{
 	  phdr = alloca (maplength);
 	  __lseek (fd, ehdr->e_phoff, SEEK_SET);
-	  if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
+	  if ((size_t) __read_nocancel (fd, (void *) phdr, maplength)
+	      != maplength)
 	    {
 	    read_error:
 	      errval = errno;
@@ -1635,7 +1636,7 @@  open_verify (const char *name, int fd,
 	      {
 		abi_note = alloca (size);
 		__lseek (fd, ph->p_offset, SEEK_SET);
-		if (__libc_read (fd, (void *) abi_note, size) != size)
+		if (__read_nocancel (fd, (void *) abi_note, size) != size)
 		  goto read_error;
 	      }
 
@@ -1664,7 +1665,7 @@  open_verify (const char *name, int fd,
 		|| (GLRO(dl_osversion) && GLRO(dl_osversion) < osversion))
 	      {
 	      close_and_out:
-		__close (fd);
+		__close_nocancel (fd);
 		__set_errno (ENOENT);
 		fd = -1;
 	      }
@@ -1780,7 +1781,7 @@  open_path (const char *name, size_t namelen, int mode,
 		  /* The shared object cannot be tested for being SUID
 		     or this bit is not set.  In this case we must not
 		     use this object.  */
-		  __close (fd);
+		  __close_nocancel (fd);
 		  fd = -1;
 		  /* We simply ignore the file, signal this by setting
 		     the error value which would have been set by `open'.  */
@@ -1801,7 +1802,7 @@  open_path (const char *name, size_t namelen, int mode,
 	    {
 	      /* No memory for the name, we certainly won't be able
 		 to load and link it.  */
-	      __close (fd);
+	      __close_nocancel (fd);
 	      return -1;
 	    }
 	}
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index b7174994cd..c46281cb0c 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -33,7 +33,7 @@ 
 #include <sysdep.h>
 #include <_itoa.h>
 #include <dl-writev.h>
-
+#include <not-cancel.h>
 
 /* Read the whole contents of FILE into new mmap'd space with given
    protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
@@ -44,7 +44,7 @@  _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
 {
   void *result = MAP_FAILED;
   struct stat64 st;
-  int fd = __open (file, O_RDONLY | O_CLOEXEC);
+  int fd = __open_nocancel (file, O_RDONLY | O_CLOEXEC);
   if (fd >= 0)
     {
       if (__fxstat64 (_STAT_VER, fd, &st) >= 0)
@@ -65,7 +65,7 @@  _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
 #endif
 			     , fd, 0);
 	}
-      __close (fd);
+      __close_nocancel (fd);
     }
   return result;
 }
diff --git a/elf/dl-profile.c b/elf/dl-profile.c
index 7f15352123..cf9ec2297f 100644
--- a/elf/dl-profile.c
+++ b/elf/dl-profile.c
@@ -35,6 +35,7 @@ 
 #include <sys/param.h>
 #include <sys/stat.h>
 #include <atomic.h>
+#include <not-cancel.h>
 
 /* The LD_PROFILE feature has to be implemented different to the
    normal profiling using the gmon/ functions.  The problem is that an
@@ -324,7 +325,7 @@  _dl_start_profile (void)
   *cp++ = '/';
   __stpcpy (__stpcpy (cp, GLRO(dl_profile)), ".profile");
 
-  fd = __open (filename, O_RDWR | O_CREAT | O_NOFOLLOW, DEFFILEMODE);
+  fd = __open_nocancel (filename, O_RDWR | O_CREAT | O_NOFOLLOW, DEFFILEMODE);
   if (fd == -1)
     {
       char buf[400];
@@ -335,7 +336,7 @@  _dl_start_profile (void)
     print_error:
       errnum = errno;
       if (fd != -1)
-	__close (fd);
+	__close_nocancel (fd);
       _dl_error_printf (errstr, filename,
 			__strerror_r (errnum, buf, sizeof buf));
       return;
@@ -364,15 +365,14 @@  _dl_start_profile (void)
 	  goto print_error;
 	}
 
-      if (TEMP_FAILURE_RETRY (__libc_write (fd, buf, (expected_size
-						      & (GLRO(dl_pagesize)
-							 - 1))))
+      if (TEMP_FAILURE_RETRY
+	  (__write_nocancel (fd, buf, (expected_size & (GLRO(dl_pagesize) - 1))))
 	  < 0)
 	goto cannot_create;
     }
   else if (st.st_size != expected_size)
     {
-      __close (fd);
+      __close_nocancel (fd);
     wrong_format:
 
       if (addr != NULL)
@@ -392,7 +392,7 @@  _dl_start_profile (void)
     }
 
   /* We don't need the file descriptor anymore.  */
-  __close (fd);
+  __close_nocancel (fd);
 
   /* Pointer to data after the header.  */
   hist = (char *) (addr + 1);
diff --git a/elf/rtld.c b/elf/rtld.c
index f8d9597cdd..bb6fb0fa4c 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -41,6 +41,7 @@ 
 #include <tls.h>
 #include <stap-probe.h>
 #include <stackinfo.h>
+#include <not-cancel.h>
 
 #include <assert.h>
 
@@ -2673,7 +2674,7 @@  process_envvars (enum mode *modep)
       *--startp = '.';
       startp = memcpy (startp - name_len, debug_output, name_len);
 
-      GLRO(dl_debug_fd) = __open (startp, flags, DEFFILEMODE);
+      GLRO(dl_debug_fd) = __open_nocancel (startp, flags, DEFFILEMODE);
       if (GLRO(dl_debug_fd) == -1)
 	/* We use standard output if opening the file failed.  */
 	GLRO(dl_debug_fd) = STDOUT_FILENO;
diff --git a/nptl/libc-cancellation.c b/nptl/libc-cancellation.c
index aef5b5d321..076c9015b5 100644
--- a/nptl/libc-cancellation.c
+++ b/nptl/libc-cancellation.c
@@ -18,6 +18,9 @@ 
 
 #include "pthreadP.h"
 
+#if IS_IN (rtld)
+# error "Cancellation should not occur within rtld"
+#endif
 
 #define __pthread_enable_asynccancel __libc_enable_asynccancel
 #define __pthread_disable_asynccancel __libc_disable_asynccancel
diff --git a/sysdeps/posix/fdopendir.c b/sysdeps/posix/fdopendir.c
index ab4541f7fc..6e235223e5 100644
--- a/sysdeps/posix/fdopendir.c
+++ b/sysdeps/posix/fdopendir.c
@@ -37,8 +37,11 @@  __fdopendir (int fd)
       return NULL;
     }
 
-  /* Make sure the descriptor allows for reading.  */
-  int flags = __fcntl (fd, F_GETFL);
+  /* Make sure the descriptor allows for reading.  fcntl(F_GETFL) is
+     not a cancellation point, but we still use __fcntl_nocancel so
+     that it is *statically* not a cancellation point, which matters
+     to the code constructing ld.so.  */
+  int flags = __fcntl_nocancel (fd, F_GETFL);
   if (__glibc_unlikely (flags == -1))
     return NULL;
   if (__glibc_unlikely ((flags & O_ACCMODE) == O_WRONLY))
diff --git a/sysdeps/posix/opendir.c b/sysdeps/posix/opendir.c
index dea23b2ff5..bc6a9c94a1 100644
--- a/sysdeps/posix/opendir.c
+++ b/sysdeps/posix/opendir.c
@@ -97,9 +97,12 @@  DIR *
 __alloc_dir (int fd, bool close_fd, int flags, const struct stat64 *statp)
 {
   /* We have to set the close-on-exit flag if the user provided the
-     file descriptor.  */
+     file descriptor.  fcntl(F_SETFD) is not a cancellation point,
+     but we still use __fcntl_nocancel so that it is *statically*
+     not a cancellation point, which matters to the code that
+     constructs ld.so.  */
   if (!close_fd
-      && __builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
+      && __builtin_expect (__fcntl_nocancel (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
 	goto lose;
 
   const size_t default_allocation = (4 * BUFSIZ < sizeof (struct dirent64)
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index 8f19e0efc3..5f99a1c54c 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -167,7 +167,12 @@  endif
 
 ifeq ($(subdir),io)
 sysdep_routines += xstatconv internal_statvfs internal_statvfs64 \
-		   sync_file_range fallocate fallocate64
+		   sync_file_range fallocate fallocate64 \
+		   close_nocancel fcntl_nocancel nanosleep_nocancel \
+		   open_nocancel open64_nocancel \
+		   openat_nocancel openat64_nocancel \
+		   pause_nocancel read_nocancel waitpid_nocancel write_nocancel
+
 sysdep_headers += bits/fcntl-linux.h
 
 tests += tst-fallocate tst-fallocate64
diff --git a/sysdeps/unix/sysv/linux/close.c b/sysdeps/unix/sysv/linux/close.c
index c832d27a0f..fa0938bd89 100644
--- a/sysdeps/unix/sysv/linux/close.c
+++ b/sysdeps/unix/sysv/linux/close.c
@@ -29,14 +29,3 @@  __close (int fd)
 libc_hidden_def (__close)
 strong_alias (__close, __libc_close)
 weak_alias (__close, close)
-
-# if !IS_IN (rtld)
-int
-__close_nocancel (int fd)
-{
-  return INLINE_SYSCALL_CALL (close, fd);
-}
-#else
-strong_alias (__libc_close, __close_nocancel)
-#endif
-libc_hidden_def (__close_nocancel)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c b/sysdeps/unix/sysv/linux/close_nocancel.c
similarity index 70%
rename from sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c
rename to sysdeps/unix/sysv/linux/close_nocancel.c
index 48198c1150..21f8b6203c 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/fcntl.c
+++ b/sysdeps/unix/sysv/linux/close_nocancel.c
@@ -1,4 +1,5 @@ 
-/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
+/* Linux close syscall implementation.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -16,17 +17,12 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #include <unistd.h>
-#include <fcntl.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
 
-static inline int
-fcntl_adjust_cmd (int cmd)
+int
+__close_nocancel (int fd)
 {
-  if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
-    cmd -= F_GETLK64 - F_GETLK;
-  return cmd;
+  return INLINE_SYSCALL_CALL (close, fd);
 }
-
-#define FCNTL_ADJUST_CMD(__cmd) \
-  fcntl_adjust_cmd (__cmd)
-
-#include <sysdeps/unix/sysv/linux/fcntl.c>
+libc_hidden_def (__close_nocancel)
diff --git a/sysdeps/unix/sysv/linux/dl-sysdep.c b/sysdeps/unix/sysv/linux/dl-sysdep.c
index b4cda3486a..40eae0d87f 100644
--- a/sysdeps/unix/sysv/linux/dl-sysdep.c
+++ b/sysdeps/unix/sysv/linux/dl-sysdep.c
@@ -25,6 +25,7 @@ 
 #include <sys/param.h>
 #include <sys/utsname.h>
 #include <ldsodefs.h>
+#include <not-cancel.h>
 
 #ifdef SHARED
 # define DL_SYSDEP_INIT frob_brk ()
@@ -87,11 +88,11 @@  _dl_discover_osversion (void)
   if (__uname (&uts))
     {
       /* This was not successful.  Now try reading the /proc filesystem.  */
-      int fd = __open ("/proc/sys/kernel/osrelease", O_RDONLY);
+      int fd = __open_nocancel ("/proc/sys/kernel/osrelease", O_RDONLY);
       if (fd < 0)
 	return -1;
-      ssize_t reslen = __read (fd, bufmem, sizeof (bufmem));
-      __close (fd);
+      ssize_t reslen = __read_nocancel (fd, bufmem, sizeof (bufmem));
+      __close_nocancel (fd);
       if (reslen <= 0)
 	/* This also didn't work.  We give up since we cannot
 	   make sure the library can actually work.  */
diff --git a/sysdeps/unix/sysv/linux/fcntl.c b/sysdeps/unix/sysv/linux/fcntl.c
index a3cb2aea10..b5bd045a1b 100644
--- a/sysdeps/unix/sysv/linux/fcntl.c
+++ b/sysdeps/unix/sysv/linux/fcntl.c
@@ -29,24 +29,6 @@ 
 # define FCNTL_ADJUST_CMD(__cmd) __cmd
 #endif
 
-static int
-fcntl_common (int fd, int cmd, void *arg)
-{
-  if (cmd == F_GETOWN)
-    {
-      INTERNAL_SYSCALL_DECL (err);
-      struct f_owner_ex fex;
-      int res = INTERNAL_SYSCALL_CALL (fcntl64, err, fd, F_GETOWN_EX, &fex);
-      if (!INTERNAL_SYSCALL_ERROR_P (res, err))
-	return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;
-
-      return INLINE_SYSCALL_ERROR_RETURN_VALUE (INTERNAL_SYSCALL_ERRNO (res,
-								    err));
-    }
-
-  return INLINE_SYSCALL_CALL (fcntl64, fd, cmd, (void *) arg);
-}
-
 int
 __libc_fcntl (int fd, int cmd, ...)
 {
@@ -62,28 +44,10 @@  __libc_fcntl (int fd, int cmd, ...)
   if (cmd == F_SETLKW || cmd == F_SETLKW64)
     return SYSCALL_CANCEL (fcntl64, fd, cmd, (void *) arg);
 
-  return fcntl_common (fd, cmd, arg);
+  return __fcntl_nocancel (fd, cmd, arg);
 }
 libc_hidden_def (__libc_fcntl)
 
-#if !IS_IN (rtld)
-int
-__fcntl_nocancel (int fd, int cmd, ...)
-{
-  va_list ap;
-  void *arg;
-
-  va_start (ap, cmd);
-  arg = va_arg (ap, void *);
-  va_end (ap);
-
-  return fcntl_common (fd, cmd, arg);
-}
-#else
-strong_alias (__libc_fcntl, __fcntl_nocancel)
-#endif
-libc_hidden_def (__fcntl_nocancel)
-
 weak_alias (__libc_fcntl, __fcntl)
 libc_hidden_weak (__fcntl)
 weak_alias (__libc_fcntl, fcntl)
diff --git a/sysdeps/unix/sysv/linux/fcntl_nocancel.c b/sysdeps/unix/sysv/linux/fcntl_nocancel.c
new file mode 100644
index 0000000000..49f00cb79f
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/fcntl_nocancel.c
@@ -0,0 +1,58 @@ 
+/* Copyright (C) 2000-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <fcntl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+#ifndef __NR_fcntl64
+# define __NR_fcntl64 __NR_fcntl
+#endif
+
+#ifndef FCNTL_ADJUST_CMD
+# define FCNTL_ADJUST_CMD(__cmd) __cmd
+#endif
+
+int
+__fcntl_nocancel (int fd, int cmd, ...)
+{
+  va_list ap;
+  void *arg;
+
+  va_start (ap, cmd);
+  arg = va_arg (ap, void *);
+  va_end (ap);
+
+  cmd = FCNTL_ADJUST_CMD (cmd);
+
+  if (cmd == F_GETOWN)
+    {
+      INTERNAL_SYSCALL_DECL (err);
+      struct f_owner_ex fex;
+      int res = INTERNAL_SYSCALL_CALL (fcntl64, err, fd, F_GETOWN_EX, &fex);
+      if (!INTERNAL_SYSCALL_ERROR_P (res, err))
+	return fex.type == F_OWNER_GID ? -fex.pid : fex.pid;
+
+      return INLINE_SYSCALL_ERROR_RETURN_VALUE
+        (INTERNAL_SYSCALL_ERRNO (res, err));
+    }
+
+  return INLINE_SYSCALL_CALL (fcntl64, fd, cmd, (void *) arg);
+}
+hidden_def (__fcntl_nocancel)
diff --git a/sysdeps/unix/sysv/linux/nanosleep.c b/sysdeps/unix/sysv/linux/nanosleep.c
index 8945837407..3cc13a87f9 100644
--- a/sysdeps/unix/sysv/linux/nanosleep.c
+++ b/sysdeps/unix/sysv/linux/nanosleep.c
@@ -29,11 +29,3 @@  __nanosleep (const struct timespec *requested_time,
 }
 hidden_def (__nanosleep)
 weak_alias (__nanosleep, nanosleep)
-
-int
-__nanosleep_nocancel (const struct timespec *requested_time,
-		      struct timespec *remaining)
-{
-  return INLINE_SYSCALL_CALL (nanosleep, requested_time, remaining);
-}
-hidden_def (__nanosleep_nocancel)
diff --git a/sysdeps/unix/sysv/linux/nanosleep_nocancel.c b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
new file mode 100644
index 0000000000..1d8bb551b8
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/nanosleep_nocancel.c
@@ -0,0 +1,29 @@ 
+/* Linux high resolution nanosleep implementation.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <time.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+int
+__nanosleep_nocancel (const struct timespec *requested_time,
+		      struct timespec *remaining)
+{
+  return INLINE_SYSCALL_CALL (nanosleep, requested_time, remaining);
+}
+hidden_def (__nanosleep_nocancel)
diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h
index e6cdd144c2..0b5c955989 100644
--- a/sysdeps/unix/sysv/linux/not-cancel.h
+++ b/sysdeps/unix/sysv/linux/not-cancel.h
@@ -30,31 +30,24 @@ 
 
 /* Non cancellable open syscall.  */
 __typeof (open) __open_nocancel;
-libc_hidden_proto (__open_nocancel)
 
 /* Non cancellable open syscall (LFS version).  */
 __typeof (open64) __open64_nocancel;
-libc_hidden_proto (__open64_nocancel)
 
 /* Non cancellable openat syscall.  */
 __typeof (openat) __openat_nocancel;
-libc_hidden_proto (__openat_nocancel)
 
 /* Non cacellable openat syscall (LFS version).  */
 __typeof (openat64) __openat64_nocancel;
-libc_hidden_proto (__openat64_nocancel)
 
 /* Non cancellable read syscall.  */
 __typeof (__read) __read_nocancel;
-libc_hidden_proto (__read_nocancel)
 
 /* Uncancelable write.  */
 __typeof (__write) __write_nocancel;
-libc_hidden_proto (__write_nocancel)
 
 /* Uncancelable close.  */
 __typeof (__close) __close_nocancel;
-libc_hidden_proto (__close_nocancel)
 
 /* Non cancellable close syscall that does not also set errno in case of
    failure.  */
@@ -75,18 +68,28 @@  __writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt)
 
 /* Uncancelable waitpid.  */
 __typeof (waitpid) __waitpid_nocancel;
-libc_hidden_proto (__waitpid_nocancel)
 
 /* Uncancelable pause.  */
 __typeof (pause) __pause_nocancel;
-libc_hidden_proto (__pause_nocancel)
 
 /* Uncancelable nanosleep.  */
 __typeof (__nanosleep) __nanosleep_nocancel;
-hidden_proto (__nanosleep_nocancel)
 
 /* Uncancelable fcntl.  */
 __typeof (__fcntl) __fcntl_nocancel;
-libc_hidden_proto (__fcntl_nocancel)
+
+#if IS_IN (libc) || IS_IN (rtld)
+hidden_proto (__open_nocancel)
+hidden_proto (__open64_nocancel)
+hidden_proto (__openat_nocancel)
+hidden_proto (__openat64_nocancel)
+hidden_proto (__read_nocancel)
+hidden_proto (__write_nocancel)
+hidden_proto (__close_nocancel)
+hidden_proto (__waitpid_nocancel)
+hidden_proto (__pause_nocancel)
+hidden_proto (__nanosleep_nocancel)
+hidden_proto (__fcntl_nocancel)
+#endif
 
 #endif /* NOT_CANCEL_H  */
diff --git a/sysdeps/unix/sysv/linux/open.c b/sysdeps/unix/sysv/linux/open.c
index c189e285c9..6984b272ac 100644
--- a/sysdeps/unix/sysv/linux/open.c
+++ b/sysdeps/unix/sysv/linux/open.c
@@ -22,7 +22,6 @@ 
 #include <stdarg.h>
 
 #include <sysdep-cancel.h>
-#include <not-cancel.h>
 
 #ifndef __OFF_T_MATCHES_OFF64_T
 
@@ -48,25 +47,4 @@  libc_hidden_def (__libc_open)
 weak_alias (__libc_open, __open)
 libc_hidden_weak (__open)
 weak_alias (__libc_open, open)
-
-# if !IS_IN (rtld)
-int
-__open_nocancel (const char *file, int oflag, ...)
-{
-  int mode = 0;
-
-  if (__OPEN_NEEDS_MODE (oflag))
-    {
-      va_list arg;
-      va_start (arg, oflag);
-      mode = va_arg (arg, int);
-      va_end (arg);
-    }
-
-  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag, mode);
-}
-# else
-strong_alias (__libc_open, __open_nocancel)
-# endif
-libc_hidden_def (__open_nocancel)
 #endif
diff --git a/sysdeps/unix/sysv/linux/open64.c b/sysdeps/unix/sysv/linux/open64.c
index 4af5ee2466..b7dbfa91d6 100644
--- a/sysdeps/unix/sysv/linux/open64.c
+++ b/sysdeps/unix/sysv/linux/open64.c
@@ -21,7 +21,7 @@ 
 #include <stdarg.h>
 
 #include <sysdep-cancel.h>
-#include <not-cancel.h>
+
 
 #ifdef __OFF_T_MATCHES_OFF64_T
 # define EXTRA_OPEN_FLAGS 0
@@ -52,34 +52,9 @@  strong_alias (__libc_open64, __open64)
 libc_hidden_weak (__open64)
 weak_alias (__libc_open64, open64)
 
-# if !IS_IN (rtld)
-int
-__open64_nocancel (const char *file, int oflag, ...)
-{
-  int mode = 0;
-
-  if (__OPEN_NEEDS_MODE (oflag))
-    {
-      va_list arg;
-      va_start (arg, oflag);
-      mode = va_arg (arg, int);
-      va_end (arg);
-    }
-
-  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag | EXTRA_OPEN_FLAGS,
-			      mode);
-}
-#else
-strong_alias (__libc_open64, __open64_nocancel)
-#endif
-libc_hidden_def (__open64_nocancel)
-
 #ifdef __OFF_T_MATCHES_OFF64_T
 strong_alias (__libc_open64, __libc_open)
 strong_alias (__libc_open64, __open)
 libc_hidden_weak (__open)
 weak_alias (__libc_open64, open)
-
-strong_alias (__open64_nocancel, __open_nocancel)
-libc_hidden_weak (__open_nocancel)
 #endif
diff --git a/sysdeps/unix/sysv/linux/open64_nocancel.c b/sysdeps/unix/sysv/linux/open64_nocancel.c
new file mode 100644
index 0000000000..ce2229bcf3
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/open64_nocancel.c
@@ -0,0 +1,53 @@ 
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include <not-cancel.h>
+
+#ifdef __OFF_T_MATCHES_OFF64_T
+# define EXTRA_OPEN_FLAGS 0
+#else
+# define EXTRA_OPEN_FLAGS O_LARGEFILE
+#endif
+
+int
+__open64_nocancel (const char *file, int oflag, ...)
+{
+  int mode = 0;
+
+  if (__OPEN_NEEDS_MODE (oflag))
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, int);
+      va_end (arg);
+    }
+
+  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag | EXTRA_OPEN_FLAGS,
+			      mode);
+}
+
+hidden_def (__open64_nocancel)
+
+#ifdef __OFF_T_MATCHES_OFF64_T
+strong_alias (__open64_nocancel, __open_nocancel)
+hidden_def (__open_nocancel)
+#endif
diff --git a/sysdeps/unix/sysv/linux/open_nocancel.c b/sysdeps/unix/sysv/linux/open_nocancel.c
new file mode 100644
index 0000000000..64dcb0e536
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/open_nocancel.c
@@ -0,0 +1,46 @@ 
+/* Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+#ifndef __OFF_T_MATCHES_OFF64_T
+
+int
+__open_nocancel (const char *file, int oflag, ...)
+{
+  int mode = 0;
+
+  if (__OPEN_NEEDS_MODE (oflag))
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, int);
+      va_end (arg);
+    }
+
+  return INLINE_SYSCALL_CALL (openat, AT_FDCWD, file, oflag, mode);
+}
+hidden_def (__open_nocancel)
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/openat.c b/sysdeps/unix/sysv/linux/openat.c
index 9601e617db..181cdc6105 100644
--- a/sysdeps/unix/sysv/linux/openat.c
+++ b/sysdeps/unix/sysv/linux/openat.c
@@ -19,7 +19,6 @@ 
 #include <stdarg.h>
 
 #include <sysdep-cancel.h>
-#include <not-cancel.h>
 
 #ifndef __OFF_T_MATCHES_OFF64_T
 
@@ -43,24 +42,4 @@  __libc_openat (int fd, const char *file, int oflag, ...)
 weak_alias (__libc_openat, __openat)
 libc_hidden_weak (__openat)
 weak_alias (__libc_openat, openat)
-
-# if !IS_IN (rtld)
-int
-__openat_nocancel (int fd, const char *file, int oflag, ...)
-{
-  mode_t mode = 0;
-  if (__OPEN_NEEDS_MODE (oflag))
-    {
-      va_list arg;
-      va_start (arg, oflag);
-      mode = va_arg (arg, mode_t);
-      va_end (arg);
-    }
-
-  return INLINE_SYSCALL_CALL (openat, fd, file, oflag, mode);
-}
-# else
-strong_alias (__libc_openat, __openat_nocancel)
-# endif
-libc_hidden_weak (__openat_nocancel)
 #endif
diff --git a/sysdeps/unix/sysv/linux/openat64.c b/sysdeps/unix/sysv/linux/openat64.c
index 6f14711df3..818ddc51f0 100644
--- a/sysdeps/unix/sysv/linux/openat64.c
+++ b/sysdeps/unix/sysv/linux/openat64.c
@@ -19,7 +19,6 @@ 
 #include <stdarg.h>
 
 #include <sysdep-cancel.h>
-#include <not-cancel.h>
 
 #ifdef __OFF_T_MATCHES_OFF64_T
 # define EXTRA_OPEN_FLAGS 0
@@ -49,31 +48,8 @@  strong_alias (__libc_openat64, __openat64)
 libc_hidden_weak (__openat64)
 weak_alias (__libc_openat64, openat64)
 
-#if !IS_IN (rtld)
-int
-__openat64_nocancel (int fd, const char *file, int oflag, ...)
-{
-  mode_t mode = 0;
-  if (__OPEN_NEEDS_MODE (oflag))
-    {
-      va_list arg;
-      va_start (arg, oflag);
-      mode = va_arg (arg, mode_t);
-      va_end (arg);
-    }
-
-  return INLINE_SYSCALL_CALL (openat, fd, file, oflag | EXTRA_OPEN_FLAGS,
-			      mode);
-}
-#else
-strong_alias (__libc_openat64, __openat64_nocancel)
-#endif
-libc_hidden_def (__openat64_nocancel)
-
 #ifdef __OFF_T_MATCHES_OFF64_T
 strong_alias (__libc_openat64, __openat)
 libc_hidden_weak (__openat)
 weak_alias (__libc_openat64, openat)
-
-strong_alias (__openat64_nocancel, __openat_nocancel)
 #endif
diff --git a/sysdeps/unix/sysv/linux/openat64_nocancel.c b/sysdeps/unix/sysv/linux/openat64_nocancel.c
new file mode 100644
index 0000000000..ce342dfc0d
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/openat64_nocancel.c
@@ -0,0 +1,50 @@ 
+/* Copyright (C) 2007-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+#ifdef __OFF_T_MATCHES_OFF64_T
+# define EXTRA_OPEN_FLAGS 0
+#else
+# define EXTRA_OPEN_FLAGS O_LARGEFILE
+#endif
+
+int
+__openat64_nocancel (int fd, const char *file, int oflag, ...)
+{
+  mode_t mode = 0;
+  if (__OPEN_NEEDS_MODE (oflag))
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, mode_t);
+      va_end (arg);
+    }
+
+  return INLINE_SYSCALL_CALL (openat, fd, file, oflag | EXTRA_OPEN_FLAGS,
+			      mode);
+}
+hidden_def (__openat64_nocancel)
+
+#ifdef __OFF_T_MATCHES_OFF64_T
+strong_alias (__openat64_nocancel, __openat_nocancel)
+hidden_def (__openat_nocancel)
+#endif
diff --git a/sysdeps/unix/sysv/linux/openat_nocancel.c b/sysdeps/unix/sysv/linux/openat_nocancel.c
new file mode 100644
index 0000000000..0cfc94565c
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/openat_nocancel.c
@@ -0,0 +1,42 @@ 
+/* Copyright (C) 2005-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <fcntl.h>
+#include <stdarg.h>
+
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+#ifndef __OFF_T_MATCHES_OFF64_T
+
+int
+__openat_nocancel (int fd, const char *file, int oflag, ...)
+{
+  mode_t mode = 0;
+  if (__OPEN_NEEDS_MODE (oflag))
+    {
+      va_list arg;
+      va_start (arg, oflag);
+      mode = va_arg (arg, mode_t);
+      va_end (arg);
+    }
+
+  return INLINE_SYSCALL_CALL (openat, fd, file, oflag, mode);
+}
+hidden_def (__openat_nocancel)
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/pause.c b/sysdeps/unix/sysv/linux/pause.c
index 7c8d9f4861..7b90365b98 100644
--- a/sysdeps/unix/sysv/linux/pause.c
+++ b/sysdeps/unix/sysv/linux/pause.c
@@ -19,7 +19,6 @@ 
 #include <signal.h>
 #include <unistd.h>
 #include <sysdep-cancel.h>
-#include <not-cancel.h>
 
 /* Suspend the process until a signal arrives.
    This always returns -1 and sets errno to EINTR.  */
@@ -33,14 +32,3 @@  __libc_pause (void)
 #endif
 }
 weak_alias (__libc_pause, pause)
-
-int
-__pause_nocancel (void)
-{
-#ifdef __NR_pause
-  return INLINE_SYSCALL_CALL (pause);
-#else
-  return INLINE_SYSCALL_CALL (ppoll, NULL, 0, NULL, NULL);
-#endif
-}
-libc_hidden_def (__pause_nocancel)
diff --git a/sysdeps/unix/sysv/linux/pause_nocancel.c b/sysdeps/unix/sysv/linux/pause_nocancel.c
new file mode 100644
index 0000000000..58e0445679
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/pause_nocancel.c
@@ -0,0 +1,33 @@ 
+/* Linux pause syscall implementation.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <signal.h>
+#include <unistd.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+int
+__pause_nocancel (void)
+{
+#ifdef __NR_pause
+  return INLINE_SYSCALL_CALL (pause);
+#else
+  return INLINE_SYSCALL_CALL (ppoll, NULL, 0, NULL, NULL);
+#endif
+}
+hidden_def (__pause_nocancel)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
index 0fc179a9a1..ba500e5f84 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h
@@ -236,4 +236,13 @@ 
 # endif
 #endif
 
+/* In the PowerPC64 ABI, the unadorned F_GETLK* opcodes should be used
+   even by largefile64 code.  */
+#define FCNTL_ADJUST_CMD(__cmd)			\
+  ({ int cmd_ = (__cmd);			\
+     cmd_ == F_GETLK64 ? F_GETLK :		\
+       cmd_ == F_SETLK64 ? F_SETLK :		\
+       cmd_ == F_SETLKW64 ? F_SETLKW : cmd_ })
+
+
 #endif /* linux/powerpc/powerpc64/sysdep.h */
diff --git a/sysdeps/unix/sysv/linux/read.c b/sysdeps/unix/sysv/linux/read.c
index 33ce38aaba..26d0bed404 100644
--- a/sysdeps/unix/sysv/linux/read.c
+++ b/sysdeps/unix/sysv/linux/read.c
@@ -18,7 +18,6 @@ 
 
 #include <unistd.h>
 #include <sysdep-cancel.h>
-#include <not-cancel.h>
 
 /* Read NBYTES into BUF from FD.  Return the number read or -1.  */
 ssize_t
@@ -32,14 +31,3 @@  libc_hidden_def (__read)
 weak_alias (__libc_read, __read)
 libc_hidden_def (read)
 weak_alias (__libc_read, read)
-
-#if !IS_IN (rtld)
-ssize_t
-__read_nocancel (int fd, void *buf, size_t nbytes)
-{
-  return INLINE_SYSCALL_CALL (read, fd, buf, nbytes);
-}
-#else
-strong_alias (__libc_read, __read_nocancel)
-#endif
-libc_hidden_def (__read_nocancel)
diff --git a/sysdeps/unix/sysv/linux/read_nocancel.c b/sysdeps/unix/sysv/linux/read_nocancel.c
new file mode 100644
index 0000000000..fe3a716639
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/read_nocancel.c
@@ -0,0 +1,28 @@ 
+/* Linux read syscall implementation.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+ssize_t
+__read_nocancel (int fd, void *buf, size_t nbytes)
+{
+  return INLINE_SYSCALL_CALL (read, fd, buf, nbytes);
+}
+hidden_def (__read_nocancel)
diff --git a/sysdeps/unix/sysv/linux/waitpid.c b/sysdeps/unix/sysv/linux/waitpid.c
index d1d30fd431..a05d908c7b 100644
--- a/sysdeps/unix/sysv/linux/waitpid.c
+++ b/sysdeps/unix/sysv/linux/waitpid.c
@@ -19,7 +19,6 @@ 
 #include <sysdep-cancel.h>
 #include <stdlib.h>
 #include <sys/wait.h>
-#include <not-cancel.h>
 
 __pid_t
 __waitpid (__pid_t pid, int *stat_loc, int options)
@@ -32,14 +31,3 @@  __waitpid (__pid_t pid, int *stat_loc, int options)
 }
 libc_hidden_def (__waitpid)
 weak_alias (__waitpid, waitpid)
-
-__pid_t
-__waitpid_nocancel (__pid_t pid, int *stat_loc, int options)
-{
-#ifdef __NR_waitpid
-  return INLINE_SYSCALL_CALL (waitpid, pid, stat_loc, options);
-#else
-  return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, NULL);
-#endif
-}
-libc_hidden_def (__waitpid_nocancel)
diff --git a/sysdeps/unix/sysv/linux/waitpid_nocancel.c b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
new file mode 100644
index 0000000000..f8f3231f32
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/waitpid_nocancel.c
@@ -0,0 +1,33 @@ 
+/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <sysdep-cancel.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <not-cancel.h>
+
+__pid_t
+__waitpid_nocancel (__pid_t pid, int *stat_loc, int options)
+{
+#ifdef __NR_waitpid
+  return INLINE_SYSCALL_CALL (waitpid, pid, stat_loc, options);
+#else
+  return INLINE_SYSCALL_CALL (wait4, pid, stat_loc, options, NULL);
+#endif
+}
+libc_hidden_def (__waitpid_nocancel)
diff --git a/sysdeps/unix/sysv/linux/write.c b/sysdeps/unix/sysv/linux/write.c
index c96dc6f397..558639d471 100644
--- a/sysdeps/unix/sysv/linux/write.c
+++ b/sysdeps/unix/sysv/linux/write.c
@@ -18,7 +18,6 @@ 
 
 #include <unistd.h>
 #include <sysdep-cancel.h>
-#include <not-cancel.h>
 
 /* Write NBYTES of BUF to FD.  Return the number written, or -1.  */
 ssize_t
@@ -32,14 +31,3 @@  weak_alias (__libc_write, __write)
 libc_hidden_weak (__write)
 weak_alias (__libc_write, write)
 libc_hidden_weak (write)
-
-#if !IS_IN (rtld)
-ssize_t
-__write_nocancel (int fd, const void *buf, size_t nbytes)
-{
-  return INLINE_SYSCALL_CALL (write, fd, buf, nbytes);
-}
-#else
-strong_alias (__libc_write, __write_nocancel)
-#endif
-libc_hidden_def (__write_nocancel)
diff --git a/sysdeps/unix/sysv/linux/write_nocancel.c b/sysdeps/unix/sysv/linux/write_nocancel.c
new file mode 100644
index 0000000000..696f40beec
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/write_nocancel.c
@@ -0,0 +1,28 @@ 
+/* Linux write syscall implementation.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+ssize_t
+__write_nocancel (int fd, const void *buf, size_t nbytes)
+{
+  return INLINE_SYSCALL_CALL (write, fd, buf, nbytes);
+}
+hidden_def (__write_nocancel)