From 3fd5be9e19921a89d9ed78d6a708a379a6c3c76a Mon Sep 17 00:00:00 2001 From: Mike Sager Date: Wed, 1 Apr 2009 09:21:48 -0400 Subject: nfs41: add mount command option minorversion mount -t nfs4 -o minorversion=[0|1] specifies whether to use 4.0 or 4.1. By default, the minorversion is set to 0. Signed-off-by: Mike Sager [set default minorversion to 0 as per Trond and SteveD's request] Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index e4d6a8348adf..ffa6bd54d439 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -44,6 +44,7 @@ struct nfs_parsed_mount_data { unsigned int auth_flavor_len; rpc_authflavor_t auth_flavors[1]; char *client_address; + unsigned int minorversion; char *fscache_uniq; struct { -- cgit v1.2.2 From 557134a39c8d2ab79d8b8d53438e03e29feb5ec4 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 1 Apr 2009 09:21:53 -0400 Subject: nfs41: sessions client infrastructure NFSv4.1 Sessions basic data types, initialization, and destruction. The session is always associated with a struct nfs_client that holds the exchange_id results. Signed-off-by: Rahul Iyer Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [remove extraneous rpc_clnt pointer, use the struct nfs_client cl_rpcclient. remove the rpc_clnt parameter from nfs4 nfs4_init_session] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [Use the presence of a session to determine behaviour instead of the minorversion number.] Signed-off-by: Andy Adamson [constified nfs4_has_session's struct nfs_client parameter] Signed-off-by: Benny Halevy [Rename nfs4_put_session() to nfs4_destroy_session() and call it from nfs4_free_client() not nfs4_free_server(). Also get rid of nfs4_get_session() and the ref_count in nfs4_session struct as keeping track of nfs_client should be sufficient] Signed-off-by: Alexandros Batsakis [nfs41: pass rsize and wsize into nfs4_init_session] Signed-off-by: Andy Adamson [separated out removal of rpc_clnt parameter from nfs4_init_session ot a patch of its own] Signed-off-by: Benny Halevy [Pass the nfs_client pointer into nfs4_alloc_session] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [nfs41: don't assign to session->clp->cl_session in nfs4_destroy_session] [nfs41: fixup nfs4_clear_client_minor_version] [introduce nfs4_clear_client_minor_version() in this patch] Signed-off-by: Benny Halevy [Refactor nfs4_init_session] Moved session allocation into nfs4_init_client_minor_version, called from nfs4_init_client. Leave rwise and wsize initialization in nfs4_init_session, called from nfs4_init_server. Reverted moving of nfs_fsid definition to nfs_fs_sb.h Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [nfs41: Move NFS4_MAX_SLOT_TABLE define from under CONFIG_NFS_V4_1] [Fix comile error when CONFIG_NFS_V4_1 is not set.] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [moved nfs4_init_slot_table definition to "create_session operation"] Signed-off-by: Benny Halevy [nfs41: alloc session with GFP_KERNEL] Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index ffa6bd54d439..7cef45db9257 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -206,6 +206,18 @@ extern int nfs4_path_walk(struct nfs_server *server, const char *path); #endif +/* + * Determine if sessions are in use. + */ +static inline int nfs4_has_session(const struct nfs_client *clp) +{ +#ifdef CONFIG_NFS_V4_1 + if (clp->cl_session) + return 1; +#endif /* CONFIG_NFS_V4_1 */ + return 0; +} + /* * Determine the device name as a string */ -- cgit v1.2.2 From cccef3b96a4759ae0790452280c00ea505412157 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 1 Apr 2009 09:22:03 -0400 Subject: nfs41: introduce nfs4_call_sync Use nfs4_call_sync rather than rpc_call_sync to provide for a nfs41 sessions-enabled interface for sessions manipulation. The nfs41 rpc logic uses the rpc_call_prepare method to recover and create the session, as well as selecting a free slot id and the rpc_call_done to free the slot and update slot table related metadata. In the coming patches we'll add rpc prepare and done routines for setting up the sequence op and processing the sequence result. Signed-off-by: Benny Halevy [nfs41: nfs4_call_sync] As per 11-14-08 review. Squash into "nfs41: introduce nfs4_call_sync" and "nfs41: nfs4_setup_sequence" Define two functions one for v4 and one for v41 add a pointer to struct nfs4_client to the correct one. Signed-off-by: Andy Adamson [added BUG() in _nfs4_call_sync_session if !CONFIG_NFS_V4_1] Signed-off-by: Benny Halevy [nfs41: check for session not minorversion] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [group minorversion specific stuff together] Signed-off-by: Alexandros Batsakis Signed-off-by: Benny Halevy Signed-off-by: Andy Adamson [nfs41: fixup nfs4_clear_client_minor_version] [introduce nfs4_init_client_minor_version() in this patch] Signed-off-by: Benny Halevy [cleaned-up patch: got rid of nfs_call_sync_t, dprintks, cosmetics, extra server defs] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 7cef45db9257..8d67c2865dc3 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -206,6 +206,18 @@ extern int nfs4_path_walk(struct nfs_server *server, const char *path); #endif +/* nfs4proc.c */ +extern int _nfs4_call_sync(struct nfs_server *server, + struct rpc_message *msg, + struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, + int cache_reply); +extern int _nfs4_call_sync_session(struct nfs_server *server, + struct rpc_message *msg, + struct nfs4_sequence_args *args, + struct nfs4_sequence_res *res, + int cache_reply); + /* * Determine if sessions are in use. */ -- cgit v1.2.2 From 13615871cdf8e8263626a817c350c6978a6483fe Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 1 Apr 2009 09:22:17 -0400 Subject: nfs41: nfs41_sequence_free_slot [from nfs41: separate free slot from sequence done] Don't free the slot until after all rpc_restart_calls have completed. Session reset will require more work. As noted by Trond, since we're using rpc_wake_up_next rather than rpc_wake_up() we must always wake up the next task in the queue either by going through nfs4_free_slot, or just calling rpc_wake_up_next if no slot is to be freed. [nfs41: sequence res use slotid] [nfs41: remove SEQ4_STATUS_USE_TK_STATUS] [got rid of nfs4_sequence_res.sr_session, use nfs_client.cl_session instead] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [nfs41: rpc_wake_up_next if sessions slot was not consumed.] Signed-off-by: Benny Halevy [nfs41: nfs4_sequence_free_slot use nfs_client for data server] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8d67c2865dc3..12f4c5e6fd39 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -230,6 +230,20 @@ static inline int nfs4_has_session(const struct nfs_client *clp) return 0; } +#ifdef CONFIG_NFS_V4_1 +extern void nfs41_sequence_free_slot(const struct nfs_client *, + struct nfs4_sequence_res *res); +#endif /* CONFIG_NFS_V4_1 */ + +static inline void nfs4_sequence_free_slot(const struct nfs_client *clp, + struct nfs4_sequence_res *res) +{ +#ifdef CONFIG_NFS_V4_1 + if (nfs4_has_session(clp)) + nfs41_sequence_free_slot(clp, res); +#endif /* CONFIG_NFS_V4_1 */ +} + /* * Determine the device name as a string */ -- cgit v1.2.2 From f11c88af26453aee2823a1fd9120d0cd8dae7b9a Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 1 Apr 2009 09:22:25 -0400 Subject: nfs41: read sequence setup/done support Implement the read rpc_call_prepare method for asynchronuos nfs rpcs, call nfs41_setup_sequence from respective rpc_call_validate_args methods. Call nfs4_sequence_done from respective rpc_call_done methods. Note that we need to pass a pointer to the nfs_server in calls data for passing on to nfs4_sequence_done. Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [pnfs: client data server write validate and release] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [move the nfs4_sequence_free_slot call in nfs_readpage_retry from] [nfs41: separate free slot from sequence done] [remove nfs_readargs.nfs_server, use calldata->inode instead] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [nfs41: Support sessions with O_DIRECT] Signed-off-by: Dean Hildebrand Signed-off-by: Benny Halevy [nfs41: nfs4_sequence_free_slot use nfs_client for data server] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 12f4c5e6fd39..988c8b9aa78b 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -206,6 +206,9 @@ extern int nfs4_path_walk(struct nfs_server *server, const char *path); #endif +/* read.c */ +extern void nfs_read_prepare(struct rpc_task *task, void *calldata); + /* nfs4proc.c */ extern int _nfs4_call_sync(struct nfs_server *server, struct rpc_message *msg, -- cgit v1.2.2 From def6ed7ef45ed19c3d6ca765f3bfdff1fe4c6bba Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 1 Apr 2009 09:22:26 -0400 Subject: nfs41 write sequence setup done support Separate write calls from nfs41: sequence setup/done support Implement the write rpc_call_prepare method for asynchronuos nfs rpcs, call nfs41_setup_sequence from respective rpc_call_validate_args methods. Call nfs4_sequence_done from respective rpc_call_done methods. Note that we need to pass a pointer to the nfs_server in calls data for passing on to nfs4_sequence_done. Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [pnfs: client data server write validate and release] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [move the nfs4_sequence_free_slot call in nfs_readpage_retry from] [nfs41: separate free slot from sequence done Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [nfs41: Support sessions with O_DIRECT.] Signed-off-by: Dean Hildebrand Signed-off-by: Benny Halevy [nfs41: nfs4_sequence_free_slot use nfs_client for data server] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 988c8b9aa78b..f62bc5226155 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -209,6 +209,9 @@ extern int nfs4_path_walk(struct nfs_server *server, /* read.c */ extern void nfs_read_prepare(struct rpc_task *task, void *calldata); +/* write.c */ +extern void nfs_write_prepare(struct rpc_task *task, void *calldata); + /* nfs4proc.c */ extern int _nfs4_call_sync(struct nfs_server *server, struct rpc_message *msg, -- cgit v1.2.2 From 76db6d9500caeaa774a3e32a997eba30bbdc176b Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 1 Apr 2009 09:22:38 -0400 Subject: nfs41: add session setup to the state manager At mount, nfs_alloc_client sets the cl_state NFS4CLNT_LEASE_EXPIRED bit and nfs4_alloc_session sets the NFS4CLNT_SESSION_SETUP bit, so both bits are set when nfs4_lookup_root calls nfs4_recover_expired_lease which schedules the nfs4_state_manager and waits for it to complete. Place the session setup after the clientid establishment in nfs4_state_manager so that the session is setup right after the clientid has been established without rescheduling the state manager. Unlike nfsv4.0, the nfs_client struct is not ready to use until the session has been established. Postpone marking the nfs_client struct to NFS_CS_READY until after a successful CREATE_SESSION call so that other threads cannot use the client until the session is established. If the EXCHANGE_ID call fails and the session has not been setup (the NFS4CLNT_SESSION_SETUP bit is set), mark the client with the error and return. If the session setup CREATE_SESSION call fails with NFS4ERR_STALE_CLIENTID which could occur due to server reboot or network partition inbetween the EXCHANGE_ID and CREATE_SESSION call, reset the NFS4CLNT_LEASE_EXPIRED and NFS4CLNT_SESSION_SETUP bits and try again. If the CREATE_SESSION call fails with other errors, mark the client with the error and return. Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [nfs41: NFS_CS_SESSION_SETUP cl_cons_state for back channel setup] On session setup, the CREATE_SESSION reply races with the server back channel probe which needs to succeed to setup the back channel. Set a new cl_cons_state NFS_CS_SESSION_SETUP just prior to the CREATE_SESSION call and add it as a valid state to nfs_find_client so that the client back channel can find the nfs_client struct and won't drop the server backchannel probe. Use a new cl_cons_state so that NFSv4.0 back channel behaviour which only sets NFS_CS_READY is unchanged. Adjust waiting on the nfs_client_active_wq accordingly. Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [nfs41: rename NFS_CS_SESSION_SETUP to NFS_CS_SESSION_INITING] Signed-off-by: Andy Adamson [nfs41: set NFS_CL_SESSION_INITING in alloc_session] Signed-off-by: Andy Adamson [nfs41: move session setup into a function] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [moved nfs4_proc_create_session declaration here] Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index f62bc5226155..f3b310e8ea03 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -100,6 +100,7 @@ extern void nfs_free_server(struct nfs_server *server); extern struct nfs_server *nfs_clone_server(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); +extern void nfs_mark_client_ready(struct nfs_client *clp, int state); #ifdef CONFIG_PROC_FS extern int __init nfs_fs_proc_init(void); extern void nfs_fs_proc_exit(void); -- cgit v1.2.2 From eedc020e718b8ce45381383ec66030f09eb02a1e Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 1 Apr 2009 09:22:41 -0400 Subject: nfs41: use rpc prepare call state for session reset [nfs41: change nfs4_restart_rpc argument] [nfs41: check for session not minorversion] [nfs41: trigger the state manager for session reset] Signed-off-by: Andy Adamson Signed-off-by: Benny Halevy [always define nfs4_restart_rpc] Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index f3b310e8ea03..78508f29c03a 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -2,6 +2,7 @@ * NFS internal definitions */ +#include "nfs4_fs.h" #include #include @@ -17,6 +18,18 @@ struct nfs_string; */ #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) +/* + * Determine if sessions are in use. + */ +static inline int nfs4_has_session(const struct nfs_client *clp) +{ +#ifdef CONFIG_NFS_V4_1 + if (clp->cl_session) + return 1; +#endif /* CONFIG_NFS_V4_1 */ + return 0; +} + struct nfs_clone_mount { const struct super_block *sb; const struct dentry *dentry; @@ -148,6 +161,20 @@ extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int); extern struct rpc_procinfo nfs3_procedures[]; extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int); +/* nfs4proc.c */ +static inline void nfs4_restart_rpc(struct rpc_task *task, + const struct nfs_client *clp) +{ +#ifdef CONFIG_NFS_V4_1 + if (nfs4_has_session(clp) && + test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)) { + rpc_restart_call_prepare(task); + return; + } +#endif /* CONFIG_NFS_V4_1 */ + rpc_restart_call(task); +} + /* nfs4xdr.c */ #ifdef CONFIG_NFS_V4 extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus); @@ -225,18 +252,6 @@ extern int _nfs4_call_sync_session(struct nfs_server *server, struct nfs4_sequence_res *res, int cache_reply); -/* - * Determine if sessions are in use. - */ -static inline int nfs4_has_session(const struct nfs_client *clp) -{ -#ifdef CONFIG_NFS_V4_1 - if (clp->cl_session) - return 1; -#endif /* CONFIG_NFS_V4_1 */ - return 0; -} - #ifdef CONFIG_NFS_V4_1 extern void nfs41_sequence_free_slot(const struct nfs_client *, struct nfs4_sequence_res *res); -- cgit v1.2.2 From 008f55d0e019943323c20a03493a2ba5672a4cc8 Mon Sep 17 00:00:00 2001 From: Benny Halevy Date: Wed, 1 Apr 2009 09:22:50 -0400 Subject: nfs41: recover lease in _nfs4_lookup_root This creates the nfsv4.1 session on mount. Signed-off-by: Benny Halevy Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 78508f29c03a..acee3274d275 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -114,6 +114,7 @@ extern struct nfs_server *nfs_clone_server(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); extern void nfs_mark_client_ready(struct nfs_client *clp, int state); +extern int nfs4_check_client_ready(struct nfs_client *clp); #ifdef CONFIG_PROC_FS extern int __init nfs_fs_proc_init(void); extern void nfs_fs_proc_exit(void); -- cgit v1.2.2 From a14017db2852f9393a401a0f64053c331003babf Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 17 Jun 2009 18:02:12 -0700 Subject: NFS: add XDR decoder for mountd version 3 auth-flavor lists Introduce an xdr_stream-based XDR decoder that can unpack the auth- flavor list returned in a MNT3 reply. The nfs_mount() function's caller allocates an array, and passes the size and a pointer to it. The decoder decodes all the flavors it can into the array, and returns the number of decoded flavors. If the caller is not interested in the auth flavors, it can pass a value of zero as the size of the pre-allocated array. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index e4d6a8348adf..0207758de44a 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -29,6 +29,12 @@ struct nfs_clone_mount { rpc_authflavor_t authflavor; }; +/* + * Note: RFC 1813 doesn't limit the number of auth flavors that + * a server can return, so make something up. + */ +#define NFS_MAX_SECFLAVORS (12) + /* * In-kernel mount arguments */ -- cgit v1.2.2 From 8e02f6b9aae9b265064f929c6df15222b9baf256 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 17 Jun 2009 18:02:13 -0700 Subject: NFS: Update MNT and MNT3 reply decoding functions Solder xdr_stream-based XDR decoding functions into the in-kernel mountd client that are more careful about checking data types and watching for buffer overflows. The new MNT3 decoder includes support for auth-flavor list decoding. The "_sz" macro for MNT3 replies was missing the size of the file handle. I've added this back, and included the size of the auth flavor array. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/nfs/internal.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs/nfs/internal.h') diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 0207758de44a..10cf1110df48 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -83,6 +83,8 @@ struct nfs_mount_request { unsigned short protocol; struct nfs_fh *fh; int noresvport; + unsigned int *auth_flav_len; + rpc_authflavor_t *auth_flavs; }; extern int nfs_mount(struct nfs_mount_request *info); -- cgit v1.2.2