layout-sim: layout recall callback (forgetful client)
Subsystems (2)
PATCH 1/1 layout-sim: layout recall callback (forgetful client)
[Fixing typo in list address]
-------- Original Message --------
Subject: [PATCH] layout-sim: layout recall callback (forgetful client)
Date: Thu, 27 Jan 2011 17:06:06 +0200
From: Benny Halevy <[email protected]>
To: [email protected], [email protected]
CC: Benny Halevy <[email protected]>
Simulate cb_layoutrecall with the forget client model.
The client responds with NFS4ERR_DELAY if there are any calls it needs to wait for before processing the callback, or if there I/Os in flight (simulated randomally). When the layout can be returned, the client deleted it locally and replies synchronously with NFS4ERR_NOMATCHING_LAYOUT instead of sending layout return.
The server sends only one CB_LAYOUT_RECALL at a time and does not process any LAYOUTGETs while waiting on it, replying with NFS4ERR_RECALLCONFLICT. LAYOUTRETURN stateid sequencing is enforced so that only those sent after the client processed the layout recall callback are accepted. The layout recall "process" is completed either on NFS4ERR_RECALLCONFLICT or on a matching LAYOUTRETURN.
--- client.c | 37 ++++++++++++++++++++++-- layout.c | 21 +++++++++---- layout.h | 18 +++++++++++- server.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 150 insertions(+), 19 deletions(-)
client.c +34 -3
@@ -171,6 +171,8 @@ _reprocess_queue(void)struct msg *m; list_for_each_entry (m, &cl_queued.list, list) { +if (m->type ==CB_LAYOUT_RECALL ) +continue ; if (is_next(&m->stateid, &cl_layout.stateid) || (m->type == LAYOUTRETURN && m->stateid.type == OPEN_STATEID &&
@@ -227,6 +229,36 @@ out_free: }static void +cl_recv_cb_layout_recall (struct msg *m) +{ +if ((m->stateid.type ==OPEN_STATEID && + cl_layout.stateid.type !=OPEN_STATEID ) || + (m->stateid.seq > cl_layout.stateid.seq +1 )) { +dprintk (1 ,"%s: m=%p seq=%llu cl_layout.seq=%llu: waiting\n" , + __func__, m, +llu (m->stateid.seq),llu (cl_layout.stateid.seq)); + m->status =NFS4ERR_DELAY ; + goto out; + } + +BUG_ON (m->stateid.seq <= cl_layout.stateid.seq); +if (mynrand (10 ) <3 ) { +dprintk (1 ,"%s: m=%p: simulating delay\n" , __func__, m); + m->status =NFS4ERR_DELAY ; + goto out; + } + +/* forgetful model */ +layout_delete (&cl_layout, &m->range); + cl_layout.stateid = m->stateid; + m->status =NFS4ERR_NOMATCHING_LAYOUT ; + +out: +dprintk (1 ,"%s: m=%p status=%d\n" , __func__, m, m->status); +enqueue (&srv_msg_queue, m); +} + +static void _cl_recv_msg (struct msg *m) {switch (m->type) {
@@ -236,10 +268,9 @@ _cl_recv_msg(struct msg *m)case LAYOUTRETURN :cl_recv_layoutreturn (m);break ; -#if 0 -case CB_LAYOUTRECALL : +case CB_LAYOUT_RECALL : +cl_recv_cb_layout_recall (m);break ; -#endif default :BUG_ON (true); }
layout.c +14 -7
@@ -65,7 +65,7 @@ last_byte_offset(u64 start, u64 len)* |----------------| */ static inline int -lo_seg_overlapping (struct layout_range *l1,struct layout_range *l2) +lo_seg_overlapping (const struct layout_range *l1,const struct layout_range *l2) {u64 start1 = l1->offset;u64 last1 =last_byte_offset (start1, l1->length);
@@ -82,13 +82,15 @@ lo_seg_overlapping(struct layout_range *l1, struct layout_range *l2) }bool -layout_delete (struct layout *lo,struct layout_range *range) +_lookup_layout (const char *func,struct layout *lo, +const struct layout_range *range, +bool do_delete) {bool found = false;struct layout_item *pos, *next;dprintk (1 ,"%s: %s: offset=%llu length=%llu iomode=%d roc=%d\n" , - __func__, lo->desc, + func, lo->desc,llu (range->offset),llu (range->length), range->iomode, range->roc);
@@ -98,9 +100,12 @@ layout_delete(struct layout *lo, struct layout_range *range) (!range->roc || pos->range.roc) && lo_seg_overlapping(&pos->range, range)) {dprintk (1 ,"%s: found l=%p\n" , __func__, pos); -list_del (&pos->list); -myfree (pos); found = true; +if (do_delete) { +list_del (&pos->list); +myfree (pos); + }else +break ; } }
@@ -113,8 +118,10 @@ layout_verify(struct layout *server, struct layout *client)bool ok = true, found;struct layout_item *cl, *sl; -if ((client->stateid.type != server->stateid.type) || - (client->stateid.seq != server->stateid.seq)) { +if (((client->stateid.type != server->stateid.type) || + (client->stateid.seq != server->stateid.seq)) && + (!server->layout_recall_msg || + client->stateid.seq >= server->stateid.seq)) { dprintk(0, "%s: cl stateid=%d:%llu srv stateid=%d:%llu\n", __func__, client->stateid.type, llu(client->stateid.seq),
layout.h +17 -1
@@ -43,15 +43,31 @@ struct stateid {type resets to OPEN_STATEID */ }; +struct msg ; +struct layout {struct stateid stateid;struct list_head segs;char *desc; +struct msg *layout_recall_msg; };void layout_init (struct layout *,char *desc);void layout_insert (struct layout *,struct layout_range *); -bool layout_delete (struct layout *,struct layout_range *); +bool _lookup_layout (const char *func,struct layout *, +const struct layout_range *, +bool do_delete); + +static inline bool has_layout (struct layout *lo,const struct layout_range *range) +{ +return _lookup_layout (__func__, lo, range, false); +} + +static inline bool layout_delete (struct layout *lo,const struct layout_range *range) +{ +return _lookup_layout (__func__, lo, range, true); +} +bool layout_verify (struct layout *server,struct layout *client);enum msg_type {
server.c +85 -8
146 lines not on this page · raw message
Signature · 1 line
1.7.3.4