Re: [PATCH_V2 1/1] NFS add session back channel draining

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Dec 12, 2010, at 3:59 PM, Fred Isaman wrote:

> On Mon, Dec 6, 2010 at 10:19 PM,  <andros@xxxxxxxxxx> wrote:
>> From: Andy Adamson <andros@xxxxxxxxxx>
>> 
>> Currently session draining only drains the fore channel.
>> The back channel processing must also be drained.
>> 
>> Use the back channel highest_slot_used to indicate that a callback is being
>> processed by the callback thread.  Move the session complete to be per channel.
>> 
>> When the session is draininig, wait for any current back channel processing
>> to complete and stop all new back channel processing by returning NFS4ERR_DELAY
>> to the back channel client.
>> 
>> Drain the back channel, then the fore channel.
>> 
>> Signed-off-by: Andy Adamson <andros@xxxxxxxxxx>
>> ---
>>  fs/nfs/callback.h         |    1 +
>>  fs/nfs/callback_proc.c    |    6 ++++++
>>  fs/nfs/callback_xdr.c     |   17 +++++++++++++++++
>>  fs/nfs/nfs4proc.c         |   26 +++++++++++++++++++-------
>>  fs/nfs/nfs4state.c        |   29 ++++++++++++++++++++++-------
>>  include/linux/nfs_fs_sb.h |    2 +-
>>  6 files changed, 66 insertions(+), 15 deletions(-)
>> 
>> diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
>> index 85a7cfd..434233e 100644
>> --- a/fs/nfs/callback.h
>> +++ b/fs/nfs/callback.h
>> @@ -131,6 +131,7 @@ extern unsigned nfs4_callback_recallslot(struct cb_recallslotargs *args,
>> 
>>  extern __be32 nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres *res);
>>  extern __be32 nfs4_callback_recall(struct cb_recallargs *args, void *dummy);
>> +extern void nfs4_check_drain_bc_complete(struct nfs4_session *ses);
>> 
>>  #ifdef CONFIG_NFS_V4
>>  extern int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt);
>> diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
>> index 2950fca..7a976ef 100644
>> --- a/fs/nfs/callback_proc.c
>> +++ b/fs/nfs/callback_proc.c
>> @@ -287,6 +287,12 @@ __be32 nfs4_callback_sequence(struct cb_sequenceargs *args,
>>        if (clp == NULL)
>>                goto out;
>> 
>> +       /* state manager is resetting the session */
>> +       if (test_bit(NFS4_SESSION_DRAINING, &clp->cl_session->session_state)) {
>> +               status = NFS4ERR_DELAY;
>> +               goto out_putclient;
>> +       }
>> +
>>        status = validate_seqid(&clp->cl_session->bc_slot_table, args);
>>        if (status)
>>                goto out_putclient;
>> diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
>> index 05af212..0a5e32d 100644
>> --- a/fs/nfs/callback_xdr.c
>> +++ b/fs/nfs/callback_xdr.c
>> @@ -593,6 +593,20 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
>>        return htonl(NFS_OK);
>>  }
>> 
>> +static void nfs4_callback_free_slot(struct nfs4_session *session)
> 
> 
> Am I missing something, or was the call to this function omitted?

You're right, I omitted it - should be in nfs4_callback_compound. I'll check all these patches again, and resend to Trond who I suspect lost them in the flurry of patches...

-->Andy

> 
> Fred
> 
>> +{
>> +       struct nfs4_slot_table *tbl = &session->bc_slot_table;
>> +
>> +       spin_lock(&tbl->slot_tbl_lock);
>> +       /*
>> +        * Let the state manager know callback processing done.
>> +        * A single slot, so highest used slotid is either 0 or -1
>> +        */
>> +       tbl->highest_used_slotid--;
>> +       nfs4_check_drain_bc_complete(session);
>> +       spin_unlock(&tbl->slot_tbl_lock);
>> +}
>> +
>>  #else /* CONFIG_NFS_V4_1 */
>> 
>>  static __be32
>> @@ -601,6 +615,9 @@ preprocess_nfs41_op(int nop, unsigned int op_nr, struct callback_op **op)
>>        return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
>>  }
>> 
>> +static void nfs4_callback_free_slot(struct nfs4_session *session)
>> +{
>> +}
>>  #endif /* CONFIG_NFS_V4_1 */
>> 
>>  static __be32
>> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
>> index 6a653ff..b48f607 100644
>> --- a/fs/nfs/nfs4proc.c
>> +++ b/fs/nfs/nfs4proc.c
>> @@ -355,9 +355,9 @@ nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
>>  }
>> 
>>  /*
>> - * Signal state manager thread if session is drained
>> + * Signal state manager thread if session fore channel is drained
>>  */
>> -static void nfs41_check_drain_session_complete(struct nfs4_session *ses)
>> +static void nfs4_check_drain_fc_complete(struct nfs4_session *ses)
>>  {
>>        struct rpc_task *task;
>> 
>> @@ -371,8 +371,20 @@ static void nfs41_check_drain_session_complete(struct nfs4_session *ses)
>>        if (ses->fc_slot_table.highest_used_slotid != -1)
>>                return;
>> 
>> -       dprintk("%s COMPLETE: Session Drained\n", __func__);
>> -       complete(&ses->complete);
>> +       dprintk("%s COMPLETE: Session Fore Channel Drained\n", __func__);
>> +       complete(&ses->fc_slot_table.complete);
>> +}
>> +
>> +/*
>> + * Signal state manager thread if session back channel is drained
>> + */
>> +void nfs4_check_drain_bc_complete(struct nfs4_session *ses)
>> +{
>> +       if (!test_bit(NFS4_SESSION_DRAINING, &ses->session_state) ||
>> +           ses->bc_slot_table.highest_used_slotid != -1)
>> +               return;
>> +       dprintk("%s COMPLETE: Session Back Channel Drained\n", __func__);
>> +       complete(&ses->bc_slot_table.complete);
>>  }
>> 
>>  static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
>> @@ -389,7 +401,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
>> 
>>        spin_lock(&tbl->slot_tbl_lock);
>>        nfs4_free_slot(tbl, res->sr_slot);
>> -       nfs41_check_drain_session_complete(res->sr_session);
>> +       nfs4_check_drain_fc_complete(res->sr_session);
>>        spin_unlock(&tbl->slot_tbl_lock);
>>        res->sr_slot = NULL;
>>  }
>> @@ -4767,17 +4779,17 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp)
>>        if (!session)
>>                return NULL;
>> 
>> -       init_completion(&session->complete);
>> -
>>        tbl = &session->fc_slot_table;
>>        tbl->highest_used_slotid = -1;
>>        spin_lock_init(&tbl->slot_tbl_lock);
>>        rpc_init_priority_wait_queue(&tbl->slot_tbl_waitq, "ForeChannel Slot table");
>> +       init_completion(&tbl->complete);
>> 
>>        tbl = &session->bc_slot_table;
>>        tbl->highest_used_slotid = -1;
>>        spin_lock_init(&tbl->slot_tbl_lock);
>>        rpc_init_wait_queue(&tbl->slot_tbl_waitq, "BackChannel Slot table");
>> +       init_completion(&tbl->complete);
>> 
>>        session->session_state = 1<<NFS4_SESSION_INITING;
>> 
>> diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
>> index f575a31..0082483 100644
>> --- a/fs/nfs/nfs4state.c
>> +++ b/fs/nfs/nfs4state.c
>> @@ -142,6 +142,11 @@ static int nfs41_setup_state_renewal(struct nfs_client *clp)
>>        return status;
>>  }
>> 
>> +/*
>> + * Back channel returns NFS4ERR_DELAY for new requests when
>> + * NFS4_SESSION_DRAINING is set so there is no work to be done when draining
>> + * is ended.
>> + */
>>  static void nfs4_end_drain_session(struct nfs_client *clp)
>>  {
>>        struct nfs4_session *ses = clp->cl_session;
>> @@ -165,21 +170,31 @@ static void nfs4_end_drain_session(struct nfs_client *clp)
>>        }
>>  }
>> 
>> -static int nfs4_begin_drain_session(struct nfs_client *clp)
>> +static int nfs4_wait_on_slot_tbl(struct nfs4_slot_table *tbl)
>>  {
>> -       struct nfs4_session *ses = clp->cl_session;
>> -       struct nfs4_slot_table *tbl = &ses->fc_slot_table;
>> -
>>        spin_lock(&tbl->slot_tbl_lock);
>> -       set_bit(NFS4_SESSION_DRAINING, &ses->session_state);
>>        if (tbl->highest_used_slotid != -1) {
>> -               INIT_COMPLETION(ses->complete);
>> +               INIT_COMPLETION(tbl->complete);
>>                spin_unlock(&tbl->slot_tbl_lock);
>> -               return wait_for_completion_interruptible(&ses->complete);
>> +               return wait_for_completion_interruptible(&tbl->complete);
>>        }
>>        spin_unlock(&tbl->slot_tbl_lock);
>>        return 0;
>>  }
>> +
>> +static int nfs4_begin_drain_session(struct nfs_client *clp)
>> +{
>> +       struct nfs4_session *ses = clp->cl_session;
>> +       int ret = 0;
>> +
>> +       set_bit(NFS4_SESSION_DRAINING, &ses->session_state);
>> +       /* back channel */
>> +       ret = nfs4_wait_on_slot_tbl(&ses->bc_slot_table);
>> +       if (ret)
>> +               return ret;
>> +       /* fore channel */
>> +       return nfs4_wait_on_slot_tbl(&ses->fc_slot_table);
>> +}
>> 
>>  int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
>>  {
>> diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
>> index 452d964..8ded472 100644
>> --- a/include/linux/nfs_fs_sb.h
>> +++ b/include/linux/nfs_fs_sb.h
>> @@ -196,6 +196,7 @@ struct nfs4_slot_table {
>>                                                 * op for dynamic resizing */
>>        int             target_max_slots;       /* Set by CB_RECALL_SLOT as
>>                                                 * the new max_slots */
>> +       struct completion complete;
>>  };
>> 
>>  static inline int slot_idx(struct nfs4_slot_table *tbl, struct nfs4_slot *sp)
>> @@ -212,7 +213,6 @@ struct nfs4_session {
>>        unsigned long                   session_state;
>>        u32                             hash_alg;
>>        u32                             ssv_len;
>> -       struct completion               complete;
>> 
>>        /* The fore and back channel */
>>        struct nfs4_channel_attrs       fc_attrs;
>> --
>> 1.6.6
>> 
>> --
>> 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
>> 

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


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux