From: Andy Adamson <andros@xxxxxxxxxx> 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. Add an nfs_client struct backpointer to the session and refactor the session recovery routines to only require a struct nfs4_sessions parameter. Signed-off-by: Rahul Iyer <iyer@xxxxxxxxxx> Signed-off-by: Andy Adamson<andros@xxxxxxxxxx> Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> --- fs/nfs/client.c | 40 +++++++++++++++++++++++++++++++++++++ fs/nfs/internal.h | 1 + fs/nfs/nfs4_fs.h | 4 +++ fs/nfs/nfs4proc.c | 35 ++++++++++++++++++++++++++++++++ include/linux/nfs4_session.h | 45 ++++++++++++++++++++++++++++++++++++++++++ include/linux/nfs_fs_sb.h | 5 ++++ 6 files changed, 130 insertions(+), 0 deletions(-) create mode 100644 include/linux/nfs4_session.h diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 0a8a082..80091dc 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -37,6 +37,9 @@ #include <linux/in6.h> #include <net/ipv6.h> #include <linux/nfs_xdr.h> +#if defined(CONFIG_NFS_V4_1) +#include <linux/nfs4_session.h> +#endif /* CONFIG_NFS_V4_1 */ #include <asm/system.h> @@ -884,6 +887,11 @@ void nfs_free_server(struct nfs_server *server) list_del(&server->master_link); spin_unlock(&nfs_client_lock); +#ifdef CONFIG_NFS_V4_1 + if (server->nfs_client->cl_session != NULL) + nfs4_put_session(&server->nfs_client->cl_session); +#endif /* CONFIG_NFS_V4_1 */ + if (server->destroy != NULL) server->destroy(server); @@ -1110,6 +1118,34 @@ error: } /* + * Allocate and initialize a session if required + */ +int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt) +{ + int error = 0; + +#if defined(CONFIG_NFS_V4_1) + if (clp->cl_minorversion) { + struct nfs4_session *session = NULL; + /* + * Create the session and mark it expired. + * When a SEQUENCE operation encounters the expired session + * it will do session recovery to initialize it. + */ + session = nfs4_alloc_session(); + if (!session) + error = -ENOMEM; + else { + session->clnt = clnt; + session->clp = clp; + } + clp->cl_session = session; + } +#endif /* CONFIG_NFS_V4_1 */ + return error; +} + +/* * Create a version 4 volume record * - keyed on server and FSID */ @@ -1139,6 +1175,10 @@ retry: BUG_ON(!server->nfs_client->rpc_ops); BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); + error = nfs4_init_session(server->nfs_client, server->client); + if (error) + goto error; + /* Probe the root fh to retrieve its FSID */ error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); if (error < 0) diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8386e99..9b2228f 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -82,6 +82,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 int nfs4_init_session(struct nfs_client *clp, struct rpc_clnt *clnt); #ifdef CONFIG_PROC_FS extern int __init nfs_fs_proc_init(void); extern void nfs_fs_proc_exit(void); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 5fb7382..4b13945 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -188,6 +188,10 @@ extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops; extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops; +#if defined(CONFIG_NFS_V4_1) +extern void nfs4_put_session(struct nfs4_session **session); +extern struct nfs4_session *nfs4_alloc_session(void); +#endif /* CONFIG_NFS_V4_1 */ extern const u32 nfs4_fattr_bitmap[2]; extern const u32 nfs4_statfs_bitmap[2]; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f87d4de..8e373e9 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -53,6 +53,9 @@ #include "delegation.h" #include "internal.h" #include "iostat.h" +#if defined(CONFIG_NFS_V4_1) +#include <linux/nfs4_session.h> +#endif /* CONFIG_NFS_V4_1 */ #define NFSDBG_FACILITY NFSDBG_PROC @@ -3679,6 +3682,38 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, return status; } +#ifdef CONFIG_NFS_V4_1 +struct nfs4_session *nfs4_alloc_session(void) +{ + struct nfs4_session *session; + + session = kzalloc(sizeof(struct nfs4_session), GFP_ATOMIC); + if (!session) + return NULL; + + atomic_set(&session->ref_count, 1); + + return session; +} + +static void nfs4_free_session(struct nfs4_session *session) +{ + dprintk("%s: freeing session %p\n", __func__, session); + kfree(session); +} + +void nfs4_put_session(struct nfs4_session **session) +{ + dprintk("--> nfs4_put_session()\n"); + if (atomic_dec_and_test(&((*session)->ref_count))) { + nfs4_free_session(*session); + *session = NULL; + } + dprintk("<-- nfs4_put_session()\n"); +} + +#endif /* CONFIG_NFS_V4_1 */ + struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = { .recover_open = nfs4_open_reclaim, .recover_lock = nfs4_lock_reclaim, diff --git a/include/linux/nfs4_session.h b/include/linux/nfs4_session.h new file mode 100644 index 0000000..36c0f94 --- /dev/null +++ b/include/linux/nfs4_session.h @@ -0,0 +1,45 @@ +#ifndef _NFS4_SESSIONS_H +#define _NFS4_SESSIONS_H + +#if defined(CONFIG_NFS_V4_1) + +#include <linux/nfs4.h> +#include <linux/smp_lock.h> +#include <linux/sunrpc/sched.h> + +struct nfs4_channel_attrs { + u32 headerpadsz; + u32 max_rqst_sz; + u32 max_resp_sz; + u32 max_resp_sz_cached; + u32 max_ops; + u32 max_reqs; + u32 rdma_attrs; +}; + +struct nfs4_channel { + struct nfs4_channel_attrs chan_attrs; + struct rpc_clnt *rpc_client; +}; + +/* + * Session related parameters + */ +struct nfs4_session { + nfs41_sessionid sess_id; + u32 flags; + unsigned long session_state; + u32 hash_alg; + u32 ssv_len; + + /* The fore and back channel */ + struct nfs4_channel fore_channel; + struct nfs4_channel back_channel; + + atomic_t ref_count; + struct rpc_clnt *clnt; + struct nfs_client *clp; +}; + +#endif /* CONFIG_NFS_V4_1 */ +#endif diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index 80e0fc3..15c0aa5 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h @@ -7,6 +7,7 @@ #include <asm/atomic.h> +struct nfs4_session; struct nfs_iostats; struct nlm_host; @@ -72,6 +73,10 @@ struct nfs_client { unsigned char cl_id_uniquifier; u32 cl_minorversion; #endif /* CONFIG_NFS_V4 */ + +#ifdef CONFIG_NFS_V4_1 + struct nfs4_session *cl_session; /* sharred session */ +#endif /* CONFIG_NFS_V4_1 */ }; #ifdef CONFIG_NFS_V4 -- 1.6.0.2 -- 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