2016-08-28 22:25:03

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 0/5] Fix callback channel handling of referring triples

RFC5661 has a mechanism for ensuring that the forward channel and backward
channel do not race. The Linux client implements this mechanism, but in
a manner that is racy, making it rather pointless, and buggy (Oops!).

This patch series fixes the most egregious issues around delegations and
layouts by ensuring that we wait for completion of the actual setup of
the delegation or layout that could be subject to recall.

Trond Myklebust (5):
NFSv4.1: Fix Oopsable condition in server callback races
NFSv4.1: Delay callback processing when there are referring triples
NFSv4.1: Defer bumping the slot sequence number until we free the slot
NFSv4.1: Close callback races for OPEN, LAYOUTGET and LAYOUTRETURN
NFSv4.1: Remove obsolete and incorrrect assignment in
nfs4_callback_sequence

fs/nfs/callback_proc.c | 8 ++---
fs/nfs/nfs4proc.c | 89 +++++++++++++++++++++++++++++++++++++++++---------
fs/nfs/nfs4session.c | 53 ++++++++++++++++++++++++++++++
fs/nfs/nfs4session.h | 7 +++-
4 files changed, 135 insertions(+), 22 deletions(-)

--
2.7.4



2016-08-28 22:25:04

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 1/5] NFSv4.1: Fix Oopsable condition in server callback races

The slot table hasn't been an array since v3.7. Ensure that we
use nfs4_lookup_slot() to access the slot correctly.

Fixes: 87dda67e7386 ("NFSv4.1: Allow SEQUENCE to resize the slot table...")
Signed-off-by: Trond Myklebust <[email protected]>
Cc: [email protected] # v3.8+
---
fs/nfs/callback_proc.c | 5 +----
fs/nfs/nfs4session.c | 33 +++++++++++++++++++++++++++++++++
fs/nfs/nfs4session.h | 1 +
3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index c92a75e066a6..a4cf6d2c14a4 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -454,11 +454,8 @@ static bool referring_call_exists(struct nfs_client *clp,
((u32 *)&rclist->rcl_sessionid.data)[3],
ref->rc_sequenceid, ref->rc_slotid);

- spin_lock(&tbl->slot_tbl_lock);
- status = (test_bit(ref->rc_slotid, tbl->used_slots) &&
- tbl->slots[ref->rc_slotid].seq_nr ==
+ status = nfs4_slot_seqid_in_use(tbl, ref->rc_slotid,
ref->rc_sequenceid);
- spin_unlock(&tbl->slot_tbl_lock);
if (status)
goto out;
}
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c
index 332d06e64fa9..c1f4c208f38a 100644
--- a/fs/nfs/nfs4session.c
+++ b/fs/nfs/nfs4session.c
@@ -172,6 +172,39 @@ struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid)
return ERR_PTR(-E2BIG);
}

+static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid,
+ u32 *seq_nr)
+ __must_hold(&tbl->slot_tbl_lock)
+{
+ struct nfs4_slot *slot;
+
+ slot = nfs4_lookup_slot(tbl, slotid);
+ if (IS_ERR(slot))
+ return PTR_ERR(slot);
+ *seq_nr = slot->seq_nr;
+ return 0;
+}
+
+/*
+ * nfs4_slot_seqid_in_use - test if a slot sequence id is still in use
+ *
+ * Given a slot table, slot id and sequence number, determine if the
+ * RPC call in question is still in flight. This function is mainly
+ * intended for use by the callback channel.
+ */
+bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr)
+{
+ u32 cur_seq;
+ bool ret = false;
+
+ spin_lock(&tbl->slot_tbl_lock);
+ if (nfs4_slot_get_seqid(tbl, slotid, &cur_seq) == 0 &&
+ cur_seq == seq_nr && test_bit(slotid, tbl->used_slots))
+ ret = true;
+ spin_unlock(&tbl->slot_tbl_lock);
+ return ret;
+}
+
/*
* nfs4_alloc_slot - efficiently look for a free slot
*
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index 5b51298d1d03..33cace62b50b 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -78,6 +78,7 @@ extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
extern struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid);
+extern bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr);
extern bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
--
2.7.4


2016-08-28 22:25:05

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 2/5] NFSv4.1: Delay callback processing when there are referring triples

If CB_SEQUENCE tells us that the processing of this request depends on
the completion of one or more referring triples (see RFC 5661 Section
2.10.6.3), delay the callback processing until after the RPC requests
being referred to have completed.
If we end up delaying for more than 1/2 second, then fall back to
returning NFS4ERR_DELAY in reply to the callback.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/callback_proc.c | 4 ++--
fs/nfs/nfs4proc.c | 2 ++
fs/nfs/nfs4session.c | 22 +++++++++++++++++++++-
fs/nfs/nfs4session.h | 5 ++++-
4 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index a4cf6d2c14a4..c35932967722 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -454,8 +454,8 @@ static bool referring_call_exists(struct nfs_client *clp,
((u32 *)&rclist->rcl_sessionid.data)[3],
ref->rc_sequenceid, ref->rc_slotid);

- status = nfs4_slot_seqid_in_use(tbl, ref->rc_slotid,
- ref->rc_sequenceid);
+ status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
+ ref->rc_sequenceid, HZ >> 1) < 0;
if (status)
goto out;
}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1949bbd806eb..0cc0c319cfdd 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -686,6 +686,8 @@ out_unlock:
res->sr_slot = NULL;
if (send_new_highest_used_slotid)
nfs41_notify_server(session->clp);
+ if (waitqueue_active(&tbl->slot_waitq))
+ wake_up_all(&tbl->slot_waitq);
}

int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c
index c1f4c208f38a..b62973045a3e 100644
--- a/fs/nfs/nfs4session.c
+++ b/fs/nfs/nfs4session.c
@@ -28,6 +28,7 @@ static void nfs4_init_slot_table(struct nfs4_slot_table *tbl, const char *queue)
tbl->highest_used_slotid = NFS4_NO_SLOT;
spin_lock_init(&tbl->slot_tbl_lock);
rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, queue);
+ init_waitqueue_head(&tbl->slot_waitq);
init_completion(&tbl->complete);
}

@@ -192,7 +193,8 @@ static int nfs4_slot_get_seqid(struct nfs4_slot_table *tbl, u32 slotid,
* RPC call in question is still in flight. This function is mainly
* intended for use by the callback channel.
*/
-bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr)
+static bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl,
+ u32 slotid, u32 seq_nr)
{
u32 cur_seq;
bool ret = false;
@@ -206,6 +208,24 @@ bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr)
}

/*
+ * nfs4_slot_wait_on_seqid - wait until a slot sequence id is complete
+ *
+ * Given a slot table, slot id and sequence number, wait until the
+ * corresponding RPC call completes. This function is mainly
+ * intended for use by the callback channel.
+ */
+int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
+ u32 slotid, u32 seq_nr,
+ unsigned long timeout)
+{
+ if (wait_event_timeout(tbl->slot_waitq,
+ !nfs4_slot_seqid_in_use(tbl, slotid, seq_nr),
+ timeout) == 0)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+/*
* nfs4_alloc_slot - efficiently look for a free slot
*
* nfs4_alloc_slot looks for an unset bit in the used_slots bitmap.
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index 33cace62b50b..fa75d7db3db3 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -36,6 +36,7 @@ struct nfs4_slot_table {
unsigned long used_slots[SLOT_TABLE_SZ]; /* used/unused bitmap */
spinlock_t slot_tbl_lock;
struct rpc_wait_queue slot_tbl_waitq; /* allocators may wait here */
+ wait_queue_head_t slot_waitq; /* Completion wait on slot */
u32 max_slots; /* # slots in table */
u32 max_slotid; /* Max allowed slotid value */
u32 highest_used_slotid; /* sent to server on each SEQ.
@@ -78,7 +79,9 @@ extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl,
extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl);
extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl);
extern struct nfs4_slot *nfs4_lookup_slot(struct nfs4_slot_table *tbl, u32 slotid);
-extern bool nfs4_slot_seqid_in_use(struct nfs4_slot_table *tbl, u32 slotid, u32 seq_nr);
+extern int nfs4_slot_wait_on_seqid(struct nfs4_slot_table *tbl,
+ u32 slotid, u32 seq_nr,
+ unsigned long timeout);
extern bool nfs4_try_to_lock_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot);
extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl);
--
2.7.4


2016-08-28 22:25:07

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 5/5] NFSv4.1: Remove obsolete and incorrrect assignment in nfs4_callback_sequence

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/callback_proc.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index c35932967722..f953ef6b2f2e 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -484,7 +484,6 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
goto out;

tbl = &clp->cl_session->bc_slot_table;
- slot = tbl->slots + args->csa_slotid;

/* Set up res before grabbing the spinlock */
memcpy(&res->csr_sessionid, &args->csa_sessionid,
--
2.7.4


2016-08-28 22:25:06

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 3/5] NFSv4.1: Defer bumping the slot sequence number until we free the slot

For operations like OPEN or LAYOUTGET, which return recallable state
(i.e. delegations and layouts) we want to enable the mechanism for
resolving recall races in RFC5661 Section 2.10.6.3.
To do so, we will want to defer bumping the slot's sequence number until
we have finished processing the RPC results.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/nfs4proc.c | 9 +++++++--
fs/nfs/nfs4session.h | 3 ++-
2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 0cc0c319cfdd..de4a89d3d740 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -666,6 +666,11 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
tbl = slot->table;
session = tbl->session;

+ /* Bump the slot sequence number */
+ if (slot->seq_done)
+ slot->seq_nr++;
+ slot->seq_done = 0;
+
spin_lock(&tbl->slot_tbl_lock);
/* Be nice to the server: try to ensure that the last transmitted
* value for highest_user_slotid <= target_highest_slotid
@@ -716,7 +721,7 @@ int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
switch (res->sr_status) {
case 0:
/* Update the slot's sequence and clientid lease timer */
- ++slot->seq_nr;
+ slot->seq_done = 1;
clp = session->clp;
do_renew_lease(clp, res->sr_timestamp);
/* Check sequence flags */
@@ -771,7 +776,7 @@ int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
goto retry_nowait;
default:
/* Just update the slot sequence no. */
- ++slot->seq_nr;
+ slot->seq_done = 1;
}
out:
/* The session may be reset by one of the error handlers. */
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index fa75d7db3db3..f703b755351b 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -21,7 +21,8 @@ struct nfs4_slot {
unsigned long generation;
u32 slot_nr;
u32 seq_nr;
- unsigned int interrupted : 1;
+ unsigned int interrupted : 1,
+ seq_done : 1;
};

/* Sessions */
--
2.7.4


2016-08-28 22:25:07

by Trond Myklebust

[permalink] [raw]
Subject: [PATCH 4/5] NFSv4.1: Close callback races for OPEN, LAYOUTGET and LAYOUTRETURN

Defer freeing the slot until after we have processed the results from
OPEN and LAYOUTGET. This means that the server can rely on the
mechanism in RFC5661 Section 2.10.6.3 to ensure that replies to an
OPEN or LAYOUTGET/RETURN RPC call don't race with the callbacks that
apply to them.

Signed-off-by: Trond Myklebust <[email protected]>
---
fs/nfs/nfs4proc.c | 78 +++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 65 insertions(+), 13 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index de4a89d3d740..f5aecaabcb7c 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -634,15 +634,11 @@ out_sleep:
}
EXPORT_SYMBOL_GPL(nfs40_setup_sequence);

-static int nfs40_sequence_done(struct rpc_task *task,
- struct nfs4_sequence_res *res)
+static void nfs40_sequence_free_slot(struct nfs4_sequence_res *res)
{
struct nfs4_slot *slot = res->sr_slot;
struct nfs4_slot_table *tbl;

- if (slot == NULL)
- goto out;
-
tbl = slot->table;
spin_lock(&tbl->slot_tbl_lock);
if (!nfs41_wake_and_assign_slot(tbl, slot))
@@ -650,7 +646,13 @@ static int nfs40_sequence_done(struct rpc_task *task,
spin_unlock(&tbl->slot_tbl_lock);

res->sr_slot = NULL;
-out:
+}
+
+static int nfs40_sequence_done(struct rpc_task *task,
+ struct nfs4_sequence_res *res)
+{
+ if (res->sr_slot != NULL)
+ nfs40_sequence_free_slot(res);
return 1;
}

@@ -695,7 +697,8 @@ out_unlock:
wake_up_all(&tbl->slot_waitq);
}

-int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
+static int nfs41_sequence_process(struct rpc_task *task,
+ struct nfs4_sequence_res *res)
{
struct nfs4_session *session;
struct nfs4_slot *slot = res->sr_slot;
@@ -781,11 +784,11 @@ int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
out:
/* The session may be reset by one of the error handlers. */
dprintk("%s: Error %d free the slot \n", __func__, res->sr_status);
- nfs41_sequence_free_slot(res);
out_noaction:
return ret;
retry_nowait:
if (rpc_restart_call_prepare(task)) {
+ nfs41_sequence_free_slot(res);
task->tk_status = 0;
ret = 0;
}
@@ -796,8 +799,37 @@ out_retry:
rpc_delay(task, NFS4_POLL_RETRY_MAX);
return 0;
}
+
+int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
+{
+ if (!nfs41_sequence_process(task, res))
+ return 0;
+ if (res->sr_slot != NULL)
+ nfs41_sequence_free_slot(res);
+ return 1;
+
+}
EXPORT_SYMBOL_GPL(nfs41_sequence_done);

+static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res)
+{
+ if (res->sr_slot == NULL)
+ return 1;
+ if (res->sr_slot->table->session != NULL)
+ return nfs41_sequence_process(task, res);
+ return nfs40_sequence_done(task, res);
+}
+
+static void nfs4_sequence_free_slot(struct nfs4_sequence_res *res)
+{
+ if (res->sr_slot != NULL) {
+ if (res->sr_slot->table->session != NULL)
+ nfs41_sequence_free_slot(res);
+ else
+ nfs40_sequence_free_slot(res);
+ }
+}
+
int nfs4_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
{
if (res->sr_slot == NULL)
@@ -927,6 +959,17 @@ static int nfs4_setup_sequence(const struct nfs_server *server,
args, res, task);
}

+static int nfs4_sequence_process(struct rpc_task *task, struct nfs4_sequence_res *res)
+{
+ return nfs40_sequence_done(task, res);
+}
+
+static void nfs4_sequence_free_slot(struct nfs4_sequence_res *res)
+{
+ if (res->sr_slot != NULL)
+ nfs40_sequence_free_slot(res);
+}
+
int nfs4_sequence_done(struct rpc_task *task,
struct nfs4_sequence_res *res)
{
@@ -1204,6 +1247,7 @@ static void nfs4_opendata_free(struct kref *kref)
struct super_block *sb = p->dentry->d_sb;

nfs_free_seqid(p->o_arg.seqid);
+ nfs4_sequence_free_slot(&p->o_res.seq_res);
if (p->state != NULL)
nfs4_put_open_state(p->state);
nfs4_put_state_owner(p->owner);
@@ -1663,9 +1707,14 @@ err:
static struct nfs4_state *
nfs4_opendata_to_nfs4_state(struct nfs4_opendata *data)
{
+ struct nfs4_state *ret;
+
if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS)
- return _nfs4_opendata_reclaim_to_nfs4_state(data);
- return _nfs4_opendata_to_nfs4_state(data);
+ ret =_nfs4_opendata_reclaim_to_nfs4_state(data);
+ else
+ ret = _nfs4_opendata_to_nfs4_state(data);
+ nfs4_sequence_free_slot(&data->o_res.seq_res);
+ return ret;
}

static struct nfs_open_context *nfs4_state_find_open_context(struct nfs4_state *state)
@@ -2063,7 +2112,7 @@ static void nfs4_open_done(struct rpc_task *task, void *calldata)

data->rpc_status = task->tk_status;

- if (!nfs4_sequence_done(task, &data->o_res.seq_res))
+ if (!nfs4_sequence_process(task, &data->o_res.seq_res))
return;

if (task->tk_status == 0) {
@@ -7871,7 +7920,7 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
struct nfs4_layoutget *lgp = calldata;

dprintk("--> %s\n", __func__);
- nfs41_sequence_done(task, &lgp->res.seq_res);
+ nfs41_sequence_process(task, &lgp->res.seq_res);
dprintk("<-- %s\n", __func__);
}

@@ -8087,6 +8136,7 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
if (status == 0 && lgp->res.layoutp->len)
lseg = pnfs_layout_process(lgp);
+ nfs4_sequence_free_slot(&lgp->res.seq_res);
rpc_put_task(task);
dprintk("<-- %s status=%d\n", __func__, status);
if (status)
@@ -8113,7 +8163,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)

dprintk("--> %s\n", __func__);

- if (!nfs41_sequence_done(task, &lrp->res.seq_res))
+ if (!nfs41_sequence_process(task, &lrp->res.seq_res))
return;

server = NFS_SERVER(lrp->args.inode);
@@ -8125,6 +8175,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
case -NFS4ERR_DELAY:
if (nfs4_async_handle_error(task, server, NULL, NULL) != -EAGAIN)
break;
+ nfs4_sequence_free_slot(&lrp->res.seq_res);
rpc_restart_call_prepare(task);
return;
}
@@ -8145,6 +8196,7 @@ static void nfs4_layoutreturn_release(void *calldata)
pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
pnfs_clear_layoutreturn_waitbit(lo);
spin_unlock(&lo->plh_inode->i_lock);
+ nfs4_sequence_free_slot(&lrp->res.seq_res);
pnfs_free_lseg_list(&freeme);
pnfs_put_layout_hdr(lrp->args.layout);
nfs_iput_and_deactive(lrp->inode);
--
2.7.4


2016-09-06 18:14:55

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 0/5] Fix callback channel handling of referring triples

On Sun, Aug 28, 2016 at 06:21:00PM -0400, Trond Myklebust wrote:
> RFC5661 has a mechanism for ensuring that the forward channel and backward
> channel do not race. The Linux client implements this mechanism, but in
> a manner that is racy, making it rather pointless, and buggy (Oops!).
>
> This patch series fixes the most egregious issues around delegations and
> layouts by ensuring that we wait for completion of the actual setup of
> the delegation or layout that could be subject to recall.

Out of curiosity--so do we know if there are servers out there using
it at this point?

--b.

>
> Trond Myklebust (5):
> NFSv4.1: Fix Oopsable condition in server callback races
> NFSv4.1: Delay callback processing when there are referring triples
> NFSv4.1: Defer bumping the slot sequence number until we free the slot
> NFSv4.1: Close callback races for OPEN, LAYOUTGET and LAYOUTRETURN
> NFSv4.1: Remove obsolete and incorrrect assignment in
> nfs4_callback_sequence
>
> fs/nfs/callback_proc.c | 8 ++---
> fs/nfs/nfs4proc.c | 89 +++++++++++++++++++++++++++++++++++++++++---------
> fs/nfs/nfs4session.c | 53 ++++++++++++++++++++++++++++++
> fs/nfs/nfs4session.h | 7 +++-
> 4 files changed, 135 insertions(+), 22 deletions(-)
>
> --
> 2.7.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html

2016-09-06 18:16:42

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 0/5] Fix callback channel handling of referring triples


> On Sep 6, 2016, at 14:14, J. Bruce Fields <[email protected]> wrote:
>=20
> On Sun, Aug 28, 2016 at 06:21:00PM -0400, Trond Myklebust wrote:
>> RFC5661 has a mechanism for ensuring that the forward channel and backwa=
rd
>> channel do not race. The Linux client implements this mechanism, but in
>> a manner that is racy, making it rather pointless, and buggy (Oops!).
>>=20
>> This patch series fixes the most egregious issues around delegations and
>> layouts by ensuring that we wait for completion of the actual setup of
>> the delegation or layout that could be subject to recall.
>=20
> Out of curiosity--so do we know if there are servers out there using
> it at this point?

Yes, the Primary Data server does.

>=20
> --b.
>=20
>>=20
>> Trond Myklebust (5):
>> NFSv4.1: Fix Oopsable condition in server callback races
>> NFSv4.1: Delay callback processing when there are referring triples
>> NFSv4.1: Defer bumping the slot sequence number until we free the slot
>> NFSv4.1: Close callback races for OPEN, LAYOUTGET and LAYOUTRETURN
>> NFSv4.1: Remove obsolete and incorrrect assignment in
>> nfs4_callback_sequence
>>=20
>> fs/nfs/callback_proc.c | 8 ++---
>> fs/nfs/nfs4proc.c | 89 +++++++++++++++++++++++++++++++++++++++++---=
------
>> fs/nfs/nfs4session.c | 53 ++++++++++++++++++++++++++++++
>> fs/nfs/nfs4session.h | 7 +++-
>> 4 files changed, 135 insertions(+), 22 deletions(-)
>>=20
>> --=20
>> 2.7.4
>>=20
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html