the seqid needs to represent the current layout state after NFS4ERR_DELAY
it is not a mere RPC-level retry.
Signed-off-by: Benny Halevy <[email protected]>
---
server.c | 28 +++++++++++++++++++---------
1 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/server.c b/server.c
index 19bb85a..b9c90de 100644
--- a/server.c
+++ b/server.c
@@ -123,16 +123,33 @@ srv_recv_layoutreturn(struct msg *m)
}
static void
+issue_layout_recall(struct msg *m)
+{
+ /* bump server stateid.seq */
+ srv_layout.stateid.seq++;
+ m->stateid = srv_layout.stateid;
+ m->status = -1;
+ srv_layout.layout_recall_msg = m;
+ dump_msg(m);
+ enqueue(&cl_msg_queue, m);
+}
+
+static void
srv_recv_cb_layout_recall(struct msg *m)
{
BUG_ON(m != srv_layout.layout_recall_msg);
dump_msg(m);
switch (m->status) {
case NFS4_OK:
+ /* CB_LAYOUT_RECALL RPC is done but the meta-operations
+ * continues until after receiving the respective terminating
+ * LAYOUTRETURN
+ */
+ break;
case NFS4ERR_DELAY:
dprintk(1, "%s: m=%p: layout_recall resent\n",
__func__, srv_layout.layout_recall_msg);
- enqueue(&cl_msg_queue, srv_layout.layout_recall_msg);
+ issue_layout_recall(srv_layout.layout_recall_msg);
break;
case NFS4ERR_NOMATCHING_LAYOUT:
layout_delete(&cl_layout, &m->range);
@@ -190,14 +207,7 @@ srv_recall_layout(void)
m->range.offset = mynrand(MAX_LO_MSG_OFFSET) & ~BLOCK_MASK;
m->range.length = BLOCK_SIZE + mynrand(MAX_LO_MSG_LENGTH - BLOCK_SIZE);
m->range.iomode = IOMODE_READ + mynrand(3);
- /* bump server stateid.seq */
- srv_layout.stateid.seq++;
- m->stateid = srv_layout.stateid;
- m->status = -1;
- srv_layout.layout_recall_msg = m;
- dump_msg(m);
-
- enqueue(&cl_msg_queue, m);
+ issue_layout_recall(m);
}
struct rand_event srv_events[] = {
--
1.7.3.4
Signed-off-by: Benny Halevy <[email protected]>
---
server.c | 19 ++++++++++++++++++-
1 files changed, 18 insertions(+), 1 deletions(-)
diff --git a/server.c b/server.c
index b9c90de..7119ab2 100644
--- a/server.c
+++ b/server.c
@@ -65,6 +65,7 @@ verify_stateid(struct msg *m)
/* FIXME: use an actual limit on parallelism */
return m->status = NFS4ERR_OLD_STATEID;
} else if (m->stateid.type == LAYOUT_STATEID) {
+ /* FIXME: is this specified for LAYOUTRETURN. */
if (srv_layout.layout_recall_msg &&
m->stateid.seq < srv_layout.layout_recall_msg->stateid.seq)
return m->status = NFS4ERR_OLD_STATEID;
@@ -78,10 +79,26 @@ verify_stateid(struct msg *m)
return 0;
}
+static bool
+is_conflicting(struct layout_range *lr, struct layout_range *r)
+{
+ if (lr->iomode != IOMODE_ANY && lr->iomode != r->iomode)
+ return false;
+ if (r->offset >= lr->offset)
+ return (lr->length == NFS4_MAX_UINT64) ||
+ (lr->offset + lr->length > r->offset);
+ else
+ return (r->length == NFS4_MAX_UINT64) ||
+ (r->offset + r->length > lr->offset);
+}
+
static void
srv_recv_layoutget(struct msg *m)
{
- if (srv_layout.layout_recall_msg) {
+ struct msg *lrm = srv_layout.layout_recall_msg;
+
+ /* See section 12.5.5.2.1.3 */
+ if (lrm && is_conflicting(&lrm->range, &m->range)) {
m->status = NFS4ERR_RECALLCONFLICT;
goto out;
}
--
1.7.3.4
_______________________________________________
nfsv4 mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/nfsv4