From 7df302f75ee28a6a87436e93b625ef60d37d098e Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 29 May 2012 13:56:37 -0400 Subject: NFSD: TEST_STATEID should not return NFS4ERR_STALE_STATEID According to RFC 5661, the TEST_STATEID operation is not allowed to return NFS4ERR_STALE_STATEID. In addition, RFC 5661 says: 15.1.16.5. NFS4ERR_STALE_STATEID (Error Code 10023) A stateid generated by an earlier server instance was used. This error is moot in NFSv4.1 because all operations that take a stateid MUST be preceded by the SEQUENCE operation, and the earlier server instance is detected by the session infrastructure that supports SEQUENCE. I triggered NFS4ERR_STALE_STATEID while testing the Linux client's NOGRACE recovery. Bruce suggested an additional test that could be useful to client developers. Lastly, RFC 5661, section 18.48.3 has this: o Special stateids are always considered invalid (they result in the error code NFS4ERR_BAD_STATEID). An explicit check is made for those state IDs to avoid printk noise. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 849091e16ea..495df4e3aa6 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -475,7 +475,6 @@ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); extern int nfs4_client_to_reclaim(const char *name); extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); extern void release_session_client(struct nfsd4_session *); -extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *); extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); /* nfs4recover operations */ -- cgit v1.2.1 From 5ccb0066f2d561549cc4d73d7f56b4ce3ca7a8a1 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Jul 2012 16:57:22 +0400 Subject: LockD: pass actual network namespace to grace period management functions Passed network namespace replaced hard-coded init_net Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 495df4e3aa6..981ef10141b 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -451,7 +451,8 @@ static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) struct nfsd4_compound_state; -extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, +extern __be32 nfs4_preprocess_stateid_op(struct net *net, + struct nfsd4_compound_state *cstate, stateid_t *stateid, int flags, struct file **filp); extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); -- cgit v1.2.1 From 2c142baa7b237584bae7dc28630851701497e1ef Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 25 Jul 2012 16:57:45 +0400 Subject: NFSd: make boot_time variable per network namespace NFSd's boot_time represents grace period start point in time. Signed-off-by: Stanislav Kinsbursky 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 981ef10141b..e6173147f98 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -450,6 +450,7 @@ static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) #define WR_STATE 0x00000020 struct nfsd4_compound_state; +struct nfsd_net; extern __be32 nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate, -- cgit v1.2.1 From 39307655a1effa8d913bba054c0e985bfaca808c Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 16 Aug 2012 17:01:21 -0400 Subject: nfsd4: fix security flavor of NFSv4.0 callback Commit d5497fc693a446ce9100fcf4117c3f795ddfd0d2 "nfsd4: move rq_flavor into svc_cred" forgot to remove cl_flavor from the client, leaving two places (cl_flavor and cl_cred.cr_flavor) for the flavor to be stored. After that patch, the latter was the one that was updated, but the former was the one that the callback used. Symptoms were a long delay on utime(). This is because the utime() generated a setattr which recalled a delegation, but the cb_recall was ignored by the client because it had the wrong security flavor. Cc: stable@vger.kernel.org Tested-by: Jamie Heilman Reported-by: Jamie Heilman Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 1 - 1 file changed, 1 deletion(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index e6173147f98..22bd0a66c35 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -231,7 +231,6 @@ struct nfs4_client { nfs4_verifier cl_verifier; /* generated by client */ time_t cl_time; /* time of last lease renewal */ struct sockaddr_storage cl_addr; /* client ipaddress */ - u32 cl_flavor; /* setclientid pseudoflavor */ struct svc_cred cl_cred; /* setclientid principal */ clientid_t cl_clientid; /* generated by server */ nfs4_verifier cl_confirm; /* generated by server */ -- cgit v1.2.1 From 1696c47ce2f42e671f6a17682b533273f4ac7963 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 6 Aug 2012 11:00:27 -0400 Subject: nfsd: trivial comment updates locks.c doesn't use the BKL anymore and there is no fi_perfile field. Signed-off-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 22bd0a66c35..ec513fd4bae 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -373,11 +373,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so) return container_of(so, struct nfs4_lockowner, lo_owner); } -/* -* nfs4_file: a file opened by some number of (open) nfs4_stateowners. -* o fi_perfile list is used to search for conflicting -* share_acces, share_deny on the file. -*/ +/* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */ struct nfs4_file { atomic_t fi_ref; struct list_head fi_hash; /* hash by "struct inode *" */ -- cgit v1.2.1 From d15c077e442d3c4167aaac87b3b7fe8ccad67a1f Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 13 Sep 2012 16:19:31 -0400 Subject: nfsd4: enforce per-client sessions/no-sessions distinction Something like creating a client with setclientid and then trying to confirm it with create_session may not crash the server, but I'm not completely positive of that, and in any case it's obviously bad client behavior. 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 ec513fd4bae..e036894bce5 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -455,7 +455,7 @@ extern void nfs4_unlock_state(void); extern int nfs4_in_grace(void); extern void nfs4_release_reclaim(void); extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); -extern __be32 nfs4_check_open_reclaim(clientid_t *clid); +extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); extern void nfs4_free_openowner(struct nfs4_openowner *); extern void nfs4_free_lockowner(struct nfs4_lockowner *); extern int set_callback_cred(void); -- cgit v1.2.1 From acb2887e04c2140c2c63c8bf94e0b446efcc7001 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 27 Mar 2012 14:50:26 -0400 Subject: nfsd4: clean up callback security parsing Move the callback parsing into a separate function. Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index e036894bce5..df33e781f36 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -150,6 +150,11 @@ struct nfsd4_channel_attrs { u32 rdma_attrs; }; +struct nfsd4_cb_sec { + u32 uid; + u32 gid; +}; + struct nfsd4_create_session { clientid_t clientid; struct nfs4_sessionid sessionid; @@ -158,8 +163,7 @@ struct nfsd4_create_session { struct nfsd4_channel_attrs fore_channel; struct nfsd4_channel_attrs back_channel; u32 callback_prog; - u32 uid; - u32 gid; + struct nfsd4_cb_sec cb_sec; }; struct nfsd4_bind_conn_to_session { @@ -192,6 +196,7 @@ struct nfsd4_session { struct nfs4_sessionid se_sessionid; struct nfsd4_channel_attrs se_fchannel; struct nfsd4_channel_attrs se_bchannel; + struct nfsd4_cb_sec se_cb_sec; struct list_head se_conns; u32 se_cb_prog; u32 se_cb_seq_nr; -- cgit v1.2.1 From c6bb3ca27d78b902baa143b931a8d9ef53298afa Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 1 Nov 2012 16:31:02 -0400 Subject: nfsd4: use callback security parameters in create_session We're currently ignoring the callback security parameters specified in create_session, and just assuming the client wants auth_sys, because that's all the current linux client happens to care about. But this could cause us callbacks to fail to a client that wanted something different. For now, all we're doing is no longer ignoring the uid and gid passed in the auth_sys case. Further patches will add support for auth_null and gss (and possibly use more of the auth_sys information; the spec wants us to use exactly the credential we're passed, though it's hard to imagine why a client would care). 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 df33e781f36..bff856c34a3 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -250,6 +250,7 @@ struct nfs4_client { #define NFSD4_CLIENT_CB_FLAG_MASK (1 << NFSD4_CLIENT_CB_UPDATE | \ 1 << NFSD4_CLIENT_CB_KILL) unsigned long cl_flags; + struct rpc_cred *cl_cb_cred; struct rpc_clnt *cl_cb_client; u32 cl_cb_ident; #define NFSD4_CB_UP 0 -- cgit v1.2.1 From cb73a9f4649bf63c0397e565a15abf8a91ecf56f Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 1 Nov 2012 18:09:48 -0400 Subject: nfsd4: implement backchannel_ctl operation This operation is mandatory for servers to implement. 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 bff856c34a3..758bc9c2646 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -166,6 +166,11 @@ struct nfsd4_create_session { struct nfsd4_cb_sec cb_sec; }; +struct nfsd4_backchannel_ctl { + u32 bc_cb_program; + struct nfsd4_cb_sec bc_cb_sec; +}; + struct nfsd4_bind_conn_to_session { struct nfs4_sessionid sessionid; u32 dir; -- cgit v1.2.1 From 57725155dc1b8c78b7a96886d5cdc69dc89e9c54 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 5 Nov 2012 15:10:26 -0500 Subject: nfsd4: common helper to initialize callback work I've found it confusing having the only references to nfsd4_do_callback_rpc() in a different file. 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 758bc9c2646..0fd342a2174 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -470,10 +470,10 @@ extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); extern void nfs4_free_openowner(struct nfs4_openowner *); extern void nfs4_free_lockowner(struct nfs4_lockowner *); extern int set_callback_cred(void); +extern void nfsd4_init_callback(struct nfsd4_callback *); extern void nfsd4_probe_callback(struct nfs4_client *clp); extern void nfsd4_probe_callback_sync(struct nfs4_client *clp); extern void nfsd4_change_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); extern void nfsd4_destroy_callback_queue(void); -- cgit v1.2.1 From 12fc3e92d4b18b4e99af624586e1696479ff36ce Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 5 Nov 2012 16:01:48 -0500 Subject: nfsd4: backchannel should use client-provided security flavor For now this only adds support for AUTH_NULL. (Previously we assumed AUTH_UNIX.) We'll also need AUTH_GSS, which is trickier. 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 0fd342a2174..0498053b8f0 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -151,6 +151,7 @@ struct nfsd4_channel_attrs { }; struct nfsd4_cb_sec { + u32 flavor; /* (u32)(-1) used to mean "no valid flavor" */ u32 uid; u32 gid; }; -- cgit v1.2.1 From a0af710a6510213672d28f83681c391d36a7555e Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Fri, 9 Nov 2012 15:06:38 -0500 Subject: nfsd: remove unused argument to nfs4_has_reclaimed_state Signed-off-by: Jeff Layton 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 0498053b8f0..8053b574796 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -482,7 +482,7 @@ extern void nfsd4_shutdown_callback(struct nfs4_client *); extern void nfs4_put_delegation(struct nfs4_delegation *dp); extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); extern int nfs4_client_to_reclaim(const char *name); -extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); +extern int nfs4_has_reclaimed_state(const char *name); extern void release_session_client(struct nfsd4_session *); extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); -- cgit v1.2.1 From 278c931cb05ae624df8c82b6bdfbb0e03392cde7 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 Nov 2012 15:00:52 -0500 Subject: nfsd: have nfsd4_find_reclaim_client take a char * argument Currently, it takes a client pointer, but later we're going to need to search for these records without knowing whether a matching client even exists. Signed-off-by: Jeff Layton 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 8053b574796..c41c28020ca 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -466,7 +466,7 @@ extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); extern int nfs4_in_grace(void); extern void nfs4_release_reclaim(void); -extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); +extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir); extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); extern void nfs4_free_openowner(struct nfs4_openowner *); extern void nfs4_free_lockowner(struct nfs4_lockowner *); -- cgit v1.2.1 From ce30e5392fcb26b6aa53bb16d06da1d7d8bb0863 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 Nov 2012 15:00:53 -0500 Subject: nfsd: break out reclaim record removal into separate function We'll need to be able to call this from nfs4recover.c eventually. Signed-off-by: Jeff Layton 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 c41c28020ca..3528616c955 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -465,6 +465,7 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net, extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); extern int nfs4_in_grace(void); +void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *); extern void nfs4_release_reclaim(void); extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir); extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); -- cgit v1.2.1 From 772a9bbbb5769c646c74452ef21df538bbe2ebf0 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 Nov 2012 15:00:54 -0500 Subject: nfsd: make nfs4_client_to_reclaim return a pointer to the reclaim record Later callers will need to make changes to the record. Signed-off-by: Jeff Layton 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 3528616c955..3f8b26b9b47 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -482,7 +482,7 @@ extern void nfsd4_destroy_callback_queue(void); extern void nfsd4_shutdown_callback(struct nfs4_client *); extern void nfs4_put_delegation(struct nfs4_delegation *dp); extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); -extern int nfs4_client_to_reclaim(const char *name); +extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name); extern int nfs4_has_reclaimed_state(const char *name); extern void release_session_client(struct nfsd4_session *); extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); -- cgit v1.2.1 From 0ce0c2b5d23080eec39ccc52354be1eea326ed5f Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 Nov 2012 15:00:55 -0500 Subject: nfsd: don't search for client by hash on legacy reboot recovery gracedone When nfsd starts, the legacy reboot recovery code creates a tracking struct for each directory in the v4recoverydir. When the grace period ends, it basically does a "readdir" on the directory again, and matches each dentry in there to an existing client id to see if it should be removed or not. If the matching client doesn't exist, or hasn't reclaimed its state then it will remove that dentry. This is pretty inefficient since it involves doing a lot of hash-bucket searching. It also means that we have to keep relying on being able to search for a nfs4_client by md5 hashed cl_recdir name. Instead, add a pointer to the nfs4_client that indicates the association between the nfs4_client_reclaim and nfs4_client. When a reclaim operation comes in, we set the pointer to make that association. On gracedone, the legacy client tracker will keep the recdir around iff: 1/ there is a reclaim record for the directory ...and... 2/ there's an association between the reclaim record and a client record -- that is, a create or check operation was performed on the client that matches that directory. Signed-off-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 3f8b26b9b47..cf9f7ba4df8 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -304,6 +304,7 @@ is_client_expired(struct nfs4_client *clp) */ struct nfs4_client_reclaim { struct list_head cr_strhash; /* hash by cr_name */ + struct nfs4_client *cr_clp; /* pointer to associated clp */ char cr_recdir[HEXDIR_LEN]; /* recover dir */ }; @@ -464,7 +465,6 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net, stateid_t *stateid, int flags, struct file **filp); extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); -extern int nfs4_in_grace(void); void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *); extern void nfs4_release_reclaim(void); extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir); @@ -483,7 +483,7 @@ extern void nfsd4_shutdown_callback(struct nfs4_client *); extern void nfs4_put_delegation(struct nfs4_delegation *dp); extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name); -extern int nfs4_has_reclaimed_state(const char *name); +extern bool nfs4_has_reclaimed_state(const char *name); extern void release_session_client(struct nfsd4_session *); extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); -- cgit v1.2.1 From ac55fdc408039b425a2fa3cbcaed7444e5339f9a Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 Nov 2012 15:00:56 -0500 Subject: nfsd: move the confirmed and unconfirmed hlists to a rbtree The current code requires that we md5 hash the name in order to store the client in the confirmed and unconfirmed trees. Change it instead to store the clients in a pair of rbtrees, and simply compare the cl_names directly instead of hashing them. This also necessitates that we add a new flag to the clp->cl_flags field to indicate which tree the client is currently in. Signed-off-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index cf9f7ba4df8..6c342bd806e 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -232,7 +232,7 @@ struct nfsd4_sessionid { */ struct nfs4_client { struct list_head cl_idhash; /* hash by cl_clientid.id */ - struct list_head cl_strhash; /* hash by cl_name */ + struct rb_node cl_namenode; /* link into by-name trees */ struct list_head cl_openowners; struct idr cl_stateids; /* stateid lookup */ struct list_head cl_delegations; @@ -253,6 +253,7 @@ struct nfs4_client { #define NFSD4_CLIENT_CB_KILL (1) #define NFSD4_CLIENT_STABLE (2) /* client on stable storage */ #define NFSD4_CLIENT_RECLAIM_COMPLETE (3) /* reclaim_complete done */ +#define NFSD4_CLIENT_CONFIRMED (4) /* client is confirmed */ #define NFSD4_CLIENT_CB_FLAG_MASK (1 << NFSD4_CLIENT_CB_UPDATE | \ 1 << NFSD4_CLIENT_CB_KILL) unsigned long cl_flags; -- cgit v1.2.1 From 2216d449a97927cc105912e337d169cd4d4db548 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 12 Nov 2012 15:00:57 -0500 Subject: nfsd: get rid of cl_recdir field Remove the cl_recdir field from the nfs4_client struct. Instead, just compute it on the fly when and if it's needed, which is now only when the legacy client tracking code is in effect. The error handling in the legacy client tracker is also changed to handle the case where md5 is unavailable. In that case, we'll warn the admin with a KERN_ERR message and disable the client tracking. Signed-off-by: Jeff Layton 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 6c342bd806e..029217ad2cb 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -238,7 +238,6 @@ struct nfs4_client { struct list_head cl_delegations; struct list_head cl_lru; /* tail queue */ struct xdr_netobj cl_name; /* id generated by client */ - char cl_recdir[HEXDIR_LEN]; /* recovery dir */ nfs4_verifier cl_verifier; /* generated by client */ time_t cl_time; /* time of last lease renewal */ struct sockaddr_storage cl_addr; /* client ipaddress */ @@ -482,7 +481,6 @@ extern int nfsd4_create_callback_queue(void); extern void nfsd4_destroy_callback_queue(void); extern void nfsd4_shutdown_callback(struct nfs4_client *); extern void nfs4_put_delegation(struct nfs4_delegation *dp); -extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name); extern bool nfs4_has_reclaimed_state(const char *name); extern void release_session_client(struct nfsd4_session *); -- cgit v1.2.1 From c212cecfa21b3d30cd5cc2389754a46973ad9027 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 14 Nov 2012 18:21:10 +0300 Subject: nfsd: make nfs4_client network namespace dependent And use it's net where possible. Signed-off-by: Stanislav Kinsbursky 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 029217ad2cb..ca8ee8c3ae7 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -283,6 +283,7 @@ struct nfs4_client { unsigned long cl_cb_slot_busy; struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */ /* wait here for slots */ + struct net *net; }; static inline void -- cgit v1.2.1 From 52e19c09a183d82d99f10c284bc8b27933b1d1fc Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 14 Nov 2012 18:21:16 +0300 Subject: nfsd: make reclaim_str_hashtbl allocated per net This hash holds nfs4_clients info, which are network namespace aware. So let's make it allocated per network namespace. Note: this hash is used only by legacy tracker. So let's allocate hash in tracker init. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index ca8ee8c3ae7..26a912cdfe0 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -466,9 +466,10 @@ extern __be32 nfs4_preprocess_stateid_op(struct net *net, stateid_t *stateid, int flags, struct file **filp); extern void nfs4_lock_state(void); extern void nfs4_unlock_state(void); -void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *); -extern void nfs4_release_reclaim(void); -extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir); +void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *); +extern void nfs4_release_reclaim(struct nfsd_net *); +extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, + struct nfsd_net *nn); extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); extern void nfs4_free_openowner(struct nfs4_openowner *); extern void nfs4_free_lockowner(struct nfs4_lockowner *); @@ -482,8 +483,9 @@ extern int nfsd4_create_callback_queue(void); extern void nfsd4_destroy_callback_queue(void); extern void nfsd4_shutdown_callback(struct nfs4_client *); extern void nfs4_put_delegation(struct nfs4_delegation *dp); -extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name); -extern bool nfs4_has_reclaimed_state(const char *name); +extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name, + struct nfsd_net *nn); +extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn); extern void release_session_client(struct nfsd4_session *); extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); -- cgit v1.2.1 From 3320fef19b542b8df9606bd8e63990dc2a3fb330 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 14 Nov 2012 18:22:07 +0300 Subject: nfsd: use service net instead of hard-coded init_net This patch replaces init_net by SVC_NET(), where possible and also passes proper context to nested functions where required. Signed-off-by: Stanislav Kinsbursky 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 26a912cdfe0..bfe0106333c 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -470,7 +470,7 @@ void nfs4_remove_reclaim_record(struct nfs4_client_reclaim *, struct nfsd_net *) extern void nfs4_release_reclaim(struct nfsd_net *); extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(const char *recdir, struct nfsd_net *nn); -extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions); +extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions, struct nfsd_net *nn); extern void nfs4_free_openowner(struct nfs4_openowner *); extern void nfs4_free_lockowner(struct nfs4_lockowner *); extern int set_callback_cred(void); -- cgit v1.2.1 From 12760c6685624d65f8de078485c21b6a08e83409 Mon Sep 17 00:00:00 2001 From: Stanislav Kinsbursky Date: Wed, 14 Nov 2012 18:22:12 +0300 Subject: nfsd: pass nfsd_net instead of net to grace enders Passing net context looks as overkill. Signed-off-by: Stanislav Kinsbursky 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 bfe0106333c..2deb6a88e58 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -495,5 +495,5 @@ extern void nfsd4_client_tracking_exit(struct net *net); extern void nfsd4_client_record_create(struct nfs4_client *clp); extern void nfsd4_client_record_remove(struct nfs4_client *clp); extern int nfsd4_client_record_check(struct nfs4_client *clp); -extern void nfsd4_record_grace_done(struct net *net, time_t boot_time); +extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time); #endif /* NFSD4_STATE_H */ -- cgit v1.2.1 From f3c7521fe53a7892d8c8c4715f7c0f4add7b2e19 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Tue, 27 Nov 2012 09:35:10 -0500 Subject: NFSD: Fold fault_inject.h into state.h There were only a small number of functions in this file and since they all affect stored state I think it makes sense to put them in state.h instead. I also dropped most static inline declarations since there are no callers when fault injection is not enabled. Signed-off-by: Bryan Schumaker Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2deb6a88e58..b542bf2c0fe 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -496,4 +496,19 @@ extern void nfsd4_client_record_create(struct nfs4_client *clp); extern void nfsd4_client_record_remove(struct nfs4_client *clp); extern int nfsd4_client_record_check(struct nfs4_client *clp); extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time); + +/* nfs fault injection functions */ +#ifdef CONFIG_NFSD_FAULT_INJECTION +int nfsd_fault_inject_init(void); +void nfsd_fault_inject_cleanup(void); +void nfsd_forget_clients(u64); +void nfsd_forget_locks(u64); +void nfsd_forget_openowners(u64); +void nfsd_forget_delegations(u64); +void nfsd_recall_delegations(u64); +#else /* CONFIG_NFSD_FAULT_INJECTION */ +static inline int nfsd_fault_inject_init(void) { return 0; } +static inline void nfsd_fault_inject_cleanup(void) {} +#endif /* CONFIG_NFSD_FAULT_INJECTION */ + #endif /* NFSD4_STATE_H */ -- cgit v1.2.1 From 8ce54e0d82730ece61737c9fd7b61b28ab8c3390 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 29 Nov 2012 11:40:43 -0500 Subject: NFSD: Fault injection operations take a per-client forget function The eventual goal is to forget state based on ip address, so it makes sense to call this function in a for-each-client loop until the correct amount of state is forgotten. I also use this patch as an opportunity to rename the forget function from "func()" to "forget()". Signed-off-by: Bryan Schumaker Signed-off-by: J. Bruce Fields --- fs/nfsd/state.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'fs/nfsd/state.h') diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index b542bf2c0fe..423ac64ceb7 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -501,11 +501,13 @@ extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time); #ifdef CONFIG_NFSD_FAULT_INJECTION int nfsd_fault_inject_init(void); void nfsd_fault_inject_cleanup(void); -void nfsd_forget_clients(u64); -void nfsd_forget_locks(u64); -void nfsd_forget_openowners(u64); -void nfsd_forget_delegations(u64); -void nfsd_recall_delegations(u64); +u64 nfsd_for_n_state(u64, u64 (*)(struct nfs4_client *, u64)); + +u64 nfsd_forget_client(struct nfs4_client *, u64); +u64 nfsd_forget_client_locks(struct nfs4_client*, u64); +u64 nfsd_forget_client_openowners(struct nfs4_client *, u64); +u64 nfsd_forget_client_delegations(struct nfs4_client *, u64); +u64 nfsd_recall_client_delegations(struct nfs4_client *, u64); #else /* CONFIG_NFSD_FAULT_INJECTION */ static inline int nfsd_fault_inject_init(void) { return 0; } static inline void nfsd_fault_inject_cleanup(void) {} -- cgit v1.2.1 From 184c18471f7d0963ad5752692c4b441a546d88f1 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 29 Nov 2012 11:40:44 -0500 Subject: NFSD: Reading a fault injection file prints a state count I also log basic information that I can figure out about the type of state (such as number of locks for each client IP address). This can be useful for checking that state was actually dropped and later for checking if the client was able to recover. Signed-off-by: Bryan Schumaker 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 423ac64ceb7..4017f3553a6 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -508,6 +508,11 @@ u64 nfsd_forget_client_locks(struct nfs4_client*, u64); u64 nfsd_forget_client_openowners(struct nfs4_client *, u64); u64 nfsd_forget_client_delegations(struct nfs4_client *, u64); u64 nfsd_recall_client_delegations(struct nfs4_client *, u64); + +u64 nfsd_print_client(struct nfs4_client *, u64); +u64 nfsd_print_client_locks(struct nfs4_client *, u64); +u64 nfsd_print_client_openowners(struct nfs4_client *, u64); +u64 nfsd_print_client_delegations(struct nfs4_client *, u64); #else /* CONFIG_NFSD_FAULT_INJECTION */ static inline int nfsd_fault_inject_init(void) { return 0; } static inline void nfsd_fault_inject_cleanup(void) {} -- cgit v1.2.1 From 6c1e82a4b74ad0c8b45c833a4409f153199d9be4 Mon Sep 17 00:00:00 2001 From: Bryan Schumaker Date: Thu, 29 Nov 2012 11:40:46 -0500 Subject: NFSD: Forget state for a specific client Write the client's ip address to any state file and all appropriate state for that client will be forgotten. Signed-off-by: Bryan Schumaker 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 4017f3553a6..d1c229feed5 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -502,6 +502,7 @@ extern void nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time); int nfsd_fault_inject_init(void); void nfsd_fault_inject_cleanup(void); u64 nfsd_for_n_state(u64, u64 (*)(struct nfs4_client *, u64)); +struct nfs4_client *nfsd_find_client(struct sockaddr_storage *, size_t); u64 nfsd_forget_client(struct nfs4_client *, u64); u64 nfsd_forget_client_locks(struct nfs4_client*, u64); -- cgit v1.2.1