From 227f98d98d2ed7929f41426adc21f57b927354a6 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 18 Feb 2010 08:27:24 -0800 Subject: nfsd4: preallocate nfs4_rpc_args Instead of allocating this small structure, just include it in the delegation. The nfsd4_callback structure isn't really necessary yet, but we plan to add to it all the information necessary to perform a callback. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index fefeae27f25e..b85437982a8d 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -70,6 +70,15 @@ struct nfsd4_cb_sequence { struct nfs4_client *cbs_clp; }; +struct nfs4_rpc_args { + void *args_op; + struct nfsd4_cb_sequence args_seq; +}; + +struct nfsd4_callback { + struct nfs4_rpc_args cb_args; +}; + struct nfs4_delegation { struct list_head dl_perfile; struct list_head dl_perclnt; @@ -86,6 +95,7 @@ struct nfs4_delegation { stateid_t dl_stateid; struct knfsd_fh dl_fh; int dl_retries; + struct nfsd4_callback dl_recall; }; /* client delegation callback info */ -- cgit v1.2.3 From b5a1a81e5c25fb6bb3fdc1812ba69ff6ab638fcf Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 3 Mar 2010 14:52:55 -0500 Subject: nfsd4: don't sleep in lease-break callback The NFSv4 server's fl_break callback can sleep (dropping the BKL), in order to allocate a new rpc task to send a recall to the client. As far as I can tell this doesn't cause any races in the current code, but the analysis is difficult. Also, the sleep here may complicate the move away from the BKL. So, just schedule some work to do the job for us instead. The work will later also prove useful for restarting a call after the callback information is changed. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index b85437982a8d..c4c92aea8f39 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -77,6 +77,7 @@ struct nfs4_rpc_args { struct nfsd4_callback { struct nfs4_rpc_args cb_args; + struct work_struct cb_work; }; struct nfs4_delegation { @@ -391,7 +392,11 @@ extern void put_nfs4_client(struct nfs4_client *clp); extern void nfs4_free_stateowner(struct kref *kref); extern int set_callback_cred(void); extern void nfsd4_probe_callback(struct nfs4_client *clp); +extern void nfsd4_do_callback_rpc(struct work_struct *); extern void nfsd4_cb_recall(struct nfs4_delegation *dp); +extern int nfsd4_create_callback_queue(void); +extern void nfsd4_destroy_callback_queue(void); +extern void nfsd4_set_callback_client(struct nfs4_client *, struct rpc_clnt *); extern void nfs4_put_delegation(struct nfs4_delegation *dp); extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); extern void nfsd4_init_recdir(char *recdir_name); -- cgit v1.2.3 From b12a05cbdfdf7e4d8cbe8fa78e995f971420086b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 4 Mar 2010 11:32:59 -0500 Subject: nfsd4: cl_count is unused Now that the shutdown sequence guarantees callbacks are shut down before the client is destroyed, we no longer have a use for cl_count. We'll probably reinstate a reference count on the client some day, but it will be held by users other than callbacks. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index c4c92aea8f39..cef20abf330c 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -224,7 +224,6 @@ struct nfs4_client { clientid_t cl_clientid; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */ struct nfs4_cb_conn cl_cb_conn; /* callback info */ - atomic_t cl_count; /* ref count */ u32 cl_firststate; /* recovery dir creation */ /* for nfs41 */ @@ -388,7 +387,6 @@ extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); extern int nfs4_in_grace(void); extern __be32 nfs4_check_open_reclaim(clientid_t *clid); -extern void put_nfs4_client(struct nfs4_client *clp); extern void nfs4_free_stateowner(struct kref *kref); extern int set_callback_cred(void); extern void nfsd4_probe_callback(struct nfs4_client *clp); -- cgit v1.2.3 From 2bf23875f55af6038a5d1c164a52cec4c24609ba Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 8 Mar 2010 12:37:27 -0500 Subject: nfsd4: rearrange cb data structures Mainly I just want to separate the arguments used for setting up the tcp client from the rest. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index cef20abf330c..cf43812e6da5 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -107,9 +107,7 @@ struct nfs4_cb_conn { u32 cb_prog; u32 cb_minorversion; u32 cb_ident; /* minorversion 0 only */ - /* RPC client info */ - atomic_t cb_set; /* successful CB_NULL call */ - struct rpc_clnt * cb_client; + struct svc_xprt *cb_xprt; /* minorversion 1 only */ }; /* Maximum number of slots per session. 160 is useful for long haul TCP */ @@ -223,9 +221,13 @@ struct nfs4_client { struct svc_cred cl_cred; /* setclientid principal */ clientid_t cl_clientid; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */ - struct nfs4_cb_conn cl_cb_conn; /* callback info */ u32 cl_firststate; /* recovery dir creation */ + /* for v4.0 and v4.1 callbacks: */ + struct nfs4_cb_conn cl_cb_conn; + struct rpc_clnt *cl_cb_client; + atomic_t cl_cb_set; + /* for nfs41 */ struct list_head cl_sessions; struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */ @@ -236,7 +238,6 @@ struct nfs4_client { /* We currently support a single back channel with a single slot */ unsigned long cl_cb_slot_busy; u32 cl_cb_seq_nr; - struct svc_xprt *cl_cb_xprt; /* 4.1 callback transport */ struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */ /* wait here for slots */ }; -- cgit v1.2.3 From 4b21d0defcc9680da8a694e92d5fe8eb668c2c0b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sun, 7 Mar 2010 23:39:01 -0500 Subject: nfsd4: allow 4.0 clients to change callback path The rfc allows a client to change the callback parameters, but we didn't previously implement it. Teach the callbacks to rerun themselves (by placing themselves on a workqueue) when they recognize that their rpc task has been killed and that the callback connection has changed. Then we can change the callback connection by setting up a new rpc client, modifying the nfs4 client to point at it, waiting for any work in progress to complete, and then shutting down the old client. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index cf43812e6da5..98836fd87f69 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -390,7 +390,7 @@ extern int nfs4_in_grace(void); extern __be32 nfs4_check_open_reclaim(clientid_t *clid); extern void nfs4_free_stateowner(struct kref *kref); extern int set_callback_cred(void); -extern void nfsd4_probe_callback(struct nfs4_client *clp); +extern void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); extern void nfsd4_do_callback_rpc(struct work_struct *); extern void nfsd4_cb_recall(struct nfs4_delegation *dp); extern int nfsd4_create_callback_queue(void); -- cgit v1.2.3 From 46583e2597af649f134462d2f2c1be5e6689198d Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 12 May 2010 00:13:29 +0300 Subject: nfsd4: introduce nfs4_client.cl_refcount Currently just initialize the cl_refcount to 1 and decrement in expire_client(), conditionally freeing the client when the refcount reaches 0. To be used later by nfsv4.1 compounds to keep the client from timing out while in use. Signed-off-by: Benny Halevy Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 98836fd87f69..ee42a0beecfa 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -233,6 +233,8 @@ struct nfs4_client { struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */ u32 cl_exchange_flags; struct nfs4_sessionid cl_sessionid; + /* number of rpc's in progress over an associated session: */ + atomic_t cl_refcount; /* for nfs41 callbacks */ /* We currently support a single back channel with a single slot */ -- cgit v1.2.3 From 07cd4909a6c0c275ef42fd27748226975919e336 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 12 May 2010 00:13:41 +0300 Subject: nfsd4: mark_client_expired Mark the client as expired under the client_lock so it won't be renewed when an nfsv4.1 session is done, after it was explicitly expired during processing of the compound. Do not renew a client mark as expired (in particular, it is not on the lru list anymore) Signed-off-by: Benny Halevy Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index ee42a0beecfa..cfd743ea4b79 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -166,7 +166,7 @@ struct nfsd4_session { struct list_head se_hash; /* hash by sessionid */ struct list_head se_perclnt; u32 se_flags; - struct nfs4_client *se_client; /* for expire_client */ + struct nfs4_client *se_client; struct nfs4_sessionid se_sessionid; struct nfsd4_channel_attrs se_fchannel; struct nfsd4_channel_attrs se_bchannel; @@ -244,6 +244,18 @@ struct nfs4_client { /* wait here for slots */ }; +static inline void +mark_client_expired(struct nfs4_client *clp) +{ + clp->cl_time = 0; +} + +static inline bool +is_client_expired(struct nfs4_client *clp) +{ + return clp->cl_time == 0; +} + /* struct nfs4_client_reset * one per old client. Populates reset_str_hashtbl. Filled from conf_id_hashtbl * upon lease reset, or from upcall to state_daemon (to read in state -- cgit v1.2.3 From d76829889ac4250a18cfcc1a606bb256bb9c570c Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 12 May 2010 00:13:54 +0300 Subject: nfsd4: keep a reference count on client while in use Get a refcount on the client on SEQUENCE, Release the refcount and renew the client when all respective compounds completed. Do not expire the client by the laundromat while in use. If the client was expired via another path, free it when the compounds complete and the refcount reaches 0. Note that unhash_client_locked must call list_del_init on cl_lru as it may be called twice for the same client (once from nfs4_laundromat and then from expire_client) Signed-off-by: Benny Halevy Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index cfd743ea4b79..006c84230c7c 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -420,6 +420,7 @@ extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); extern void nfsd4_recdir_purge_old(void); extern int nfsd4_create_clid_dir(struct nfs4_client *clp); extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); +extern void release_session_client(struct nfsd4_session *); static inline void nfs4_put_stateowner(struct nfs4_stateowner *so) -- cgit v1.2.3