From: Boaz Harrosh <bharrosh@panasas.com>
To: andros@netapp.com
Cc: benny@panasas.com, linux-nfs@vger.kernel.org
Subject: Re: [PATCH 4/5] SQUASHME pnfs-submit embed pnfs_layout_type
Date: Wed, 30 Jun 2010 13:02:27 +0300 [thread overview]
Message-ID: <4C2B1633.4090909@panasas.com> (raw)
In-Reply-To: <1277829737-5465-5-git-send-email-andros@netapp.com>
On 06/29/2010 07:42 PM, andros@netapp.com wrote:
> From: Andy Adamson <andros@netapp.com>
>
> Each layoutdriver embeds the pnfs_layout_type in it's private layout cache
> head structure, and allocates them both with the alloc_layout
> layoutdriver_io_operation.
>
> Move all nfs inode pnfs field initialization into nfs4_init_once.
>
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
> fs/nfs/callback_proc.c | 2 +-
> fs/nfs/inode.c | 43 ++++---------------------
> fs/nfs/nfs4proc.c | 2 +-
> fs/nfs/nfs4state.c | 4 +-
> fs/nfs/nfs4xdr.c | 2 +-
> fs/nfs/pnfs.c | 78 +++++++++++++++++++++++++--------------------
> include/linux/nfs4_pnfs.h | 14 ++------
> include/linux/nfs_fs.h | 4 +-
> 8 files changed, 61 insertions(+), 88 deletions(-)
>
> diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
> index 4766695..d999ea8 100644
> --- a/fs/nfs/callback_proc.c
> +++ b/fs/nfs/callback_proc.c
> @@ -233,7 +233,7 @@ static int pnfs_recall_layout(void *data)
> rl.cbl_seg.length = NFS4_MAX_UINT64;
>
> if (rl.cbl_recall_type == RETURN_FILE) {
> - if (pnfs_is_next_layout_stateid(&NFS_I(inode)->layout,
> + if (pnfs_is_next_layout_stateid(NFS_I(inode)->layout,
> rl.cbl_stateid))
> status = pnfs_return_layout(inode, &rl.cbl_seg,
> &rl.cbl_stateid, RETURN_FILE,
> diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
> index cb12d33..c290806 100644
> --- a/fs/nfs/inode.c
> +++ b/fs/nfs/inode.c
> @@ -1361,17 +1361,6 @@ void nfs4_clear_inode(struct inode *inode)
> }
> #endif
>
> -static void pnfs_alloc_init_inode(struct nfs_inode *nfsi)
> -{
> -#ifdef CONFIG_NFS_V4_1
> - memset(&nfsi->layout.stateid, 0, NFS4_STATEID_SIZE);
> - nfsi->layout.roc_iomode = 0;
> - nfsi->layout.lo_cred = NULL;
> - nfsi->layout.pnfs_write_begin_pos = 0;
> - nfsi->layout.pnfs_write_end_pos = 0;
> -#endif /* CONFIG_NFS_V4_1 */
> -}
> -
> struct inode *nfs_alloc_inode(struct super_block *sb)
> {
> struct nfs_inode *nfsi;
> @@ -1387,23 +1376,14 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
> #ifdef CONFIG_NFS_V4
> nfsi->nfs4_acl = NULL;
> #endif /* CONFIG_NFS_V4 */
> - pnfs_alloc_init_inode(nfsi);
> return &nfsi->vfs_inode;
> }
>
> static void pnfs_destroy_inode(struct nfs_inode *nfsi)
> {
> #ifdef CONFIG_NFS_V4_1
> - if (!list_empty(&nfsi->layout.segs))
> + if (has_layout(nfsi))
> pnfs_destroy_layout(nfsi);
> -
> - WARN_ON(!list_empty(&nfsi->layout.segs));
> - if (nfsi->layout.refcount)
> - printk("%s: WARNING: layout.refcount %d\n", __func__,
> - nfsi->layout.refcount);
> - WARN_ON(nfsi->layout.refcount);
> - WARN_ON(!list_empty(&nfsi->layout.lo_layouts));
Andy, these problems did not go away with this patch. Please re-instate
them for the new code. All 3 WARN_ONs still apply. Perhaps in pnfs_destroy_layout()
> - WARN_ON(nfsi->layout.ld_data);
> #endif /* CONFIG_NFS_V4_1 */
> }
>
> @@ -1415,20 +1395,6 @@ void nfs_destroy_inode(struct inode *inode)
> kmem_cache_free(nfs_inode_cachep, nfsi);
> }
>
> -static void pnfs_init_once(struct nfs_inode *nfsi)
> -{
> -#ifdef CONFIG_NFS_V4_1
> - init_waitqueue_head(&nfsi->lo_waitq);
> - nfsi->pnfs_layout_state = 0;
> - nfsi->pnfs_layout_suspend = 0;
> - seqlock_init(&nfsi->layout.seqlock);
> - INIT_LIST_HEAD(&nfsi->layout.lo_layouts);
> - INIT_LIST_HEAD(&nfsi->layout.segs);
> - nfsi->layout.refcount = 0;
> - nfsi->layout.ld_data = NULL;
> -#endif /* CONFIG_NFS_V4_1 */
> -}
> -
> static inline void nfs4_init_once(struct nfs_inode *nfsi)
> {
> #ifdef CONFIG_NFS_V4
> @@ -1436,6 +1402,12 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
> nfsi->delegation = NULL;
> nfsi->delegation_state = 0;
> init_rwsem(&nfsi->rwsem);
> +#ifdef CONFIG_NFS_V4_1
> + init_waitqueue_head(&nfsi->lo_waitq);
> + nfsi->layout = NULL;
> + nfsi->pnfs_layout_state = 0;
> + nfsi->pnfs_layout_suspend = 0;
> +#endif /* CONFIG_NFS_V4_1 */
> #endif
> }
>
> @@ -1454,7 +1426,6 @@ static void init_once(void *foo)
> INIT_HLIST_HEAD(&nfsi->silly_list);
> init_waitqueue_head(&nfsi->waitqueue);
> nfs4_init_once(nfsi);
> - pnfs_init_once(nfsi);
> }
>
> static int __init nfs_init_inodecache(void)
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 6283996..61f4aa9 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -1086,7 +1086,7 @@ static void pnfs4_layout_reclaim(struct nfs4_state *state)
> * flag during grace period
> */
> pnfs_destroy_layout(NFS_I(state->inode));
> - pnfs_set_layout_stateid(&NFS_I(state->inode)->layout, &zero_stateid);
> + pnfs_set_layout_stateid(NFS_I(state->inode)->layout, &zero_stateid);
> #endif /* CONFIG_NFS_V4_1 */
> }
>
> diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
> index bfe679b..6f44cb0 100644
> --- a/fs/nfs/nfs4state.c
> +++ b/fs/nfs/nfs4state.c
> @@ -597,10 +597,10 @@ static void __nfs4_close(struct path *path, struct nfs4_state *state,
> #ifdef CONFIG_NFS_V4_1
> struct nfs_inode *nfsi = NFS_I(state->inode);
>
> - if (has_layout(nfsi) && nfsi->layout.roc_iomode) {
> + if (has_layout(nfsi) && nfsi->layout->roc_iomode) {
> struct nfs4_pnfs_layout_segment range;
>
> - range.iomode = nfsi->layout.roc_iomode;
> + range.iomode = nfsi->layout->roc_iomode;
> range.offset = 0;
> range.length = NFS4_MAX_UINT64;
> pnfs_return_layout(state->inode, &range, NULL,
> diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
> index eeee855..0fd02b1 100644
> --- a/fs/nfs/nfs4xdr.c
> +++ b/fs/nfs/nfs4xdr.c
> @@ -1886,7 +1886,7 @@ encode_layoutreturn(struct xdr_stream *xdr,
> ld_io_ops->encode_layoutreturn);
> if (ld_io_ops->encode_layoutreturn) {
> ld_io_ops->encode_layoutreturn(
> - &NFS_I(args->inode)->layout, xdr, args);
> + NFS_I(args->inode)->layout, xdr, args);
> } else {
> p = reserve_space(xdr, 4);
> *p = cpu_to_be32(0);
> diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
> index 7f6ace2..9275140 100644
> --- a/fs/nfs/pnfs.c
> +++ b/fs/nfs/pnfs.c
> @@ -153,7 +153,7 @@ pnfs_need_layoutcommit(struct nfs_inode *nfsi, struct nfs_open_context *ctx)
> dprintk("%s: has_layout=%d ctx=%p\n", __func__, has_layout(nfsi), ctx);
> spin_lock(&nfsi->vfs_inode.i_lock);
> if (has_layout(nfsi) && !layoutcommit_needed(nfsi)) {
> - nfsi->layout.lo_cred = get_rpccred(ctx->state->owner->so_cred);
> + nfsi->layout->lo_cred = get_rpccred(ctx->state->owner->so_cred);
> __set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->pnfs_layout_state);
> nfsi->change_attr++;
> spin_unlock(&nfsi->vfs_inode.i_lock);
> @@ -174,17 +174,17 @@ pnfs_update_last_write(struct nfs_inode *nfsi, loff_t offset, size_t extent)
> loff_t end_pos;
>
> spin_lock(&nfsi->vfs_inode.i_lock);
> - if (offset < nfsi->layout.pnfs_write_begin_pos)
> - nfsi->layout.pnfs_write_begin_pos = offset;
> + if (offset < nfsi->layout->pnfs_write_begin_pos)
> + nfsi->layout->pnfs_write_begin_pos = offset;
> end_pos = offset + extent - 1; /* I'm being inclusive */
> - if (end_pos > nfsi->layout.pnfs_write_end_pos)
> - nfsi->layout.pnfs_write_end_pos = end_pos;
> + if (end_pos > nfsi->layout->pnfs_write_end_pos)
> + nfsi->layout->pnfs_write_end_pos = end_pos;
> dprintk("%s: Wrote %lu@%lu bpos %lu, epos: %lu\n",
> __func__,
> (unsigned long) extent,
> (unsigned long) offset ,
> - (unsigned long) nfsi->layout.pnfs_write_begin_pos,
> - (unsigned long) nfsi->layout.pnfs_write_end_pos);
> + (unsigned long) nfsi->layout->pnfs_write_begin_pos,
> + (unsigned long) nfsi->layout->pnfs_write_end_pos);
> spin_unlock(&nfsi->vfs_inode.i_lock);
> }
>
> @@ -325,10 +325,9 @@ get_layout(struct pnfs_layout_type *lo)
> static inline struct pnfs_layout_type *
> grab_current_layout(struct nfs_inode *nfsi)
> {
> - struct pnfs_layout_type *lo = &nfsi->layout;
> + struct pnfs_layout_type *lo = nfsi->layout;
>
> - BUG_ON_UNLOCKED_LO(lo);
Why did you drop this one?
> - if (!lo->ld_data)
> + if (!lo)
> return NULL;
> get_layout(lo);
> return lo;
> @@ -342,13 +341,13 @@ put_layout(struct pnfs_layout_type *lo)
>
> lo->refcount--;
> if (!lo->refcount) {
> - struct layoutdriver_io_operations *io_ops =
> - PNFS_LD_IO_OPS(lo);
> + struct layoutdriver_io_operations *io_ops = PNFS_LD_IO_OPS(lo);
> + struct nfs_inode *nfsi = PNFS_NFS_INODE(lo);
>
> - dprintk("%s: freeing layout %p\n", __func__, lo->ld_data);
> + dprintk("%s: freeing layout cache %p\n", __func__, lo);
> WARN_ON(!list_empty(&lo->lo_layouts));
> - io_ops->free_layout(lo->ld_data);
> - lo->ld_data = NULL;
> + io_ops->free_layout(lo);
> + nfsi->layout = NULL;
> }
> }
>
> @@ -688,7 +687,7 @@ pnfs_return_layout_barrier(struct nfs_inode *nfsi,
> bool ret = false;
>
> spin_lock(&nfsi->vfs_inode.i_lock);
> - list_for_each_entry (lseg, &nfsi->layout.segs, fi_list) {
> + list_for_each_entry(lseg, &nfsi->layout->segs, fi_list) {
White space cleanup. actually I like the space. I thought checkpatch
was fixed to accept these spaces?
> if (!should_free_lseg(lseg, range))
> continue;
> lseg->valid = false;
> @@ -894,17 +893,20 @@ pnfs_insert_layout(struct pnfs_layout_type *lo,
> dprintk("%s:Return\n", __func__);
> }
>
> +/*
> + * Each layoutdriver embeds pnfs_layout_type in it's per-layout type layout
> + * cache structure. Initialize the common pnfs_layout_type fields.
> + */
> static struct pnfs_layout_type *
> alloc_init_layout(struct inode *ino)
> {
> - void *ld_data;
> struct pnfs_layout_type *lo;
> struct layoutdriver_io_operations *io_ops;
>
> io_ops = NFS_SERVER(ino)->pnfs_curr_ld->ld_io_ops;
> - lo = &NFS_I(ino)->layout;
> - ld_data = io_ops->alloc_layout(ino);
> - if (!ld_data) {
> + lo = NFS_I(ino)->layout;
> + lo = io_ops->alloc_layout(ino);
Oops, ;-)
> + if (!lo) {
> printk(KERN_ERR
> "%s: out of memory: io_ops->alloc_layout failed\n",
> __func__);
> @@ -912,11 +914,17 @@ alloc_init_layout(struct inode *ino)
> }
>
> spin_lock(&ino->i_lock);
> - BUG_ON(lo->ld_data != NULL);
You could still do a BUG_ON(nfsi->layout) above before the io_ops->alloc_layout(ino)
call.
> - lo->ld_data = ld_data;
> - memset(&lo->stateid, 0, NFS4_STATEID_SIZE);
> lo->refcount = 1;
> + INIT_LIST_HEAD(&lo->lo_layouts);
> + INIT_LIST_HEAD(&lo->segs);
> lo->roc_iomode = 0;
> + seqlock_init(&lo->seqlock);
All these below, I'd drop. The comment above io_ops->alloc_layout should
say that it must return a ZEROed out structure, which it is in your
files-layout patch.
> + memset(&lo->stateid, 0, NFS4_STATEID_SIZE);
> + lo->lo_cred = NULL;
> + lo->pnfs_write_begin_pos = 0;
> + lo->pnfs_write_end_pos = 0;
> + lo->lo_inode = ino;
> + NFS_I(ino)->layout = lo;
> spin_unlock(&ino->i_lock);
Just as a note:
A pointer/word atomic inspection theory is based on the fact that the set is
done with a memory barrier. Same as the test/set_bit operations. So here
the spin_unlock provides that for us, naturally. (*Not* that the inode state will
really need it, because no one will actually care before the allocation is done)
> return lo;
> }
> @@ -962,7 +970,7 @@ get_lock_alloc_layout(struct inode *ino)
> /* Was current_layout already allocated while we slept?
> * If so, retry get_lock'ing it. Otherwise, allocate it.
> */
> - if (nfsi->layout.ld_data) {
> + if (nfsi->layout) {
> spin_lock(&ino->i_lock);
> continue;
> }
> @@ -1312,7 +1320,7 @@ pnfs_set_pg_test(struct inode *inode, struct nfs_pageio_descriptor *pgio)
>
> pgio->pg_test = NULL;
>
> - laytype = &NFS_I(inode)->layout;
> + laytype = NFS_I(inode)->layout;
> ld = NFS_SERVER(inode)->pnfs_curr_ld;
> if (!pnfs_enabled_sb(NFS_SERVER(inode)) || !laytype)
> return;
> @@ -1445,7 +1453,7 @@ pnfs_writepages(struct nfs_write_data *wdata, int how)
> numpages);
> wdata->pdata.lseg = lseg;
> trypnfs = nfss->pnfs_curr_ld->ld_io_ops->write_pagelist(
> - &nfsi->layout,
> + nfsi->layout,
> args->pages,
> args->pgbase,
> numpages,
> @@ -1498,7 +1506,7 @@ pnfs_readpages(struct nfs_read_data *rdata)
> __func__, numpages);
> rdata->pdata.lseg = lseg;
> trypnfs = nfss->pnfs_curr_ld->ld_io_ops->read_pagelist(
> - &nfsi->layout,
> + nfsi->layout,
> args->pages,
> args->pgbase,
> numpages,
> @@ -1559,7 +1567,7 @@ pnfs_commit(struct nfs_write_data *data, int sync)
> * This will be done by passing the buck to the layout driver.
> */
> data->pdata.lseg = NULL;
> - trypnfs = nfss->pnfs_curr_ld->ld_io_ops->commit(&nfsi->layout,
> + trypnfs = nfss->pnfs_curr_ld->ld_io_ops->commit(nfsi->layout,
> sync, data);
> dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
> return trypnfs;
> @@ -1630,14 +1638,14 @@ pnfs_layoutcommit_inode(struct inode *inode, int sync)
> /* Clear layoutcommit properties in the inode so
> * new lc info can be generated
> */
> - write_begin_pos = nfsi->layout.pnfs_write_begin_pos;
> - write_end_pos = nfsi->layout.pnfs_write_end_pos;
> - data->cred = nfsi->layout.lo_cred;
> - nfsi->layout.pnfs_write_begin_pos = 0;
> - nfsi->layout.pnfs_write_end_pos = 0;
> - nfsi->layout.lo_cred = NULL;
> + write_begin_pos = nfsi->layout->pnfs_write_begin_pos;
> + write_end_pos = nfsi->layout->pnfs_write_end_pos;
> + data->cred = nfsi->layout->lo_cred;
> + nfsi->layout->pnfs_write_begin_pos = 0;
> + nfsi->layout->pnfs_write_end_pos = 0;
> + nfsi->layout->lo_cred = NULL;
> __clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->pnfs_layout_state);
> - pnfs_get_layout_stateid(&data->args.stateid, &nfsi->layout);
> + pnfs_get_layout_stateid(&data->args.stateid, nfsi->layout);
>
> spin_unlock(&inode->i_lock);
>
> diff --git a/include/linux/nfs4_pnfs.h b/include/linux/nfs4_pnfs.h
> index 4d9b15c..6e46589 100644
> --- a/include/linux/nfs4_pnfs.h
> +++ b/include/linux/nfs4_pnfs.h
> @@ -35,13 +35,13 @@ struct pnfs_layoutdriver_type {
> static inline struct nfs_inode *
> PNFS_NFS_INODE(struct pnfs_layout_type *lo)
> {
> - return container_of(lo, struct nfs_inode, layout);
> + return NFS_I(lo->lo_inode);
> }
>
> static inline struct inode *
> PNFS_INODE(struct pnfs_layout_type *lo)
> {
> - return &PNFS_NFS_INODE(lo)->vfs_inode;
> + return lo->lo_inode;
> }
>
> static inline struct nfs_server *
> @@ -50,12 +50,6 @@ PNFS_NFS_SERVER(struct pnfs_layout_type *lo)
> return NFS_SERVER(PNFS_INODE(lo));
> }
>
> -static inline void *
> -PNFS_LD_DATA(struct pnfs_layout_type *lo)
> -{
> - return lo->ld_data;
> -}
> -
> static inline struct pnfs_layoutdriver_type *
> PNFS_LD(struct pnfs_layout_type *lo)
> {
> @@ -77,7 +71,7 @@ PNFS_LD_POLICY_OPS(struct pnfs_layout_type *lo)
> static inline bool
> has_layout(struct nfs_inode *nfsi)
> {
> - return nfsi->layout.ld_data != NULL;
> + return nfsi->layout != NULL;
> }
>
> static inline bool
> @@ -149,7 +143,7 @@ struct layoutdriver_io_operations {
> /* Layout information. For each inode, alloc_layout is executed once to retrieve an
> * inode specific layout structure. Each subsequent layoutget operation results in
> * a set_layout call to set the opaque layout in the layout driver.*/
> - void * (*alloc_layout) (struct inode *inode);
> + struct pnfs_layout_type * (*alloc_layout) (struct inode *inode);
> void (*free_layout) (void *layoutid);
> struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_type *layoutid, struct nfs4_pnfs_layoutget_res *lgr);
> void (*free_lseg) (struct pnfs_layout_segment *lseg);
> diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
> index cebc958..43d516e 100644
> --- a/include/linux/nfs_fs.h
> +++ b/include/linux/nfs_fs.h
> @@ -104,13 +104,13 @@ struct pnfs_layout_type {
> int roc_iomode; /* iomode to return on close, 0=none */
> seqlock_t seqlock; /* Protects the stateid */
> nfs4_stateid stateid;
> - void *ld_data; /* layout driver private data */
> struct rpc_cred *lo_cred; /* layoutcommit credential */
> /* DH: These vars keep track of the maximum write range
> * so the values can be used for layoutcommit.
> */
> loff_t pnfs_write_begin_pos;
> loff_t pnfs_write_end_pos;
> + struct inode *lo_inode;
> };
>
> /*
> @@ -201,7 +201,7 @@ struct nfs_inode {
> /* pNFS layout information */
> #if defined(CONFIG_NFS_V4_1)
> wait_queue_head_t lo_waitq;
> - struct pnfs_layout_type layout;
> + struct pnfs_layout_type *layout;
> unsigned long pnfs_layout_state;
> #define NFS_INO_RO_LAYOUT_FAILED 0 /* ro LAYOUTGET failed stop trying */
> #define NFS_INO_RW_LAYOUT_FAILED 1 /* rw LAYOUTGET failed stop trying */
Boaz
next prev parent reply other threads:[~2010-06-30 10:02 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-29 16:42 [PATCH 0/5] pnfs-submit: embed pnfs_layout_type in per layout structure andros
2010-06-29 16:42 ` [PATCH 1/5] SQUASHME pnfs-submit: add state flag for layoutcommit_needed andros
2010-06-29 16:42 ` [PATCH 2/5] SQUASHME: pnfs_submit: move pnfs_layout_state back to nfs_inode andros
2010-06-29 16:42 ` [PATCH 3/5] SQUASHME: pnfs-submit: move pnfs_layout_suspend " andros
2010-06-29 16:42 ` [PATCH 4/5] SQUASHME pnfs-submit embed pnfs_layout_type andros
2010-06-29 16:42 ` [PATCH 5/5] SQUASHME pnfs-submit: filelayout: use new alloc_layout API andros
2010-06-30 9:06 ` Boaz Harrosh
2010-06-30 13:42 ` Andy Adamson
2010-06-30 10:02 ` Boaz Harrosh [this message]
2010-06-30 19:43 ` [PATCH 4/5] SQUASHME pnfs-submit embed pnfs_layout_type Andy Adamson
2010-06-30 14:49 ` [PATCH 3/5] SQUASHME: pnfs-submit: move pnfs_layout_suspend back to nfs_inode Boaz Harrosh
2010-06-30 15:13 ` Andy Adamson
2010-06-30 15:56 ` Boaz Harrosh
2010-06-30 16:38 ` Andy Adamson
2010-06-30 17:17 ` Boaz Harrosh
2010-06-30 9:05 ` [PATCH 2/5] SQUASHME: pnfs_submit: move pnfs_layout_state " Boaz Harrosh
2010-06-30 9:31 ` Boaz Harrosh
2010-06-30 13:48 ` Fred Isaman
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=4C2B1633.4090909@panasas.com \
--to=bharrosh@panasas.com \
--cc=andros@netapp.com \
--cc=benny@panasas.com \
--cc=linux-nfs@vger.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 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).