On Mon, 2013-05-20 at 14:13 -0400, andros@xxxxxxxxxx wrote: > From: Andy Adamson <andros@xxxxxxxxxx> > > On a CB_RECALL the callback service thread flushes the inode using > filemap_flush prior to scheduling the state manager thread to return the > delegation. When pNFS is used and I/O has not yet gone to the data server > servicing the inode, a LAYOUTGET can preceed the I/O. Unlike the async > filemap_flush call, the LAYOUTGET must proceed to completion. > > If the state manager starts to recover data while the inode flush is sending > the LAYOUTGET, a deadlock occurs as the callback service thread holds the > single callback session slot until the flushing is done which blocks the state > manager thread, and the state manager thread has set the session draining bit > which puts the inode flush LAYOUTGET RPC to sleep on the forechannel slot > table waitq. > > Separate the draining of the back channel from the draining of the fore channel > by moving the NFS4_SESSION_DRAINING bit from session scope into the fore > and back slot tables. Drain the back channel first allowing the LAYOUTGET > call to proceed (and fail) so the callback service thread frees the callback > slot. Then proceed with draining the forechannel. > > Signed-off-by: Andy Adamson <andros@xxxxxxxxxx> > --- > fs/nfs/callback_proc.c | 2 +- > fs/nfs/callback_xdr.c | 2 +- > fs/nfs/nfs4proc.c | 2 +- > fs/nfs/nfs4session.c | 6 ++++-- > fs/nfs/nfs4session.h | 13 ++++++++----- > fs/nfs/nfs4state.c | 15 +++++++-------- > 6 files changed, 22 insertions(+), 18 deletions(-) > > @@ -395,12 +395,14 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses) > /* Fore channel */ > tbl = &ses->fc_slot_table; > tbl->session = ses; > + tbl->slot_tbl_state = 0; > status = nfs4_realloc_slot_table(tbl, ses->fc_attrs.max_reqs, 1); > if (status) /* -ENOMEM */ > return status; > /* Back channel */ > tbl = &ses->bc_slot_table; > tbl->session = ses; > + tbl->slot_tbl_state = 0; > status = nfs4_realloc_slot_table(tbl, ses->bc_attrs.max_reqs, 0); > if (status && tbl->slots == NULL) > /* Fore and back channel share a connection so get Hi Andy, The above hunk is buggy. nfs4_setup_session_slot_tables() is called from nfs4_proc_create_session(), so it must not reset the NFS4_SLOT_TBL_DRAINING flag. I'm therefore removing the above 2 lines. I've applied the rest of the patch. Thanks! Trond -- Trond Myklebust Linux NFS client maintainer NetApp Trond.Myklebust@xxxxxxxxxx www.netapp.com -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html