From: "Arve Hjønnevåg" <arve@android.com>
To: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: "Arve Hjønnevåg" <arve@android.com>, NeilBrown <neilb@suse.de>,
"Linux PM list" <linux-pm@vger.kernel.org>,
LKML <linux-kernel@vger.kernel.org>,
"Magnus Damm" <magnus.damm@gmail.com>,
markgross@thegnar.org, "Matthew Garrett" <mjg@redhat.com>,
"Greg KH" <gregkh@linuxfoundation.org>,
"John Stultz" <john.stultz@linaro.org>,
"Brian Swetland" <swetland@google.com>,
"Alan Stern" <stern@rowland.harvard.edu>,
"Dmitry Torokhov" <dmitry.torokhov@gmail.com>,
"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Subject: [PATCH] epoll: Add a flag, EPOLLWAKEUP, to prevent suspend while epoll events are ready
Date: Mon, 30 Apr 2012 22:33:48 -0700 [thread overview]
Message-ID: <1335850428-30883-1-git-send-email-arve@android.com> (raw)
In-Reply-To: <CAMP5XgcatAchOXaEG0rbULes5pVHHsuGeuJ2CKaVGEdj1LzMDg@mail.gmail.com>
When an epoll_event, that has the EPOLLWAKEUP flag set, is ready, a
wakeup_source will be active to prevent suspend. This can be used to
handle wakeup events from a driver that support poll, e.g. input, if
that driver wakes up the waitqueue passed to epoll before allowing
suspend.
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
---
fs/eventpoll.c | 90 ++++++++++++++++++++++++++++++++++++++++++-
include/linux/capability.h | 5 ++-
include/linux/eventpoll.h | 12 ++++++
3 files changed, 103 insertions(+), 4 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 739b098..1abed50 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -33,6 +33,7 @@
#include <linux/bitops.h>
#include <linux/mutex.h>
#include <linux/anon_inodes.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/mman.h>
@@ -87,7 +88,7 @@
*/
/* Epoll private bits inside the event mask */
-#define EP_PRIVATE_BITS (EPOLLONESHOT | EPOLLET)
+#define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET)
/* Maximum number of nesting allowed inside epoll sets */
#define EP_MAX_NESTS 4
@@ -154,6 +155,9 @@ struct epitem {
/* List header used to link this item to the "struct file" items list */
struct list_head fllink;
+ /* wakeup_source used when EPOLLWAKEUP is set */
+ struct wakeup_source *ws;
+
/* The structure that describe the interested events and the source fd */
struct epoll_event event;
};
@@ -194,6 +198,9 @@ struct eventpoll {
*/
struct epitem *ovflist;
+ /* wakeup_source used when ep_scan_ready_list is running */
+ struct wakeup_source *ws;
+
/* The user that created the eventpoll descriptor */
struct user_struct *user;
@@ -588,8 +595,10 @@ static int ep_scan_ready_list(struct eventpoll *ep,
* queued into ->ovflist but the "txlist" might already
* contain them, and the list_splice() below takes care of them.
*/
- if (!ep_is_linked(&epi->rdllink))
+ if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
+ }
}
/*
* We need to set back ep->ovflist to EP_UNACTIVE_PTR, so that after
@@ -602,6 +611,7 @@ static int ep_scan_ready_list(struct eventpoll *ep,
* Quickly re-inject items left on "txlist".
*/
list_splice(&txlist, &ep->rdllist);
+ __pm_relax(ep->ws);
if (!list_empty(&ep->rdllist)) {
/*
@@ -656,6 +666,8 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
list_del_init(&epi->rdllink);
spin_unlock_irqrestore(&ep->lock, flags);
+ wakeup_source_unregister(epi->ws);
+
/* At this point it is safe to free the eventpoll item */
kmem_cache_free(epi_cache, epi);
@@ -706,6 +718,7 @@ static void ep_free(struct eventpoll *ep)
mutex_unlock(&epmutex);
mutex_destroy(&ep->mtx);
free_uid(ep->user);
+ wakeup_source_unregister(ep->ws);
kfree(ep);
}
@@ -737,6 +750,7 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head,
* callback, but it's not actually ready, as far as
* caller requested events goes. We can remove it here.
*/
+ __pm_relax(epi->ws);
list_del_init(&epi->rdllink);
}
}
@@ -927,13 +941,23 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
if (epi->next == EP_UNACTIVE_PTR) {
epi->next = ep->ovflist;
ep->ovflist = epi;
+ if (epi->ws) {
+ /*
+ * Activate ep->ws since epi->ws may get
+ * deactivated at any time.
+ */
+ __pm_stay_awake(ep->ws);
+ }
+
}
goto out_unlock;
}
/* If this file is already in the ready list we exit soon */
- if (!ep_is_linked(&epi->rdllink))
+ if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
+ }
/*
* Wake up ( if active ) both the eventpoll wait list and the ->poll()
@@ -1091,6 +1115,30 @@ static int reverse_path_check(void)
return error;
}
+static int ep_create_wakeup_source(struct epitem *epi)
+{
+ const char *name;
+
+ if (!epi->ep->ws) {
+ epi->ep->ws = wakeup_source_register("eventpoll");
+ if (!epi->ep->ws)
+ return -ENOMEM;
+ }
+
+ name = epi->ffd.file->f_path.dentry->d_name.name;
+ epi->ws = wakeup_source_register(name);
+ if (!epi->ws)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static void ep_destroy_wakeup_source(struct epitem *epi)
+{
+ wakeup_source_unregister(epi->ws);
+ epi->ws = NULL;
+}
+
/*
* Must be called with "mtx" held.
*/
@@ -1118,6 +1166,13 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
epi->event = *event;
epi->nwait = 0;
epi->next = EP_UNACTIVE_PTR;
+ if (epi->event.events & EPOLLWAKEUP) {
+ error = ep_create_wakeup_source(epi);
+ if (error)
+ goto error_create_wakeup_source;
+ } else {
+ epi->ws = NULL;
+ }
/* Initialize the poll table using the queue callback */
epq.epi = epi;
@@ -1164,6 +1219,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
/* If the file is already "ready" we drop it inside the ready list */
if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
/* Notify waiting tasks that events are available */
if (waitqueue_active(&ep->wq))
@@ -1204,6 +1260,9 @@ error_unregister:
list_del_init(&epi->rdllink);
spin_unlock_irqrestore(&ep->lock, flags);
+ wakeup_source_unregister(epi->ws);
+
+error_create_wakeup_source:
kmem_cache_free(epi_cache, epi);
return error;
@@ -1229,6 +1288,12 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
epi->event.events = event->events;
pt._key = event->events;
epi->event.data = event->data; /* protected by mtx */
+ if (epi->event.events & EPOLLWAKEUP) {
+ if (!epi->ws)
+ ep_create_wakeup_source(epi);
+ } else if (epi->ws) {
+ ep_destroy_wakeup_source(epi);
+ }
/*
* Get current event bits. We can safely use the file* here because
@@ -1244,6 +1309,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
spin_lock_irq(&ep->lock);
if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
/* Notify waiting tasks that events are available */
if (waitqueue_active(&ep->wq))
@@ -1282,6 +1348,18 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
!list_empty(head) && eventcnt < esed->maxevents;) {
epi = list_first_entry(head, struct epitem, rdllink);
+ /*
+ * Activate ep->ws before deactivating epi->ws to prevent
+ * triggering auto-suspend here (in case we reactive epi->ws
+ * below).
+ *
+ * This could be rearranged to delay the deactivation of epi->ws
+ * instead, but then epi->ws would temporarily be out of sync
+ * with ep_is_linked().
+ */
+ if (epi->ws && epi->ws->active)
+ __pm_stay_awake(ep->ws);
+ __pm_relax(epi->ws);
list_del_init(&epi->rdllink);
pt._key = epi->event.events;
@@ -1298,6 +1376,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
if (__put_user(revents, &uevent->events) ||
__put_user(epi->event.data, &uevent->data)) {
list_add(&epi->rdllink, head);
+ __pm_stay_awake(epi->ws);
return eventcnt ? eventcnt : -EFAULT;
}
eventcnt++;
@@ -1317,6 +1396,7 @@ static int ep_send_events_proc(struct eventpoll *ep, struct list_head *head,
* poll callback will queue them in ep->ovflist.
*/
list_add_tail(&epi->rdllink, &ep->rdllist);
+ __pm_stay_awake(epi->ws);
}
}
}
@@ -1629,6 +1709,10 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
if (!tfile->f_op || !tfile->f_op->poll)
goto error_tgt_fput;
+ /* Check if EPOLLWAKEUP is allowed */
+ if ((epds.events & EPOLLWAKEUP) && !capable(CAP_EPOLLWAKEUP))
+ goto error_tgt_fput;
+
/*
* We have to check that the file structure underneath the file descriptor
* the user passed to us _is_ an eventpoll file. And also we do not permit
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 12d52de..222974a 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -360,8 +360,11 @@ struct cpu_vfs_cap_data {
#define CAP_WAKE_ALARM 35
+/* Allow preventing automatic system suspends while epoll events are pending */
-#define CAP_LAST_CAP CAP_WAKE_ALARM
+#define CAP_EPOLLWAKEUP 36
+
+#define CAP_LAST_CAP CAP_EPOLLWAKEUP
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index 657ab55..5b591fb 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -26,6 +26,18 @@
#define EPOLL_CTL_DEL 2
#define EPOLL_CTL_MOD 3
+/*
+ * Request the handling of system wakeup events so as to prevent automatic
+ * system suspends from happening while those events are being processed.
+ *
+ * Assuming neither EPOLLET nor EPOLLONESHOT is set, automatic system suspends
+ * will not be re-allowed until epoll_wait is called again after consuming the
+ * wakeup event(s).
+ *
+ * Requires CAP_EPOLLWAKEUP
+ */
+#define EPOLLWAKEUP (1 << 29)
+
/* Set the One Shot behaviour for the target file descriptor */
#define EPOLLONESHOT (1 << 30)
--
1.7.7.3
next prev parent reply other threads:[~2012-05-01 5:34 UTC|newest]
Thread overview: 129+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-07 1:00 [RFC][PATCH 0/8] PM: Implement autosleep and "wake locks" Rafael J. Wysocki
2012-02-07 1:01 ` [PATCH 1/8] PM / Sleep: Initialize wakeup source locks in wakeup_source_add() Rafael J. Wysocki
2012-02-07 22:29 ` John Stultz
2012-02-07 22:41 ` Rafael J. Wysocki
2012-02-07 1:03 ` [PATCH 2/8] PM / Sleep: Do not check wakeup too often in try_to_freeze_tasks() Rafael J. Wysocki
2012-02-07 1:03 ` [PATCH 3/8] PM / Sleep: Look for wakeup events in later stages of device suspend Rafael J. Wysocki
2012-02-07 1:04 ` [PATCH 4/8] PM / Sleep: Use wait queue to signal "no wakeup events in progress" Rafael J. Wysocki
2012-02-08 23:10 ` NeilBrown
2012-02-09 0:05 ` Rafael J. Wysocki
2012-02-12 1:27 ` mark gross
2012-02-07 1:05 ` [RFC][PATCH 5/8] PM / Sleep: Change wakeup statistics Rafael J. Wysocki
2012-02-15 6:15 ` Arve Hjønnevåg
2012-02-15 22:37 ` Rafael J. Wysocki
2012-02-17 2:11 ` Arve Hjønnevåg
2012-02-07 1:06 ` [RFC][PATCH 6/8] PM / Sleep: Implement opportunistic sleep Rafael J. Wysocki
2012-02-07 22:49 ` [Update][RFC][PATCH " Rafael J. Wysocki
2012-02-07 1:06 ` [RFC][PATCH 7/8] PM / Sleep: Add "prevent autosleep time" statistics to wakeup sources Rafael J. Wysocki
2012-02-07 1:07 ` [RFC][PATCH 8/8] PM / Sleep: Add user space interface for manipulating " Rafael J. Wysocki
2012-02-07 1:13 ` [RFC][PATCH 0/8] PM: Implement autosleep and "wake locks" Rafael J. Wysocki
2012-02-08 23:57 ` NeilBrown
2012-02-10 0:44 ` Rafael J. Wysocki
2012-02-12 2:05 ` mark gross
2012-02-12 21:32 ` Rafael J. Wysocki
2012-02-14 0:11 ` Arve Hjønnevåg
2012-02-15 15:28 ` mark gross
2012-02-12 1:54 ` mark gross
2012-02-12 1:19 ` mark gross
2012-02-14 2:07 ` Arve Hjønnevåg
2012-02-14 23:22 ` Rafael J. Wysocki
2012-02-15 5:57 ` Arve Hjønnevåg
2012-02-15 23:07 ` Rafael J. Wysocki
2012-02-16 22:22 ` Rafael J. Wysocki
2012-02-17 3:56 ` Arve Hjønnevåg
2012-02-17 23:02 ` [PATCH] PM / Sleep: Add more wakeup source initialization routines Rafael J. Wysocki
2012-02-18 23:50 ` [Update][PATCH] " Rafael J. Wysocki
2012-02-20 23:04 ` [Update 2x][PATCH] " Rafael J. Wysocki
2012-02-17 3:55 ` [RFC][PATCH 0/8] PM: Implement autosleep and "wake locks" Arve Hjønnevåg
2012-02-17 20:57 ` Rafael J. Wysocki
2012-02-21 23:31 ` [RFC][PATCH 0/7] PM: Implement autosleep and "wake locks", take 2 Rafael J. Wysocki
2012-02-21 23:32 ` [RFC][PATCH 1/7] PM / Sleep: Look for wakeup events in later stages of device suspend Rafael J. Wysocki
2012-02-21 23:33 ` [RFC][PATCH 2/7] PM / Sleep: Use wait queue to signal "no wakeup events in progress" Rafael J. Wysocki
2012-02-21 23:34 ` [RFC][PATCH 3/7] PM / Sleep: Change wakeup source statistics to follow Android Rafael J. Wysocki
2012-02-21 23:34 ` [RFC][PATCH 4/7] Input / PM: Add ioctl to block suspend while event queue is not empty Rafael J. Wysocki
2012-02-24 5:16 ` Matt Helsley
2012-02-25 4:25 ` Arve Hjønnevåg
2012-02-25 23:33 ` Rafael J. Wysocki
2012-02-28 0:19 ` Matt Helsley
2012-02-26 20:57 ` Rafael J. Wysocki
2012-02-27 22:18 ` Matt Helsley
2012-02-28 1:17 ` Rafael J. Wysocki
2012-02-28 5:58 ` Arve Hjønnevåg
2012-03-04 22:56 ` Rafael J. Wysocki
2012-03-06 1:04 ` [PATCH 1/2] epoll: Add a flag, EPOLLWAKEUP, to prevent suspend while epoll events are ready Arve Hjønnevåg
2012-03-06 1:04 ` [PATCH 2/2] PM / Sleep: Add wakeup_source_activate and wakeup_source_deactivate tracepoints Arve Hjønnevåg
2012-02-21 23:35 ` [RFC][PATCH 5/7] PM / Sleep: Implement opportunistic sleep Rafael J. Wysocki
2012-02-22 8:45 ` Srivatsa S. Bhat
2012-02-22 22:10 ` Rafael J. Wysocki
2012-02-23 5:35 ` Srivatsa S. Bhat
2012-02-21 23:36 ` [RFC][PATCH 6/7] PM / Sleep: Add "prevent autosleep time" statistics to wakeup sources Rafael J. Wysocki
2012-02-21 23:37 ` [RFC][PATCH 7/7] PM / Sleep: Add user space interface for manipulating " Rafael J. Wysocki
2012-02-22 4:49 ` [RFC][PATCH 0/7] PM: Implement autosleep and "wake locks", take 2 John Stultz
2012-02-22 8:44 ` Srivatsa S. Bhat
2012-02-22 22:10 ` [RFC][PATCH 0/7] PM: Implement autosleep and "wake locks", take2 Rafael J. Wysocki
2012-02-23 6:25 ` Srivatsa S. Bhat
2012-02-23 21:26 ` Rafael J. Wysocki
2012-02-23 21:32 ` Rafael J. Wysocki
2012-02-24 4:44 ` Srivatsa S. Bhat
2012-02-24 23:21 ` Rafael J. Wysocki
2012-02-25 4:43 ` Arve Hjønnevåg
2012-02-25 20:43 ` Rafael J. Wysocki
2012-02-25 19:20 ` Srivatsa S. Bhat
2012-02-25 21:01 ` Rafael J. Wysocki
2012-02-28 10:24 ` Srivatsa S. Bhat
2012-04-22 21:19 ` [RFC][PATCH 0/8] PM: Implement autosleep and "wake locks", take 3 Rafael J. Wysocki
2012-04-22 21:19 ` [PATCH 1/8] PM / Sleep: Look for wakeup events in later stages of device suspend Rafael J. Wysocki
2012-04-22 21:20 ` [PATCH 2/8] PM / Sleep: Use wait queue to signal "no wakeup events in progress" Rafael J. Wysocki
2012-04-23 4:01 ` mark gross
2012-04-22 21:21 ` [PATCH 3/8] PM / Sleep: Change wakeup source statistics to follow Android Rafael J. Wysocki
2012-04-22 21:21 ` [PATCH 4/8] PM / Sleep: Add wakeup_source_activate and wakeup_source_deactivate tracepoints Rafael J. Wysocki
2012-04-22 21:22 ` [RFC][PATCH 5/8] epoll: Add a flag, EPOLLWAKEUP, to prevent suspend while epoll events are ready Rafael J. Wysocki
2012-04-26 4:03 ` NeilBrown
2012-04-26 20:40 ` Rafael J. Wysocki
2012-04-27 3:49 ` Arve Hjønnevåg
2012-04-27 21:18 ` Rafael J. Wysocki
2012-04-27 23:26 ` [PATCH] " Arve Hjønnevåg
2012-04-30 1:58 ` [RFC][PATCH 5/8] " NeilBrown
2012-05-01 0:52 ` Arve Hjønnevåg
2012-05-01 2:18 ` NeilBrown
2012-05-01 5:33 ` Arve Hjønnevåg [this message]
2012-05-01 6:28 ` [PATCH] " NeilBrown
2012-05-01 13:51 ` Rafael J. Wysocki
2012-07-16 6:38 ` Michael Kerrisk
2012-07-16 11:00 ` Rafael J. Wysocki
2012-07-16 22:04 ` Arve Hjønnevåg
2012-07-17 5:14 ` Michael Kerrisk
2012-07-17 19:22 ` Rafael J. Wysocki
2012-07-17 19:36 ` Greg KH
2012-07-17 19:55 ` Rafael J. Wysocki
2012-07-18 6:41 ` Michael Kerrisk (man-pages)
2012-04-22 21:23 ` [RFC][PATCH 6/8] PM / Sleep: Implement opportunistic sleep Rafael J. Wysocki
2012-04-26 3:05 ` NeilBrown
2012-04-26 21:52 ` Rafael J. Wysocki
2012-04-27 0:39 ` NeilBrown
2012-04-27 21:22 ` Rafael J. Wysocki
2012-05-03 0:23 ` Arve Hjønnevåg
2012-05-03 13:28 ` Rafael J. Wysocki
2012-05-03 21:27 ` Arve Hjønnevåg
2012-05-03 22:20 ` Rafael J. Wysocki
2012-05-03 22:16 ` Arve Hjønnevåg
2012-05-03 22:24 ` Rafael J. Wysocki
2012-04-22 21:24 ` [RFC][PATCH 7/8] PM / Sleep: Add "prevent autosleep time" statistics to wakeup sources Rafael J. Wysocki
2012-04-22 21:24 ` [RFC][PATCH 8/8] PM / Sleep: Add user space interface for manipulating " Rafael J. Wysocki
2012-04-24 1:35 ` John Stultz
2012-04-24 21:27 ` Rafael J. Wysocki
2012-04-26 6:31 ` NeilBrown
2012-04-26 22:04 ` Rafael J. Wysocki
2012-04-27 0:07 ` NeilBrown
2012-04-27 21:15 ` Rafael J. Wysocki
2012-04-27 3:57 ` Arve Hjønnevåg
2012-04-27 21:14 ` Rafael J. Wysocki
2012-04-27 21:17 ` Arve Hjønnevåg
2012-04-27 21:34 ` Rafael J. Wysocki
2012-05-03 19:29 ` [PATCH 0/2]: Kconfig options for wakelocks limit and gc (was: Re: [RFC][PATCH 8/8] PM / Sleep: Add user space ...) Rafael J. Wysocki
2012-05-03 19:30 ` [PATCH 1/2] PM / Sleep: Make the limit of user space wakeup sources configurable Rafael J. Wysocki
2012-05-03 19:34 ` [PATCH 2/2] PM / Sleep: User space wakeup sources garbage collector Kconfig option Rafael J. Wysocki
2012-05-03 22:14 ` [PATCH 0/2]: Kconfig options for wakelocks limit and gc (was: Re: [RFC][PATCH 8/8] PM / Sleep: Add user space ...) Arve Hjønnevåg
2012-05-03 22:20 ` Rafael J. Wysocki
2012-04-23 16:49 ` [RFC][PATCH 0/8] PM: Implement autosleep and "wake locks", take 3 Greg KH
2012-04-23 19:51 ` Rafael J. Wysocki
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=1335850428-30883-1-git-send-email-arve@android.com \
--to=arve@android.com \
--cc=dmitry.torokhov@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=john.stultz@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=magnus.damm@gmail.com \
--cc=markgross@thegnar.org \
--cc=mjg@redhat.com \
--cc=neilb@suse.de \
--cc=rjw@sisk.pl \
--cc=srivatsa.bhat@linux.vnet.ibm.com \
--cc=stern@rowland.harvard.edu \
--cc=swetland@google.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).