2 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
3 * Written by David Howells (dhowells@redhat.com)
5 #include <linux/nfs_fs.h>
6 #include <linux/nfs_idmap.h>
7 #include <linux/sunrpc/auth.h>
8 #include <linux/sunrpc/xprt.h>
9 #include <linux/sunrpc/bc_xprt.h>
13 #define NFSDBG_FACILITY NFSDBG_CLIENT
16 * Initialize the NFS4 callback service
18 static int nfs4_init_callback(struct nfs_client
*clp
)
22 if (clp
->rpc_ops
->version
== 4) {
23 struct rpc_xprt
*xprt
;
25 xprt
= rcu_dereference_raw(clp
->cl_rpcclient
->cl_xprt
);
27 if (nfs4_has_session(clp
)) {
28 error
= xprt_setup_backchannel(xprt
,
29 NFS41_BC_MIN_CALLBACKS
);
34 error
= nfs_callback_up(clp
->cl_mvops
->minor_version
, xprt
);
36 dprintk("%s: failed to start callback. Error = %d\n",
40 __set_bit(NFS_CS_CALLBACK
, &clp
->cl_res_state
);
46 * Initialize the minor version specific parts of an NFS4 client record
48 static int nfs4_init_client_minor_version(struct nfs_client
*clp
)
50 #if defined(CONFIG_NFS_V4_1)
51 if (clp
->cl_mvops
->minor_version
) {
52 struct nfs4_session
*session
= NULL
;
54 * Create the session and mark it expired.
55 * When a SEQUENCE operation encounters the expired session
56 * it will do session recovery to initialize it.
58 session
= nfs4_alloc_session(clp
);
62 clp
->cl_session
= session
;
64 * The create session reply races with the server back
65 * channel probe. Mark the client NFS_CS_SESSION_INITING
66 * so that the client back channel can find the
69 nfs_mark_client_ready(clp
, NFS_CS_SESSION_INITING
);
71 #endif /* CONFIG_NFS_V4_1 */
73 return nfs4_init_callback(clp
);
77 * nfs4_init_client - Initialise an NFS4 client record
79 * @clp: nfs_client to initialise
80 * @timeparms: timeout parameters for underlying RPC transport
81 * @ip_addr: callback IP address in presentation format
82 * @authflavor: authentication flavor for underlying RPC transport
84 * Returns pointer to an NFS client, or an ERR_PTR value.
86 struct nfs_client
*nfs4_init_client(struct nfs_client
*clp
,
87 const struct rpc_timeout
*timeparms
,
89 rpc_authflavor_t authflavour
)
91 char buf
[INET6_ADDRSTRLEN
+ 1];
94 if (clp
->cl_cons_state
== NFS_CS_READY
) {
95 /* the client is initialised already */
96 dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp
);
100 /* Check NFS protocol revision and initialize RPC op vector */
101 clp
->rpc_ops
= &nfs_v4_clientops
;
103 __set_bit(NFS_CS_DISCRTRY
, &clp
->cl_flags
);
104 error
= nfs_create_rpc_client(clp
, timeparms
, authflavour
);
108 /* If no clientaddr= option was specified, find a usable cb address */
109 if (ip_addr
== NULL
) {
110 struct sockaddr_storage cb_addr
;
111 struct sockaddr
*sap
= (struct sockaddr
*)&cb_addr
;
113 error
= rpc_localaddr(clp
->cl_rpcclient
, sap
, sizeof(cb_addr
));
116 error
= rpc_ntop(sap
, buf
, sizeof(buf
));
119 ip_addr
= (const char *)buf
;
121 strlcpy(clp
->cl_ipaddr
, ip_addr
, sizeof(clp
->cl_ipaddr
));
123 error
= nfs_idmap_new(clp
);
125 dprintk("%s: failed to create idmapper. Error = %d\n",
129 __set_bit(NFS_CS_IDMAP
, &clp
->cl_res_state
);
131 error
= nfs4_init_client_minor_version(clp
);
135 if (!nfs4_has_session(clp
))
136 nfs_mark_client_ready(clp
, NFS_CS_READY
);
140 nfs_mark_client_ready(clp
, error
);
142 dprintk("<-- nfs4_init_client() = xerror %d\n", error
);
143 return ERR_PTR(error
);