2 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
3 * Written by David Howells (dhowells@redhat.com)
5 #include <linux/module.h>
6 #include <linux/nfs_fs.h>
7 #include <linux/nfs_idmap.h>
8 #include <linux/nfs_mount.h>
9 #include <linux/sunrpc/addr.h>
10 #include <linux/sunrpc/auth.h>
11 #include <linux/sunrpc/xprt.h>
12 #include <linux/sunrpc/bc_xprt.h>
15 #include "delegation.h"
16 #include "nfs4session.h"
20 #define NFSDBG_FACILITY NFSDBG_CLIENT
23 * Get a unique NFSv4.0 callback identifier which will be used
24 * by the V4.0 callback service to lookup the nfs_client struct
26 static int nfs_get_cb_ident_idr(struct nfs_client
*clp
, int minorversion
)
29 struct nfs_net
*nn
= net_generic(clp
->cl_net
, nfs_net_id
);
31 if (clp
->rpc_ops
->version
!= 4 || minorversion
!= 0)
34 if (!idr_pre_get(&nn
->cb_ident_idr
, GFP_KERNEL
))
36 spin_lock(&nn
->nfs_client_lock
);
37 ret
= idr_get_new(&nn
->cb_ident_idr
, clp
, &clp
->cl_cb_ident
);
38 spin_unlock(&nn
->nfs_client_lock
);
44 #ifdef CONFIG_NFS_V4_1
45 static void nfs4_shutdown_session(struct nfs_client
*clp
)
47 if (nfs4_has_session(clp
)) {
48 nfs4_destroy_session(clp
->cl_session
);
49 nfs4_destroy_clientid(clp
);
53 #else /* CONFIG_NFS_V4_1 */
54 static void nfs4_shutdown_session(struct nfs_client
*clp
)
57 #endif /* CONFIG_NFS_V4_1 */
59 struct nfs_client
*nfs4_alloc_client(const struct nfs_client_initdata
*cl_init
)
62 struct nfs_client
*clp
= nfs_alloc_client(cl_init
);
66 err
= nfs_get_cb_ident_idr(clp
, cl_init
->minorversion
);
70 spin_lock_init(&clp
->cl_lock
);
71 INIT_DELAYED_WORK(&clp
->cl_renewd
, nfs4_renew_state
);
72 rpc_init_wait_queue(&clp
->cl_rpcwaitq
, "NFS client");
73 clp
->cl_state
= 1 << NFS4CLNT_LEASE_EXPIRED
;
74 clp
->cl_minorversion
= cl_init
->minorversion
;
75 clp
->cl_mvops
= nfs_v4_minor_ops
[cl_init
->minorversion
];
84 * Destroy the NFS4 callback service
86 static void nfs4_destroy_callback(struct nfs_client
*clp
)
88 if (__test_and_clear_bit(NFS_CS_CALLBACK
, &clp
->cl_res_state
))
89 nfs_callback_down(clp
->cl_mvops
->minor_version
, clp
->cl_net
);
92 static void nfs4_shutdown_client(struct nfs_client
*clp
)
94 if (__test_and_clear_bit(NFS_CS_RENEWD
, &clp
->cl_res_state
))
95 nfs4_kill_renewd(clp
);
96 nfs4_shutdown_session(clp
);
97 nfs4_destroy_callback(clp
);
98 if (__test_and_clear_bit(NFS_CS_IDMAP
, &clp
->cl_res_state
))
99 nfs_idmap_delete(clp
);
101 rpc_destroy_wait_queue(&clp
->cl_rpcwaitq
);
102 kfree(clp
->cl_serverowner
);
103 kfree(clp
->cl_serverscope
);
104 kfree(clp
->cl_implid
);
107 void nfs4_free_client(struct nfs_client
*clp
)
109 nfs4_shutdown_client(clp
);
110 nfs_free_client(clp
);
114 * Initialize the NFS4 callback service
116 static int nfs4_init_callback(struct nfs_client
*clp
)
120 if (clp
->rpc_ops
->version
== 4) {
121 struct rpc_xprt
*xprt
;
123 xprt
= rcu_dereference_raw(clp
->cl_rpcclient
->cl_xprt
);
125 if (nfs4_has_session(clp
)) {
126 error
= xprt_setup_backchannel(xprt
,
127 NFS41_BC_MIN_CALLBACKS
);
132 error
= nfs_callback_up(clp
->cl_mvops
->minor_version
, xprt
);
134 dprintk("%s: failed to start callback. Error = %d\n",
138 __set_bit(NFS_CS_CALLBACK
, &clp
->cl_res_state
);
144 * Initialize the minor version specific parts of an NFS4 client record
146 static int nfs4_init_client_minor_version(struct nfs_client
*clp
)
148 #if defined(CONFIG_NFS_V4_1)
149 if (clp
->cl_mvops
->minor_version
) {
150 struct nfs4_session
*session
= NULL
;
152 * Create the session and mark it expired.
153 * When a SEQUENCE operation encounters the expired session
154 * it will do session recovery to initialize it.
156 session
= nfs4_alloc_session(clp
);
160 clp
->cl_session
= session
;
162 * The create session reply races with the server back
163 * channel probe. Mark the client NFS_CS_SESSION_INITING
164 * so that the client back channel can find the
167 nfs_mark_client_ready(clp
, NFS_CS_SESSION_INITING
);
169 #endif /* CONFIG_NFS_V4_1 */
171 return nfs4_init_callback(clp
);
175 * nfs4_init_client - Initialise an NFS4 client record
177 * @clp: nfs_client to initialise
178 * @timeparms: timeout parameters for underlying RPC transport
179 * @ip_addr: callback IP address in presentation format
180 * @authflavor: authentication flavor for underlying RPC transport
182 * Returns pointer to an NFS client, or an ERR_PTR value.
184 struct nfs_client
*nfs4_init_client(struct nfs_client
*clp
,
185 const struct rpc_timeout
*timeparms
,
187 rpc_authflavor_t authflavour
)
189 char buf
[INET6_ADDRSTRLEN
+ 1];
190 struct nfs_client
*old
;
193 if (clp
->cl_cons_state
== NFS_CS_READY
) {
194 /* the client is initialised already */
195 dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp
);
199 /* Check NFS protocol revision and initialize RPC op vector */
200 clp
->rpc_ops
= &nfs_v4_clientops
;
202 __set_bit(NFS_CS_DISCRTRY
, &clp
->cl_flags
);
203 error
= nfs_create_rpc_client(clp
, timeparms
, authflavour
);
207 /* If no clientaddr= option was specified, find a usable cb address */
208 if (ip_addr
== NULL
) {
209 struct sockaddr_storage cb_addr
;
210 struct sockaddr
*sap
= (struct sockaddr
*)&cb_addr
;
212 error
= rpc_localaddr(clp
->cl_rpcclient
, sap
, sizeof(cb_addr
));
215 error
= rpc_ntop(sap
, buf
, sizeof(buf
));
218 ip_addr
= (const char *)buf
;
220 strlcpy(clp
->cl_ipaddr
, ip_addr
, sizeof(clp
->cl_ipaddr
));
222 error
= nfs_idmap_new(clp
);
224 dprintk("%s: failed to create idmapper. Error = %d\n",
228 __set_bit(NFS_CS_IDMAP
, &clp
->cl_res_state
);
230 error
= nfs4_init_client_minor_version(clp
);
234 if (!nfs4_has_session(clp
))
235 nfs_mark_client_ready(clp
, NFS_CS_READY
);
237 error
= nfs4_discover_server_trunking(clp
, &old
);
241 clp
->cl_preserve_clid
= true;
244 atomic_inc(&clp
->cl_count
);
250 nfs_mark_client_ready(clp
, error
);
252 dprintk("<-- nfs4_init_client() = xerror %d\n", error
);
253 return ERR_PTR(error
);
257 * SETCLIENTID just did a callback update with the callback ident in
258 * "drop," but server trunking discovery claims "drop" and "keep" are
259 * actually the same server. Swap the callback IDs so that "keep"
260 * will continue to use the callback ident the server now knows about,
261 * and so that "keep"'s original callback ident is destroyed when
264 static void nfs4_swap_callback_idents(struct nfs_client
*keep
,
265 struct nfs_client
*drop
)
267 struct nfs_net
*nn
= net_generic(keep
->cl_net
, nfs_net_id
);
268 unsigned int save
= keep
->cl_cb_ident
;
270 if (keep
->cl_cb_ident
== drop
->cl_cb_ident
)
273 dprintk("%s: keeping callback ident %u and dropping ident %u\n",
274 __func__
, keep
->cl_cb_ident
, drop
->cl_cb_ident
);
276 spin_lock(&nn
->nfs_client_lock
);
278 idr_replace(&nn
->cb_ident_idr
, keep
, drop
->cl_cb_ident
);
279 keep
->cl_cb_ident
= drop
->cl_cb_ident
;
281 idr_replace(&nn
->cb_ident_idr
, drop
, save
);
282 drop
->cl_cb_ident
= save
;
284 spin_unlock(&nn
->nfs_client_lock
);
288 * nfs40_walk_client_list - Find server that recognizes a client ID
290 * @new: nfs_client with client ID to test
291 * @result: OUT: found nfs_client, or new
292 * @cred: credential to use for trunking test
294 * Returns zero, a negative errno, or a negative NFS4ERR status.
295 * If zero is returned, an nfs_client pointer is planted in "result."
297 * NB: nfs40_walk_client_list() relies on the new nfs_client being
298 * the last nfs_client on the list.
300 int nfs40_walk_client_list(struct nfs_client
*new,
301 struct nfs_client
**result
,
302 struct rpc_cred
*cred
)
304 struct nfs_net
*nn
= net_generic(new->cl_net
, nfs_net_id
);
305 struct nfs_client
*pos
, *n
, *prev
= NULL
;
306 struct nfs4_setclientid_res clid
= {
307 .clientid
= new->cl_clientid
,
308 .confirm
= new->cl_confirm
,
312 spin_lock(&nn
->nfs_client_lock
);
313 list_for_each_entry_safe(pos
, n
, &nn
->nfs_client_list
, cl_share_link
) {
314 /* If "pos" isn't marked ready, we can't trust the
315 * remaining fields in "pos" */
316 if (pos
->cl_cons_state
< NFS_CS_READY
)
319 if (pos
->rpc_ops
!= new->rpc_ops
)
322 if (pos
->cl_proto
!= new->cl_proto
)
325 if (pos
->cl_minorversion
!= new->cl_minorversion
)
328 if (pos
->cl_clientid
!= new->cl_clientid
)
331 atomic_inc(&pos
->cl_count
);
332 spin_unlock(&nn
->nfs_client_lock
);
335 nfs_put_client(prev
);
337 status
= nfs4_proc_setclientid_confirm(pos
, &clid
, cred
);
339 nfs4_swap_callback_idents(pos
, new);
343 dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
344 __func__
, pos
, atomic_read(&pos
->cl_count
));
347 if (status
!= -NFS4ERR_STALE_CLIENTID
) {
349 dprintk("NFS: <-- %s status = %d, no result\n",
354 spin_lock(&nn
->nfs_client_lock
);
359 * No matching nfs_client found. This should be impossible,
360 * because the new nfs_client has already been added to
361 * nfs_client_list by nfs_get_client().
363 * Don't BUG(), since the caller is holding a mutex.
366 nfs_put_client(prev
);
367 spin_unlock(&nn
->nfs_client_lock
);
368 pr_err("NFS: %s Error: no matching nfs_client found\n", __func__
);
369 return -NFS4ERR_STALE_CLIENTID
;
372 #ifdef CONFIG_NFS_V4_1
374 * Returns true if the client IDs match
376 static bool nfs4_match_clientids(struct nfs_client
*a
, struct nfs_client
*b
)
378 if (a
->cl_clientid
!= b
->cl_clientid
) {
379 dprintk("NFS: --> %s client ID %llx does not match %llx\n",
380 __func__
, a
->cl_clientid
, b
->cl_clientid
);
383 dprintk("NFS: --> %s client ID %llx matches %llx\n",
384 __func__
, a
->cl_clientid
, b
->cl_clientid
);
389 * Returns true if the server owners match
392 nfs4_match_serverowners(struct nfs_client
*a
, struct nfs_client
*b
)
394 struct nfs41_server_owner
*o1
= a
->cl_serverowner
;
395 struct nfs41_server_owner
*o2
= b
->cl_serverowner
;
397 if (o1
->minor_id
!= o2
->minor_id
) {
398 dprintk("NFS: --> %s server owner minor IDs do not match\n",
403 if (o1
->major_id_sz
!= o2
->major_id_sz
)
404 goto out_major_mismatch
;
405 if (memcmp(o1
->major_id
, o2
->major_id
, o1
->major_id_sz
) != 0)
406 goto out_major_mismatch
;
408 dprintk("NFS: --> %s server owners match\n", __func__
);
412 dprintk("NFS: --> %s server owner major IDs do not match\n",
418 * nfs41_walk_client_list - Find nfs_client that matches a client/server owner
420 * @new: nfs_client with client ID to test
421 * @result: OUT: found nfs_client, or new
422 * @cred: credential to use for trunking test
424 * Returns zero, a negative errno, or a negative NFS4ERR status.
425 * If zero is returned, an nfs_client pointer is planted in "result."
427 * NB: nfs41_walk_client_list() relies on the new nfs_client being
428 * the last nfs_client on the list.
430 int nfs41_walk_client_list(struct nfs_client
*new,
431 struct nfs_client
**result
,
432 struct rpc_cred
*cred
)
434 struct nfs_net
*nn
= net_generic(new->cl_net
, nfs_net_id
);
435 struct nfs_client
*pos
, *n
, *prev
= NULL
;
438 spin_lock(&nn
->nfs_client_lock
);
439 list_for_each_entry_safe(pos
, n
, &nn
->nfs_client_list
, cl_share_link
) {
440 /* If "pos" isn't marked ready, we can't trust the
441 * remaining fields in "pos", especially the client
442 * ID and serverowner fields. Wait for CREATE_SESSION
444 if (pos
->cl_cons_state
< NFS_CS_READY
) {
445 atomic_inc(&pos
->cl_count
);
446 spin_unlock(&nn
->nfs_client_lock
);
449 nfs_put_client(prev
);
452 error
= nfs_wait_client_init_complete(pos
);
455 spin_lock(&nn
->nfs_client_lock
);
459 spin_lock(&nn
->nfs_client_lock
);
462 if (pos
->rpc_ops
!= new->rpc_ops
)
465 if (pos
->cl_proto
!= new->cl_proto
)
468 if (pos
->cl_minorversion
!= new->cl_minorversion
)
471 if (!nfs4_match_clientids(pos
, new))
474 if (!nfs4_match_serverowners(pos
, new))
477 spin_unlock(&nn
->nfs_client_lock
);
478 dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
479 __func__
, pos
, atomic_read(&pos
->cl_count
));
486 * No matching nfs_client found. This should be impossible,
487 * because the new nfs_client has already been added to
488 * nfs_client_list by nfs_get_client().
490 * Don't BUG(), since the caller is holding a mutex.
492 spin_unlock(&nn
->nfs_client_lock
);
493 pr_err("NFS: %s Error: no matching nfs_client found\n", __func__
);
494 return -NFS4ERR_STALE_CLIENTID
;
496 #endif /* CONFIG_NFS_V4_1 */
498 static void nfs4_destroy_server(struct nfs_server
*server
)
500 nfs_server_return_all_delegations(server
);
501 unset_pnfs_layoutdriver(server
);
502 nfs4_purge_state_owners(server
);
506 * NFSv4.0 callback thread helper
508 * Find a client by callback identifier
511 nfs4_find_client_ident(struct net
*net
, int cb_ident
)
513 struct nfs_client
*clp
;
514 struct nfs_net
*nn
= net_generic(net
, nfs_net_id
);
516 spin_lock(&nn
->nfs_client_lock
);
517 clp
= idr_find(&nn
->cb_ident_idr
, cb_ident
);
519 atomic_inc(&clp
->cl_count
);
520 spin_unlock(&nn
->nfs_client_lock
);
524 #if defined(CONFIG_NFS_V4_1)
525 /* Common match routine for v4.0 and v4.1 callback services */
526 static bool nfs4_cb_match_client(const struct sockaddr
*addr
,
527 struct nfs_client
*clp
, u32 minorversion
)
529 struct sockaddr
*clap
= (struct sockaddr
*)&clp
->cl_addr
;
531 /* Don't match clients that failed to initialise */
532 if (!(clp
->cl_cons_state
== NFS_CS_READY
||
533 clp
->cl_cons_state
== NFS_CS_SESSION_INITING
))
538 /* Match the version and minorversion */
539 if (clp
->rpc_ops
->version
!= 4 ||
540 clp
->cl_minorversion
!= minorversion
)
543 /* Match only the IP address, not the port number */
544 if (!nfs_sockaddr_match_ipaddr(addr
, clap
))
551 * NFSv4.1 callback thread helper
552 * For CB_COMPOUND calls, find a client by IP address, protocol version,
553 * minorversion, and sessionID
555 * Returns NULL if no such client
558 nfs4_find_client_sessionid(struct net
*net
, const struct sockaddr
*addr
,
559 struct nfs4_sessionid
*sid
)
561 struct nfs_client
*clp
;
562 struct nfs_net
*nn
= net_generic(net
, nfs_net_id
);
564 spin_lock(&nn
->nfs_client_lock
);
565 list_for_each_entry(clp
, &nn
->nfs_client_list
, cl_share_link
) {
566 if (nfs4_cb_match_client(addr
, clp
, 1) == false)
569 if (!nfs4_has_session(clp
))
573 if (memcmp(clp
->cl_session
->sess_id
.data
,
574 sid
->data
, NFS4_MAX_SESSIONID_LEN
) != 0)
577 atomic_inc(&clp
->cl_count
);
578 spin_unlock(&nn
->nfs_client_lock
);
581 spin_unlock(&nn
->nfs_client_lock
);
585 #else /* CONFIG_NFS_V4_1 */
588 nfs4_find_client_sessionid(struct net
*net
, const struct sockaddr
*addr
,
589 struct nfs4_sessionid
*sid
)
593 #endif /* CONFIG_NFS_V4_1 */
596 * Set up an NFS4 client
598 static int nfs4_set_client(struct nfs_server
*server
,
599 const char *hostname
,
600 const struct sockaddr
*addr
,
601 const size_t addrlen
,
603 rpc_authflavor_t authflavour
,
604 int proto
, const struct rpc_timeout
*timeparms
,
605 u32 minorversion
, struct net
*net
)
607 struct nfs_client_initdata cl_init
= {
608 .hostname
= hostname
,
613 .minorversion
= minorversion
,
616 struct nfs_client
*clp
;
619 dprintk("--> nfs4_set_client()\n");
621 if (server
->flags
& NFS_MOUNT_NORESVPORT
)
622 set_bit(NFS_CS_NORESVPORT
, &cl_init
.init_flags
);
624 /* Allocate or find a client reference we can use */
625 clp
= nfs_get_client(&cl_init
, timeparms
, ip_addr
, authflavour
);
627 error
= PTR_ERR(clp
);
632 * Query for the lease time on clientid setup or renewal
634 * Note that this will be set on nfs_clients that were created
635 * only for the DS role and did not set this bit, but now will
638 set_bit(NFS_CS_CHECK_LEASE_TIME
, &clp
->cl_res_state
);
640 server
->nfs_client
= clp
;
641 dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp
);
644 dprintk("<-- nfs4_set_client() = xerror %d\n", error
);
649 * Set up a pNFS Data Server client.
651 * Return any existing nfs_client that matches server address,port,version
654 * For a new nfs_client, use a soft mount (default), a low retrans and a
655 * low timeout interval so that if a connection is lost, we retry through
658 struct nfs_client
*nfs4_set_ds_client(struct nfs_client
* mds_clp
,
659 const struct sockaddr
*ds_addr
, int ds_addrlen
,
660 int ds_proto
, unsigned int ds_timeo
, unsigned int ds_retrans
)
662 struct nfs_client_initdata cl_init
= {
664 .addrlen
= ds_addrlen
,
667 .minorversion
= mds_clp
->cl_minorversion
,
668 .net
= mds_clp
->cl_net
,
670 struct rpc_timeout ds_timeout
;
671 struct nfs_client
*clp
;
674 * Set an authflavor equual to the MDS value. Use the MDS nfs_client
675 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS
676 * (section 13.1 RFC 5661).
678 nfs_init_timeout_values(&ds_timeout
, ds_proto
, ds_timeo
, ds_retrans
);
679 clp
= nfs_get_client(&cl_init
, &ds_timeout
, mds_clp
->cl_ipaddr
,
680 mds_clp
->cl_rpcclient
->cl_auth
->au_flavor
);
682 dprintk("<-- %s %p\n", __func__
, clp
);
685 EXPORT_SYMBOL_GPL(nfs4_set_ds_client
);
688 * Session has been established, and the client marked ready.
689 * Set the mount rsize and wsize with negotiated fore channel
690 * attributes which will be bound checked in nfs_server_set_fsinfo.
692 static void nfs4_session_set_rwsize(struct nfs_server
*server
)
694 #ifdef CONFIG_NFS_V4_1
695 struct nfs4_session
*sess
;
699 if (!nfs4_has_session(server
->nfs_client
))
701 sess
= server
->nfs_client
->cl_session
;
702 server_resp_sz
= sess
->fc_attrs
.max_resp_sz
- nfs41_maxread_overhead
;
703 server_rqst_sz
= sess
->fc_attrs
.max_rqst_sz
- nfs41_maxwrite_overhead
;
705 if (server
->rsize
> server_resp_sz
)
706 server
->rsize
= server_resp_sz
;
707 if (server
->wsize
> server_rqst_sz
)
708 server
->wsize
= server_rqst_sz
;
709 #endif /* CONFIG_NFS_V4_1 */
712 static int nfs4_server_common_setup(struct nfs_server
*server
,
713 struct nfs_fh
*mntfh
)
715 struct nfs_fattr
*fattr
;
718 /* data servers support only a subset of NFSv4.1 */
719 if (is_ds_only_client(server
->nfs_client
))
720 return -EPROTONOSUPPORT
;
722 fattr
= nfs_alloc_fattr();
726 /* We must ensure the session is initialised first */
727 error
= nfs4_init_session(server
);
731 /* Probe the root fh to retrieve its FSID and filehandle */
732 error
= nfs4_get_rootfh(server
, mntfh
);
736 dprintk("Server FSID: %llx:%llx\n",
737 (unsigned long long) server
->fsid
.major
,
738 (unsigned long long) server
->fsid
.minor
);
739 dprintk("Mount FH: %d\n", mntfh
->size
);
741 nfs4_session_set_rwsize(server
);
743 error
= nfs_probe_fsinfo(server
, mntfh
, fattr
);
747 if (server
->namelen
== 0 || server
->namelen
> NFS4_MAXNAMLEN
)
748 server
->namelen
= NFS4_MAXNAMLEN
;
750 nfs_server_insert_lists(server
);
751 server
->mount_time
= jiffies
;
752 server
->destroy
= nfs4_destroy_server
;
754 nfs_free_fattr(fattr
);
759 * Create a version 4 volume record
761 static int nfs4_init_server(struct nfs_server
*server
,
762 const struct nfs_parsed_mount_data
*data
)
764 struct rpc_timeout timeparms
;
767 dprintk("--> nfs4_init_server()\n");
769 nfs_init_timeout_values(&timeparms
, data
->nfs_server
.protocol
,
770 data
->timeo
, data
->retrans
);
772 /* Initialise the client representation from the mount data */
773 server
->flags
= data
->flags
;
774 server
->caps
|= NFS_CAP_ATOMIC_OPEN
|NFS_CAP_CHANGE_ATTR
|NFS_CAP_POSIX_LOCK
;
775 if (!(data
->flags
& NFS_MOUNT_NORDIRPLUS
))
776 server
->caps
|= NFS_CAP_READDIRPLUS
;
777 server
->options
= data
->options
;
779 /* Get a client record */
780 error
= nfs4_set_client(server
,
781 data
->nfs_server
.hostname
,
782 (const struct sockaddr
*)&data
->nfs_server
.address
,
783 data
->nfs_server
.addrlen
,
784 data
->client_address
,
785 data
->auth_flavors
[0],
786 data
->nfs_server
.protocol
,
794 * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower
797 if (nfs4_disable_idmapping
&& data
->auth_flavors
[0] == RPC_AUTH_UNIX
)
798 server
->caps
|= NFS_CAP_UIDGID_NOMAP
;
801 server
->rsize
= nfs_block_size(data
->rsize
, NULL
);
803 server
->wsize
= nfs_block_size(data
->wsize
, NULL
);
805 server
->acregmin
= data
->acregmin
* HZ
;
806 server
->acregmax
= data
->acregmax
* HZ
;
807 server
->acdirmin
= data
->acdirmin
* HZ
;
808 server
->acdirmax
= data
->acdirmax
* HZ
;
810 server
->port
= data
->nfs_server
.port
;
812 error
= nfs_init_server_rpcclient(server
, &timeparms
, data
->auth_flavors
[0]);
816 dprintk("<-- nfs4_init_server() = %d\n", error
);
821 * Create a version 4 volume record
822 * - keyed on server and FSID
824 /*struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data,
825 struct nfs_fh *mntfh)*/
826 struct nfs_server
*nfs4_create_server(struct nfs_mount_info
*mount_info
,
827 struct nfs_subversion
*nfs_mod
)
829 struct nfs_server
*server
;
832 dprintk("--> nfs4_create_server()\n");
834 server
= nfs_alloc_server();
836 return ERR_PTR(-ENOMEM
);
838 /* set up the general RPC client */
839 error
= nfs4_init_server(server
, mount_info
->parsed
);
843 error
= nfs4_server_common_setup(server
, mount_info
->mntfh
);
847 dprintk("<-- nfs4_create_server() = %p\n", server
);
851 nfs_free_server(server
);
852 dprintk("<-- nfs4_create_server() = error %d\n", error
);
853 return ERR_PTR(error
);
857 * Create an NFS4 referral server record
859 struct nfs_server
*nfs4_create_referral_server(struct nfs_clone_mount
*data
,
860 struct nfs_fh
*mntfh
)
862 struct nfs_client
*parent_client
;
863 struct nfs_server
*server
, *parent_server
;
866 dprintk("--> nfs4_create_referral_server()\n");
868 server
= nfs_alloc_server();
870 return ERR_PTR(-ENOMEM
);
872 parent_server
= NFS_SB(data
->sb
);
873 parent_client
= parent_server
->nfs_client
;
875 /* Initialise the client representation from the parent server */
876 nfs_server_copy_userdata(server
, parent_server
);
877 server
->caps
|= NFS_CAP_ATOMIC_OPEN
|NFS_CAP_CHANGE_ATTR
;
879 /* Get a client representation.
880 * Note: NFSv4 always uses TCP, */
881 error
= nfs4_set_client(server
, data
->hostname
,
884 parent_client
->cl_ipaddr
,
886 rpc_protocol(parent_server
->client
),
887 parent_server
->client
->cl_timeout
,
888 parent_client
->cl_mvops
->minor_version
,
889 parent_client
->cl_net
);
893 error
= nfs_init_server_rpcclient(server
, parent_server
->client
->cl_timeout
, data
->authflavor
);
897 error
= nfs4_server_common_setup(server
, mntfh
);
901 dprintk("<-- nfs_create_referral_server() = %p\n", server
);
905 nfs_free_server(server
);
906 dprintk("<-- nfs4_create_referral_server() = error %d\n", error
);
907 return ERR_PTR(error
);