Subject: [nfsv4] [PATCH 1/2] layout-sim: bump seqid on CB_LAYOUTRECALL re-issue

From: Benny Halevy <[email-masked]>
Date: Mon, 31 Jan 2011 16:03:07 +0200

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-masked]>
---
 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

---

From: Benny Halevy <[email-masked]>
Date: Mon, 31 Jan 2011 16:03:08 +0200

Signed-off-by: Benny Halevy <[email-masked]>
---
 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