All of lore.kernel.org
 help / color / mirror / Atom feed
From: Josh Triplett <josh@joshtriplett.org>
To: David Drysdale <drysdale@google.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>,
	Andrew Morton <akpm@linux-foundation.org>,
	Andy Lutomirski <luto@amacapital.net>,
	Ingo Molnar <mingo@redhat.com>, Kees Cook <keescook@chromium.org>,
	Oleg Nesterov <oleg@redhat.com>,
	"Paul E. McKenney" <paulmck@linux.vnet.ibm.com>,
	"H. Peter Anvin" <hpa@zytor.com>, Rik van Riel <riel@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Thiago Macieira <thiago.macieira@intel.com>,
	Michael Kerrisk <mtk.manpages@gmail.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Linux API <linux-api@vger.kernel.org>,
	linux-fsdevel@vger.kernel.org, X86 ML <x86@kernel.org>
Subject: Re: [PATCH 0/6] CLONE_FD: Task exit notification via file descriptor
Date: Fri, 13 Mar 2015 12:42:52 -0700	[thread overview]
Message-ID: <20150313194252.GA10317@cloud> (raw)
In-Reply-To: <CAHse=S9hnGm=Z8FR4f+z_TFwnrjBLkcV4wVwjDYgKuOSemdVrA@mail.gmail.com>

On Fri, Mar 13, 2015 at 04:05:29PM +0000, David Drysdale wrote:
> On Fri, Mar 13, 2015 at 1:40 AM, Josh Triplett <josh@joshtriplett.org> wrote:
> > This patch series introduces a new clone flag, CLONE_FD, which lets the caller
> > handle child process exit notification via a file descriptor rather than
> > SIGCHLD.  CLONE_FD makes it possible for libraries to safely launch and manage
> > child processes on behalf of their caller, *without* taking over process-wide
> > SIGCHLD handling (either via signal handler or signalfd).
> 
> Hi Josh,
> 
> From the overall description (i.e. I haven't looked at the code yet)
> this looks very interesting.  However, it seems to cover a lot of the
> same ground as the process descriptor feature that was added to FreeBSD
> in 9.x/10.x:
>   https://www.freebsd.org/cgi/man.cgi?query=pdfork&sektion=2

Interesting.

> I think it would ideally be nice for a userspace library developer to be
> able to do subprocess management (without SIGCHLD) in a similar way
> across both platforms, without lots of complicated autoconf shenanigans.
>
> So could we look at the overlap and seeing if we can come up with
> something that covers your requirements and also allows for something
> that looks like FreeBSD's process descriptors?

Agreed; however, I think it's reasonable to provide appropriate Linux
system calls, and then let glibc or libbsd or similar provide the
BSD-compatible calls on top of those.  I don't think the kernel
interface needs to exactly match FreeBSD's, as long as it's a superset
of the functionality.

For example, pdfork can just call clone4 with CLONE_FD and return the
resulting file descriptor.

In my further comments below, I'll suggest ways that the FreeBSD library
calls could be implemented on top of Linux system calls.

> (I've actually got some rough patches to add process descriptor
> functionality on Linux, so I can look at how the two approaches compare
> and contrast.)
> 
> > Note that signalfd for SIGCHLD does not suffice here, because that still
> > receives notification for all child processes, and interferes with process-wide
> > signal handling.
> >
> > The CLONE_FD file descriptor uniquely identifies a process on the system in a
> > race-free way, by holding a reference to the task_struct.  In the future, we
> > may introduce APIs that support using process file descriptors instead of PIDs.
> 
> FreeBSD has pdkill(2) and (theoretically) pdwait4(2) along these lines.
> I suspect we need either need pdkill(2) or a way to retrieve a PID from
> a process file descriptor, so that there's a way to send signals to the
> child.

The original caller of clone4 with CLONE_FD can pass CLONE_PARENT_SETTID
to get the PID.

In the future, I plan to add an fd-based equivalent of
rt_{,tg}sigqueueinfo (likely a single syscall with a flag to determine
whether to kill a process or thread) which is a superset of pdkill.
pdkill could then call that and just not pass the extra info.

A fair bit of pdwait4 could be implemented on top of read(), other than
the full rusage information (see below), and the ability to wait for
STOP/CONT (which the CLONE_FD file descriptor could support if desired,
but it'd have to be set via a flag at clone time).

I think it's a feature to use read() rather than an additional magic
system call.

> > Introducing CLONE_FD required two additional bits of yak shaving: Since clone
> > has no more usable flags (with the three currently unused flags unusable
> > because old kernels ignore them without EINVAL), also introduce a new clone4
> > system call with more flag bits and an extensible argument structure.  And
> > since the magic pt_regs-based syscall argument processing for clone's tls
> > argument would otherwise prevent introducing a sane clone4 system call, fix
> > that too.
> >
> > I tested the CLONE_SETTLS changes with a thread-local storage test program (two
> > threads independently reading and writing a __thread variable), on both 32-bit
> > and 64-bit, and I observed no issues there.
> 
> Worth preserving in tools/testing/selftests/ ?

Not really; it's just the following trivial program, which was faster to
write than to attempt to find somewhere:

#include <pthread.h>
#include <stdio.h>

__thread unsigned x = 0;

void *thread_func(void *unused)
{
    unsigned *tx = &x;
    for (; *tx < 10; (*tx)++)
        printf("child: tx=%p *tx=%u\n", tx, *tx);
    return NULL;
}

int main(void)
{
    unsigned *tx = &x;
    pthread_t thread;
    pthread_create(&thread, NULL, thread_func, NULL);
    for (; *tx < 10; (*tx)++)
        printf("main: tx=%p *tx=%u\n", tx, *tx);
    pthread_join(thread, NULL);
    return 0;
}

(I didn't bother with error handling, because I ran it under strace.)

> > I tested clone4 and the new CLONE_FD call with several additional test
> > programs, launching either a process or thread (in the former case using
> > syscall(), in the latter case by calling clone4 via assembly and returning to
> > C), sleeping in parent and child to test the case of either exiting first, and
> > then printing the received clone4_info structure.  Thiago also tested clone4
> > with CLONE_FD with a modified version of libqt's process handling, which
> > includes a test suite.
> >
> > I've also included the manpages patch at the end of this series.  (Note that
> > the manpage documents the behavior of the future glibc wrapper as well as the
> > raw syscall.)  Here's a formatted plain-text version of the manpage for
> > reference:
> 
> FYI, I've added some comparisons with the FreeBSD equivalents below.

Thanks!

> > CLONE4(2)                  Linux Programmer's Manual                 CLONE4(2)
> >
> >
> >
> > NAME
> >        clone4 - create a child process
> >
> > SYNOPSIS
> >        /* Prototype for the glibc wrapper function */
> >
> >        #define _GNU_SOURCE
> >        #include <sched.h>
> >
> >        int clone4(uint64_t flags,
> >                   size_t args_size,
> >                   struct clone4_args *args,
> >                   int (*fn)(void *), void *arg);
> >
> >        /* Prototype for the raw system call */
> >
> >        int clone4(unsigned flags_high, unsigned flags_low,
> >                   unsigned long args_size,
> >                   struct clone4_args *args);
> >
> >        struct clone4_args {
> >            pid_t *ptid;
> >            pid_t *ctid;
> >            unsigned long stack_start;
> >            unsigned long stack_size;
> >            unsigned long tls;
> >        };
> >
> >
> > DESCRIPTION
> >        clone4()  creates  a  new  process,  similar  to  clone(2) and fork(2).
> >        clone4() supports additional flags that clone(2) does not, and  accepts
> >        arguments via an extensible structure.
> >
> >        args  points to a clone4_args structure, and args_size must contain the
> >        size of that structure, as understood by the  caller.   If  the  caller
> >        passes  a  shorter  structure  than  the  kernel expects, the remaining
> >        fields will default to 0.  If the caller passes a larger structure than
> >        the  kernel  expects  (such  as one from a newer kernel), clone4() will
> >        return EINVAL.  The clone4_args structure may gain additional fields at
> >        the  end  in  the future, and callers must only pass a size that encom‐
> >        passes the number of fields they understand.  If the  caller  passes  0
> >        for args_size, args is ignored and may be NULL.
> >
> >        In  the clone4_args structure, ptid, ctid, stack_start, stack_size, and
> >        tls have the same semantics as they do with clone(2) and clone2(2).
> >
> >        In the glibc wrapper, fn and arg have the same  semantics  as  they  do
> >        with clone(2).  As with clone(2), the underlying system call works more
> >        like fork(2), returning 0 in the child process; the glibc wrapper  sim‐
> >        plifies  thread execution by calling fn(arg) and exiting the child when
> >        that function exits.
> >
> >        The 64-bit  flags  argument  (split  into  the  32-bit  flags_high  and
> >        flags_low arguments in the kernel interface) accepts all the same flags
> >        as  clone(2),  with  the   exception   of   the   obsolete   CLONE_PID,
> >        CLONE_DETACHED, and CLONE_STOPPED.  In addition, flags accepts the fol‐
> >        lowing flags:
> >
> >
> >        CLONE_FD
> >               Instead of returning a process ID, clone4()  with  the  CLONE_FD
> >               flag  returns a file descriptor associated with the new process.
> >               When the new process exits, the kernel will not send a signal to
> >               the  parent process, and will not keep the new process around as
> >               a "zombie" process  until  a  call  to  waitpid(2)  or  similar.
> >               Instead,  the file descriptor will become available for reading,
> >               and the new process will be immediately reaped.
> 
> Just to confirm: presumably a waitpid(-1,...) call that's already in
> progress won't return when one of these child processes exits?

I agree, I don't think it should.  Because otherwise you'd also assume
you can waitpid() on the PID itself, and that'd be a race condition
since the process autoreaps.

> >               Unlike using  signalfd(2)  for  the  SIGCHLD  signal,  the  file
> >               descriptor  returned  by  clone4()  with the CLONE_FD flag works
> >               even with SIGCHLD unblocked in one or more threads of the parent
> >               process,  and  allows the process to have different handlers for
> >               different child processes, such as those created by  a  library,
> >               without  introducing  race conditions around process-wide signal
> >               handling.
> >
> >               clone4() will never return a file descriptor in the range 0-2 to
> >               the caller, to avoid ambiguity with the return of 0 in the child
> >               process.  Only the  calling  process  will  have  the  new  file
> >               descriptor open; the child process will not.
> 
> FreeBSD's pdfork(2) returns a PID but also takes an int *fdp argument to
> return the file descriptor separately, which avoids the need for special
> case processing for low FD values (and means that POSIX's "lowest file
> descriptor not currently open" behaviour can be preserved if desired).

That'd be easy to implement if desired, by adding an outbound pointer to
clone4_args.

The (very mild) reason I'd dropped the PID: with CLONE_FD and future
syscalls that use the fd as an identifier, PIDs can hopefully become
mostly unnecessary.  However, I'm not that attached to changing the
return value; it'd be trivial to switch to an outbound parameter
instead, and then drop the "not 0-2".

> >               Since the kernel does not send a termination signal when a child
> >               process created with CLONE_FD exits, the low byte of flags  does
> >               not contain a signal number.  Instead, the low byte of flags can
> >               contain the following additional flags for use with CLONE_FD:
> >
> >
> >               CLONEFD_CLOEXEC
> >                      Set the O_CLOEXEC flag on the new open  file  descriptor.
> >                      See  the description of the O_CLOEXEC flag in open(2) for
> >                      reasons why this may be useful.
> >
> >
> >               CLONEFD_NONBLOCK
> >                      Set the O_NONBLOCK flag on the new open file  descriptor.
> >                      Using  this flag saves extra calls to fcntl(2) to achieve
> >                      the same result.
> >
> >
> >               clone4() with the CLONE_FD flag returns a file  descriptor  that
> >               supports the following operations:
> >
> >               read(2) (and similar)
> >                      When  the  new  process  exits,  reading  from  the  file
> >                      descriptor produces a single clonefd_info structure:
> >
> >                      struct clonefd_info {
> >                          uint32_t code;   /* Signal code */
> >                          uint32_t status; /* Exit status or signal */
> >                          uint64_t utime;  /* User CPU time */
> >                          uint64_t stime;  /* System CPU time */
> >                      };
> 
> Presumably there is no way to get full rusage information for the exited
> process?

I focused on the information available via SIGCHLD.  Even utime and
stime are unnecessary for the primary use case of CLONE_FD, but I
included them because SIGCHLD does.  I'd like to avoid sending the much
larger rusage over the file descriptor when the caller may not care.

However, given that the task_struct sticks around as long as the
CLONE_FD file descriptor does, if that information is normally still
available from a dead-but-not-waited-on process, it should be trivial to
add an operation that takes the file descriptor and returns the full
rusage, if someone needs that.  I think that can be done as part of a
later patch series adding other operations for use with the file
descriptor, though.

> [FreeBSD theoretically has pdwait4(2) to do wait4-like operations on a
> process descriptor, including rusage retrieval.  However, I don't think
> they actually implemented it:
>   http://fxr.watson.org/fxr/source/kern/syscalls.master#L928]

That's a pretty good argument that we don't need to either, at least not
yet.

> >                      If the new process has not  yet  exited,  read(2)  either
> >                      blocks  until  it does, or fails with the error EAGAIN if
> >                      the file descriptor has been made nonblocking.
> >
> >                      Future kernels may extend clonefd_info by appending addi‐
> >                      tional  fields  to  the end.  Callers should read as many
> >                      bytes as they understand; unread data will be  discarded,
> >                      and  subsequent  reads  after  the first will return 0 to
> >                      indicate end-of-file.  Callers requesting more bytes than
> >                      the  kernel  provides  (such as callers expecting a newer
> >                      clonefd_info structure) will receive a shorter  structure
> >                      from older kernels.
> 
> FreeBSD also implements fstat(2) for its process descriptors, although
> only a few of the fields get filled in.

I looked at what they provide, and that seems like more of a novelty
than something particularly useful (since most of the stat fields aren't
meaningful), but if that's useful for compatibility then adding it seems
fine.

> >               poll(2), select(2), epoll(7) (and similar)
> >                      The  file  descriptor  is readable (the select(2) readfds
> >                      argument; the poll(2) POLLIN flag) if the new process has
> >                      exited.
> 
> FreeBSD uses POLLHUP here.

That makes sense given that they provide the information via a separate
call rather than read.  Since the CLONE_FD file descriptor uses read, it
needs to provide POLLIN, but I have no objection to using *both* POLLIN
and POLLHUP if that'd be at all useful.

> >               close(2)
> >                      When  the file descriptor is no longer required it should
> >                      be closed.  If no process has a file descriptor open  for
> >                      the new process, no process will receive any notification
> >                      when the new process exits.  The new process  will  still
> >                      be immediately reaped.
> 
> FreeBSD has two different behaviours for close(2), depending on a flag
> value (PD_DAEMON).  With the flag set it's roughly like this, but
> without PD_DAEMON a close(2) operation on the (last open) file
> descriptor terminates the child process.
> 
> This can be quite useful, particularly for the use case where some
> userspace library has an FD-controlled subprocess -- if the application
> using the library terminates, the process descriptor is closed and so
> the subprocess is automatically terminated.

That's an interesting idea.  I don't think it makes sense for that to be
the default behavior, but if someone wanted to add an additional flag
to implement that behavior, that seems fine.  A FreeBSD-compatible
pdfork could then use that flag when not passed PD_DAEMON and not use it
when passed PD_DAEMON.

How does it kill the process when the last open descriptor closes?
SIGKILL?  SIGTERM?  The former seems unfriendly (preventing graceful
termination), and the latter blockable.  There's a reason init systems
send TERM, then wait, then KILL.

- Josh Triplett

  reply	other threads:[~2015-03-13 19:42 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-13  1:40 [PATCH 0/6] CLONE_FD: Task exit notification via file descriptor Josh Triplett
2015-03-13  1:40 ` Josh Triplett
2015-03-13  1:40 ` [PATCH 1/6] clone: Support passing tls argument via C rather than pt_regs magic Josh Triplett
     [not found] ` <cover.1426180120.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
2015-03-13  1:40   ` [PATCH 2/6] x86: Opt into HAVE_COPY_THREAD_TLS, for both 32-bit and 64-bit Josh Triplett
2015-03-13  1:40     ` Josh Triplett
     [not found]     ` <cf79b9f0c40314e6bfda7c634e378015bd7ba037.1426180120.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
2015-03-13 22:01       ` Andy Lutomirski
2015-03-13 22:01         ` Andy Lutomirski
2015-03-13 22:31         ` josh
2015-03-13 22:38           ` Andy Lutomirski
     [not found]             ` <CALCETrWspvNcEYxwbo1+ifXSj7Qj7YdcRgmNvZ1RaBrUAK12Zw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-03-13 22:43               ` josh-iaAMLnmF4UmaiuxdJuQwMA
2015-03-13 22:43                 ` josh
2015-03-13 22:45                 ` Andy Lutomirski
2015-03-13 22:45                   ` Andy Lutomirski
     [not found]                   ` <CALCETrW3kJSVz4ffVC6YdB+ELukhOHNgPFKZSziMq5nn_Nq3Zg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-03-13 23:01                     ` josh-iaAMLnmF4UmaiuxdJuQwMA
2015-03-13 23:01                       ` josh
2015-03-13  1:40   ` [PATCH 5/6] fs: Make alloc_fd non-private Josh Triplett
2015-03-13  1:40     ` Josh Triplett
2015-03-13  2:07   ` [PATCH 0/6] CLONE_FD: Task exit notification via file descriptor Thiago Macieira
2015-03-13  2:07     ` Thiago Macieira
2015-03-13 16:05   ` David Drysdale
2015-03-13 16:05     ` David Drysdale
2015-03-13 19:42     ` Josh Triplett [this message]
2015-03-13 21:16       ` Thiago Macieira
2015-03-13 21:44         ` josh
2015-03-13 21:33       ` Andy Lutomirski
     [not found]         ` <CALCETrXH+Ui1XqVZjFB=8vDpJLCYeVf+XNUPGWNfwDsNKi_nKg-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-03-13 21:45           ` josh-iaAMLnmF4UmaiuxdJuQwMA
2015-03-13 21:45             ` josh
2015-03-13 21:51             ` Andy Lutomirski
2015-03-13 21:51               ` Andy Lutomirski
     [not found]               ` <CALCETrWwkdWkNCsrcSAn+7f9SJCuYA-TV9=AygWMhXCC9Njp9Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-03-14  1:11                 ` Thiago Macieira
2015-03-14  1:11                   ` Thiago Macieira
2015-03-14 19:03                   ` Thiago Macieira
2015-03-14 19:29                     ` Josh Triplett
2015-03-14 19:29                       ` Josh Triplett
2015-03-15 10:18                       ` David Drysdale
2015-03-15 10:18                         ` David Drysdale
2015-03-15 10:59                         ` Josh Triplett
2015-03-15  8:55       ` David Drysdale
2015-03-15  8:55         ` David Drysdale
2015-03-13  1:40 ` [PATCH 3/6] Introduce a new clone4 syscall with more flag bits and extensible arguments Josh Triplett
2015-03-13  1:40 ` [PATCH 4/6] signal: Factor out a helper function to process task_struct exit_code Josh Triplett
2015-03-13  1:41 ` [PATCH 6/6] clone4: Introduce new CLONE_FD flag to get task exit notification via fd Josh Triplett
2015-03-13 16:21   ` Oleg Nesterov
2015-03-13 19:57     ` josh
2015-03-13 21:34       ` Andy Lutomirski
2015-03-13 21:34         ` Andy Lutomirski
2015-03-13 22:20         ` josh
2015-03-13 22:28           ` Andy Lutomirski
2015-03-13 22:28             ` Andy Lutomirski
     [not found]             ` <CALCETrVRqgsbpi9pPRwy42cuXiDzyPgWRJmfSRSQM7eGFfsZYA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-03-13 22:34               ` josh-iaAMLnmF4UmaiuxdJuQwMA
2015-03-13 22:34                 ` josh
2015-03-13 22:38                 ` Andy Lutomirski
2015-03-14 14:14       ` Oleg Nesterov
2015-03-14 14:14         ` Oleg Nesterov
     [not found]         ` <20150314141414.GA11062-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-03-14 14:32           ` Oleg Nesterov
2015-03-14 14:32             ` Oleg Nesterov
2015-03-14 18:38             ` Thiago Macieira
2015-03-14 18:54               ` Oleg Nesterov
     [not found]                 ` <20150314185424.GA6813-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-03-14 22:03                   ` Josh Triplett
2015-03-14 22:03                     ` Josh Triplett
2015-03-14 22:26                     ` Thiago Macieira
2015-03-14 19:01               ` Josh Triplett
2015-03-14 19:18                 ` Oleg Nesterov
2015-03-14 19:18                   ` Oleg Nesterov
     [not found]                   ` <20150314191836.GA8416-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-03-14 19:47                     ` Oleg Nesterov
2015-03-14 19:47                       ` Oleg Nesterov
     [not found]                       ` <20150314194721.GA9654-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-03-14 20:14                         ` Josh Triplett
2015-03-14 20:14                           ` Josh Triplett
2015-03-14 20:30                           ` Oleg Nesterov
     [not found]                             ` <20150314203029.GA11656-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-03-14 22:14                               ` Josh Triplett
2015-03-14 22:14                                 ` Josh Triplett
2015-03-14 20:03                     ` Josh Triplett
2015-03-14 20:03                       ` Josh Triplett
2015-03-14 20:20                       ` Oleg Nesterov
2015-03-14 22:09         ` Josh Triplett
     [not found]   ` <9c39c576e1d9a9912b4aec54d833a73a84d2f592.1426180120.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>
2015-03-14 14:35     ` Oleg Nesterov
2015-03-14 14:35       ` Oleg Nesterov
     [not found]       ` <20150314143558.GB12086-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-03-14 19:15         ` Josh Triplett
2015-03-14 19:15           ` Josh Triplett
2015-03-14 19:24           ` Oleg Nesterov
     [not found]             ` <20150314192456.GA8707-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2015-03-14 19:48               ` Josh Triplett
2015-03-14 19:48                 ` Josh Triplett
2015-03-13  1:41 ` [PATCH] clone4.2: New manpage documenting clone4(2) Josh Triplett

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150313194252.GA10317@cloud \
    --to=josh@joshtriplett.org \
    --cc=akpm@linux-foundation.org \
    --cc=drysdale@google.com \
    --cc=hpa@zytor.com \
    --cc=keescook@chromium.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=mingo@redhat.com \
    --cc=mtk.manpages@gmail.com \
    --cc=oleg@redhat.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=riel@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=thiago.macieira@intel.com \
    --cc=viro@zeniv.linux.org.uk \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.