nfs4client.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
  3. * Written by David Howells (dhowells@redhat.com)
  4. */
  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>
  10. #include "internal.h"
  11. #include "callback.h"
  12. #define NFSDBG_FACILITY NFSDBG_CLIENT
  13. /*
  14. * Initialize the NFS4 callback service
  15. */
  16. static int nfs4_init_callback(struct nfs_client *clp)
  17. {
  18. int error;
  19. if (clp->rpc_ops->version == 4) {
  20. struct rpc_xprt *xprt;
  21. xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt);
  22. if (nfs4_has_session(clp)) {
  23. error = xprt_setup_backchannel(xprt,
  24. NFS41_BC_MIN_CALLBACKS);
  25. if (error < 0)
  26. return error;
  27. }
  28. error = nfs_callback_up(clp->cl_mvops->minor_version, xprt);
  29. if (error < 0) {
  30. dprintk("%s: failed to start callback. Error = %d\n",
  31. __func__, error);
  32. return error;
  33. }
  34. __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state);
  35. }
  36. return 0;
  37. }
  38. /*
  39. * Initialize the minor version specific parts of an NFS4 client record
  40. */
  41. static int nfs4_init_client_minor_version(struct nfs_client *clp)
  42. {
  43. #if defined(CONFIG_NFS_V4_1)
  44. if (clp->cl_mvops->minor_version) {
  45. struct nfs4_session *session = NULL;
  46. /*
  47. * Create the session and mark it expired.
  48. * When a SEQUENCE operation encounters the expired session
  49. * it will do session recovery to initialize it.
  50. */
  51. session = nfs4_alloc_session(clp);
  52. if (!session)
  53. return -ENOMEM;
  54. clp->cl_session = session;
  55. /*
  56. * The create session reply races with the server back
  57. * channel probe. Mark the client NFS_CS_SESSION_INITING
  58. * so that the client back channel can find the
  59. * nfs_client struct
  60. */
  61. nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING);
  62. }
  63. #endif /* CONFIG_NFS_V4_1 */
  64. return nfs4_init_callback(clp);
  65. }
  66. /**
  67. * nfs4_init_client - Initialise an NFS4 client record
  68. *
  69. * @clp: nfs_client to initialise
  70. * @timeparms: timeout parameters for underlying RPC transport
  71. * @ip_addr: callback IP address in presentation format
  72. * @authflavor: authentication flavor for underlying RPC transport
  73. *
  74. * Returns pointer to an NFS client, or an ERR_PTR value.
  75. */
  76. struct nfs_client *nfs4_init_client(struct nfs_client *clp,
  77. const struct rpc_timeout *timeparms,
  78. const char *ip_addr,
  79. rpc_authflavor_t authflavour)
  80. {
  81. char buf[INET6_ADDRSTRLEN + 1];
  82. int error;
  83. if (clp->cl_cons_state == NFS_CS_READY) {
  84. /* the client is initialised already */
  85. dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
  86. return clp;
  87. }
  88. /* Check NFS protocol revision and initialize RPC op vector */
  89. clp->rpc_ops = &nfs_v4_clientops;
  90. __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags);
  91. error = nfs_create_rpc_client(clp, timeparms, authflavour);
  92. if (error < 0)
  93. goto error;
  94. /* If no clientaddr= option was specified, find a usable cb address */
  95. if (ip_addr == NULL) {
  96. struct sockaddr_storage cb_addr;
  97. struct sockaddr *sap = (struct sockaddr *)&cb_addr;
  98. error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr));
  99. if (error < 0)
  100. goto error;
  101. error = rpc_ntop(sap, buf, sizeof(buf));
  102. if (error < 0)
  103. goto error;
  104. ip_addr = (const char *)buf;
  105. }
  106. strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr));
  107. error = nfs_idmap_new(clp);
  108. if (error < 0) {
  109. dprintk("%s: failed to create idmapper. Error = %d\n",
  110. __func__, error);
  111. goto error;
  112. }
  113. __set_bit(NFS_CS_IDMAP, &clp->cl_res_state);
  114. error = nfs4_init_client_minor_version(clp);
  115. if (error < 0)
  116. goto error;
  117. if (!nfs4_has_session(clp))
  118. nfs_mark_client_ready(clp, NFS_CS_READY);
  119. return clp;
  120. error:
  121. nfs_mark_client_ready(clp, error);
  122. nfs_put_client(clp);
  123. dprintk("<-- nfs4_init_client() = xerror %d\n", error);
  124. return ERR_PTR(error);
  125. }