root/fs/nfs/client.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_nfs_version
  2. get_nfs_version
  3. put_nfs_version
  4. register_nfs_version
  5. unregister_nfs_version
  6. nfs_alloc_client
  7. nfs_cleanup_cb_ident_idr
  8. nfs_cb_idr_remove_locked
  9. pnfs_init_server
  10. nfs_cleanup_cb_ident_idr
  11. nfs_cb_idr_remove_locked
  12. pnfs_init_server
  13. nfs_free_client
  14. nfs_put_client
  15. nfs_match_client
  16. nfs_client_init_is_complete
  17. nfs_client_init_status
  18. nfs_wait_client_init_complete
  19. nfs_found_client
  20. nfs_get_client
  21. nfs_mark_client_ready
  22. nfs_init_timeout_values
  23. nfs_create_rpc_client
  24. nfs_destroy_server
  25. nfs_start_lockd
  26. nfs_init_server_rpcclient
  27. nfs_init_client
  28. nfs_init_server
  29. nfs_server_set_fsinfo
  30. nfs_probe_fsinfo
  31. nfs_server_copy_userdata
  32. nfs_server_insert_lists
  33. nfs_server_remove_lists
  34. nfs_alloc_server
  35. nfs_free_server
  36. nfs_create_server
  37. nfs_clone_server
  38. nfs_clients_init
  39. nfs_clients_exit
  40. nfs_server_list_start
  41. nfs_server_list_next
  42. nfs_server_list_stop
  43. nfs_server_list_show
  44. nfs_volume_list_start
  45. nfs_volume_list_next
  46. nfs_volume_list_stop
  47. nfs_volume_list_show
  48. nfs_fs_proc_net_init
  49. nfs_fs_proc_net_exit
  50. nfs_fs_proc_init
  51. nfs_fs_proc_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* client.c: NFS client sharing and management code
   3  *
   4  * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
   5  * Written by David Howells (dhowells@redhat.com)
   6  */
   7 
   8 
   9 #include <linux/module.h>
  10 #include <linux/init.h>
  11 #include <linux/sched.h>
  12 #include <linux/time.h>
  13 #include <linux/kernel.h>
  14 #include <linux/mm.h>
  15 #include <linux/string.h>
  16 #include <linux/stat.h>
  17 #include <linux/errno.h>
  18 #include <linux/unistd.h>
  19 #include <linux/sunrpc/addr.h>
  20 #include <linux/sunrpc/clnt.h>
  21 #include <linux/sunrpc/stats.h>
  22 #include <linux/sunrpc/metrics.h>
  23 #include <linux/sunrpc/xprtsock.h>
  24 #include <linux/sunrpc/xprtrdma.h>
  25 #include <linux/nfs_fs.h>
  26 #include <linux/nfs_mount.h>
  27 #include <linux/nfs4_mount.h>
  28 #include <linux/lockd/bind.h>
  29 #include <linux/seq_file.h>
  30 #include <linux/mount.h>
  31 #include <linux/vfs.h>
  32 #include <linux/inet.h>
  33 #include <linux/in6.h>
  34 #include <linux/slab.h>
  35 #include <linux/idr.h>
  36 #include <net/ipv6.h>
  37 #include <linux/nfs_xdr.h>
  38 #include <linux/sunrpc/bc_xprt.h>
  39 #include <linux/nsproxy.h>
  40 #include <linux/pid_namespace.h>
  41 
  42 
  43 #include "nfs4_fs.h"
  44 #include "callback.h"
  45 #include "delegation.h"
  46 #include "iostat.h"
  47 #include "internal.h"
  48 #include "fscache.h"
  49 #include "pnfs.h"
  50 #include "nfs.h"
  51 #include "netns.h"
  52 #include "sysfs.h"
  53 
  54 #define NFSDBG_FACILITY         NFSDBG_CLIENT
  55 
  56 static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
  57 static DEFINE_SPINLOCK(nfs_version_lock);
  58 static DEFINE_MUTEX(nfs_version_mutex);
  59 static LIST_HEAD(nfs_versions);
  60 
  61 /*
  62  * RPC cruft for NFS
  63  */
  64 static const struct rpc_version *nfs_version[5] = {
  65         [2] = NULL,
  66         [3] = NULL,
  67         [4] = NULL,
  68 };
  69 
  70 const struct rpc_program nfs_program = {
  71         .name                   = "nfs",
  72         .number                 = NFS_PROGRAM,
  73         .nrvers                 = ARRAY_SIZE(nfs_version),
  74         .version                = nfs_version,
  75         .stats                  = &nfs_rpcstat,
  76         .pipe_dir_name          = NFS_PIPE_DIRNAME,
  77 };
  78 
  79 struct rpc_stat nfs_rpcstat = {
  80         .program                = &nfs_program
  81 };
  82 
  83 static struct nfs_subversion *find_nfs_version(unsigned int version)
  84 {
  85         struct nfs_subversion *nfs;
  86         spin_lock(&nfs_version_lock);
  87 
  88         list_for_each_entry(nfs, &nfs_versions, list) {
  89                 if (nfs->rpc_ops->version == version) {
  90                         spin_unlock(&nfs_version_lock);
  91                         return nfs;
  92                 }
  93         }
  94 
  95         spin_unlock(&nfs_version_lock);
  96         return ERR_PTR(-EPROTONOSUPPORT);
  97 }
  98 
  99 struct nfs_subversion *get_nfs_version(unsigned int version)
 100 {
 101         struct nfs_subversion *nfs = find_nfs_version(version);
 102 
 103         if (IS_ERR(nfs)) {
 104                 mutex_lock(&nfs_version_mutex);
 105                 request_module("nfsv%d", version);
 106                 nfs = find_nfs_version(version);
 107                 mutex_unlock(&nfs_version_mutex);
 108         }
 109 
 110         if (!IS_ERR(nfs) && !try_module_get(nfs->owner))
 111                 return ERR_PTR(-EAGAIN);
 112         return nfs;
 113 }
 114 
 115 void put_nfs_version(struct nfs_subversion *nfs)
 116 {
 117         module_put(nfs->owner);
 118 }
 119 
 120 void register_nfs_version(struct nfs_subversion *nfs)
 121 {
 122         spin_lock(&nfs_version_lock);
 123 
 124         list_add(&nfs->list, &nfs_versions);
 125         nfs_version[nfs->rpc_ops->version] = nfs->rpc_vers;
 126 
 127         spin_unlock(&nfs_version_lock);
 128 }
 129 EXPORT_SYMBOL_GPL(register_nfs_version);
 130 
 131 void unregister_nfs_version(struct nfs_subversion *nfs)
 132 {
 133         spin_lock(&nfs_version_lock);
 134 
 135         nfs_version[nfs->rpc_ops->version] = NULL;
 136         list_del(&nfs->list);
 137 
 138         spin_unlock(&nfs_version_lock);
 139 }
 140 EXPORT_SYMBOL_GPL(unregister_nfs_version);
 141 
 142 /*
 143  * Allocate a shared client record
 144  *
 145  * Since these are allocated/deallocated very rarely, we don't
 146  * bother putting them in a slab cache...
 147  */
 148 struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
 149 {
 150         struct nfs_client *clp;
 151         int err = -ENOMEM;
 152 
 153         if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL)
 154                 goto error_0;
 155 
 156         clp->cl_minorversion = cl_init->minorversion;
 157         clp->cl_nfs_mod = cl_init->nfs_mod;
 158         if (!try_module_get(clp->cl_nfs_mod->owner))
 159                 goto error_dealloc;
 160 
 161         clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
 162 
 163         refcount_set(&clp->cl_count, 1);
 164         clp->cl_cons_state = NFS_CS_INITING;
 165 
 166         memcpy(&clp->cl_addr, cl_init->addr, cl_init->addrlen);
 167         clp->cl_addrlen = cl_init->addrlen;
 168 
 169         if (cl_init->hostname) {
 170                 err = -ENOMEM;
 171                 clp->cl_hostname = kstrdup(cl_init->hostname, GFP_KERNEL);
 172                 if (!clp->cl_hostname)
 173                         goto error_cleanup;
 174         }
 175 
 176         INIT_LIST_HEAD(&clp->cl_superblocks);
 177         clp->cl_rpcclient = ERR_PTR(-EINVAL);
 178 
 179         clp->cl_proto = cl_init->proto;
 180         clp->cl_nconnect = cl_init->nconnect;
 181         clp->cl_net = get_net(cl_init->net);
 182 
 183         clp->cl_principal = "*";
 184         nfs_fscache_get_client_cookie(clp);
 185 
 186         return clp;
 187 
 188 error_cleanup:
 189         put_nfs_version(clp->cl_nfs_mod);
 190 error_dealloc:
 191         kfree(clp);
 192 error_0:
 193         return ERR_PTR(err);
 194 }
 195 EXPORT_SYMBOL_GPL(nfs_alloc_client);
 196 
 197 #if IS_ENABLED(CONFIG_NFS_V4)
 198 static void nfs_cleanup_cb_ident_idr(struct net *net)
 199 {
 200         struct nfs_net *nn = net_generic(net, nfs_net_id);
 201 
 202         idr_destroy(&nn->cb_ident_idr);
 203 }
 204 
 205 /* nfs_client_lock held */
 206 static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
 207 {
 208         struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
 209 
 210         if (clp->cl_cb_ident)
 211                 idr_remove(&nn->cb_ident_idr, clp->cl_cb_ident);
 212 }
 213 
 214 static void pnfs_init_server(struct nfs_server *server)
 215 {
 216         rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
 217 }
 218 
 219 #else
 220 static void nfs_cleanup_cb_ident_idr(struct net *net)
 221 {
 222 }
 223 
 224 static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
 225 {
 226 }
 227 
 228 static void pnfs_init_server(struct nfs_server *server)
 229 {
 230 }
 231 
 232 #endif /* CONFIG_NFS_V4 */
 233 
 234 /*
 235  * Destroy a shared client record
 236  */
 237 void nfs_free_client(struct nfs_client *clp)
 238 {
 239         nfs_fscache_release_client_cookie(clp);
 240 
 241         /* -EIO all pending I/O */
 242         if (!IS_ERR(clp->cl_rpcclient))
 243                 rpc_shutdown_client(clp->cl_rpcclient);
 244 
 245         put_net(clp->cl_net);
 246         put_nfs_version(clp->cl_nfs_mod);
 247         kfree(clp->cl_hostname);
 248         kfree(clp->cl_acceptor);
 249         kfree(clp);
 250 }
 251 EXPORT_SYMBOL_GPL(nfs_free_client);
 252 
 253 /*
 254  * Release a reference to a shared client record
 255  */
 256 void nfs_put_client(struct nfs_client *clp)
 257 {
 258         struct nfs_net *nn;
 259 
 260         if (!clp)
 261                 return;
 262 
 263         nn = net_generic(clp->cl_net, nfs_net_id);
 264 
 265         if (refcount_dec_and_lock(&clp->cl_count, &nn->nfs_client_lock)) {
 266                 list_del(&clp->cl_share_link);
 267                 nfs_cb_idr_remove_locked(clp);
 268                 spin_unlock(&nn->nfs_client_lock);
 269 
 270                 WARN_ON_ONCE(!list_empty(&clp->cl_superblocks));
 271 
 272                 clp->rpc_ops->free_client(clp);
 273         }
 274 }
 275 EXPORT_SYMBOL_GPL(nfs_put_client);
 276 
 277 /*
 278  * Find an nfs_client on the list that matches the initialisation data
 279  * that is supplied.
 280  */
 281 static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *data)
 282 {
 283         struct nfs_client *clp;
 284         const struct sockaddr *sap = data->addr;
 285         struct nfs_net *nn = net_generic(data->net, nfs_net_id);
 286         int error;
 287 
 288 again:
 289         list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) {
 290                 const struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr;
 291                 /* Don't match clients that failed to initialise properly */
 292                 if (clp->cl_cons_state < 0)
 293                         continue;
 294 
 295                 /* If a client is still initializing then we need to wait */
 296                 if (clp->cl_cons_state > NFS_CS_READY) {
 297                         refcount_inc(&clp->cl_count);
 298                         spin_unlock(&nn->nfs_client_lock);
 299                         error = nfs_wait_client_init_complete(clp);
 300                         nfs_put_client(clp);
 301                         spin_lock(&nn->nfs_client_lock);
 302                         if (error < 0)
 303                                 return ERR_PTR(error);
 304                         goto again;
 305                 }
 306 
 307                 /* Different NFS versions cannot share the same nfs_client */
 308                 if (clp->rpc_ops != data->nfs_mod->rpc_ops)
 309                         continue;
 310 
 311                 if (clp->cl_proto != data->proto)
 312                         continue;
 313                 /* Match nfsv4 minorversion */
 314                 if (clp->cl_minorversion != data->minorversion)
 315                         continue;
 316                 /* Match the full socket address */
 317                 if (!rpc_cmp_addr_port(sap, clap))
 318                         /* Match all xprt_switch full socket addresses */
 319                         if (IS_ERR(clp->cl_rpcclient) ||
 320                             !rpc_clnt_xprt_switch_has_addr(clp->cl_rpcclient,
 321                                                            sap))
 322                                 continue;
 323 
 324                 refcount_inc(&clp->cl_count);
 325                 return clp;
 326         }
 327         return NULL;
 328 }
 329 
 330 /*
 331  * Return true if @clp is done initializing, false if still working on it.
 332  *
 333  * Use nfs_client_init_status to check if it was successful.
 334  */
 335 bool nfs_client_init_is_complete(const struct nfs_client *clp)
 336 {
 337         return clp->cl_cons_state <= NFS_CS_READY;
 338 }
 339 EXPORT_SYMBOL_GPL(nfs_client_init_is_complete);
 340 
 341 /*
 342  * Return 0 if @clp was successfully initialized, -errno otherwise.
 343  *
 344  * This must be called *after* nfs_client_init_is_complete() returns true,
 345  * otherwise it will pop WARN_ON_ONCE and return -EINVAL
 346  */
 347 int nfs_client_init_status(const struct nfs_client *clp)
 348 {
 349         /* called without checking nfs_client_init_is_complete */
 350         if (clp->cl_cons_state > NFS_CS_READY) {
 351                 WARN_ON_ONCE(1);
 352                 return -EINVAL;
 353         }
 354         return clp->cl_cons_state;
 355 }
 356 EXPORT_SYMBOL_GPL(nfs_client_init_status);
 357 
 358 int nfs_wait_client_init_complete(const struct nfs_client *clp)
 359 {
 360         return wait_event_killable(nfs_client_active_wq,
 361                         nfs_client_init_is_complete(clp));
 362 }
 363 EXPORT_SYMBOL_GPL(nfs_wait_client_init_complete);
 364 
 365 /*
 366  * Found an existing client.  Make sure it's ready before returning.
 367  */
 368 static struct nfs_client *
 369 nfs_found_client(const struct nfs_client_initdata *cl_init,
 370                  struct nfs_client *clp)
 371 {
 372         int error;
 373 
 374         error = nfs_wait_client_init_complete(clp);
 375         if (error < 0) {
 376                 nfs_put_client(clp);
 377                 return ERR_PTR(-ERESTARTSYS);
 378         }
 379 
 380         if (clp->cl_cons_state < NFS_CS_READY) {
 381                 error = clp->cl_cons_state;
 382                 nfs_put_client(clp);
 383                 return ERR_PTR(error);
 384         }
 385 
 386         smp_rmb();
 387         return clp;
 388 }
 389 
 390 /*
 391  * Look up a client by IP address and protocol version
 392  * - creates a new record if one doesn't yet exist
 393  */
 394 struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
 395 {
 396         struct nfs_client *clp, *new = NULL;
 397         struct nfs_net *nn = net_generic(cl_init->net, nfs_net_id);
 398         const struct nfs_rpc_ops *rpc_ops = cl_init->nfs_mod->rpc_ops;
 399 
 400         if (cl_init->hostname == NULL) {
 401                 WARN_ON(1);
 402                 return NULL;
 403         }
 404 
 405         /* see if the client already exists */
 406         do {
 407                 spin_lock(&nn->nfs_client_lock);
 408 
 409                 clp = nfs_match_client(cl_init);
 410                 if (clp) {
 411                         spin_unlock(&nn->nfs_client_lock);
 412                         if (new)
 413                                 new->rpc_ops->free_client(new);
 414                         if (IS_ERR(clp))
 415                                 return clp;
 416                         return nfs_found_client(cl_init, clp);
 417                 }
 418                 if (new) {
 419                         list_add_tail(&new->cl_share_link,
 420                                         &nn->nfs_client_list);
 421                         spin_unlock(&nn->nfs_client_lock);
 422                         new->cl_flags = cl_init->init_flags;
 423                         return rpc_ops->init_client(new, cl_init);
 424                 }
 425 
 426                 spin_unlock(&nn->nfs_client_lock);
 427 
 428                 new = rpc_ops->alloc_client(cl_init);
 429         } while (!IS_ERR(new));
 430 
 431         return new;
 432 }
 433 EXPORT_SYMBOL_GPL(nfs_get_client);
 434 
 435 /*
 436  * Mark a server as ready or failed
 437  */
 438 void nfs_mark_client_ready(struct nfs_client *clp, int state)
 439 {
 440         smp_wmb();
 441         clp->cl_cons_state = state;
 442         wake_up_all(&nfs_client_active_wq);
 443 }
 444 EXPORT_SYMBOL_GPL(nfs_mark_client_ready);
 445 
 446 /*
 447  * Initialise the timeout values for a connection
 448  */
 449 void nfs_init_timeout_values(struct rpc_timeout *to, int proto,
 450                                     int timeo, int retrans)
 451 {
 452         to->to_initval = timeo * HZ / 10;
 453         to->to_retries = retrans;
 454 
 455         switch (proto) {
 456         case XPRT_TRANSPORT_TCP:
 457         case XPRT_TRANSPORT_RDMA:
 458                 if (retrans == NFS_UNSPEC_RETRANS)
 459                         to->to_retries = NFS_DEF_TCP_RETRANS;
 460                 if (timeo == NFS_UNSPEC_TIMEO || to->to_initval == 0)
 461                         to->to_initval = NFS_DEF_TCP_TIMEO * HZ / 10;
 462                 if (to->to_initval > NFS_MAX_TCP_TIMEOUT)
 463                         to->to_initval = NFS_MAX_TCP_TIMEOUT;
 464                 to->to_increment = to->to_initval;
 465                 to->to_maxval = to->to_initval + (to->to_increment * to->to_retries);
 466                 if (to->to_maxval > NFS_MAX_TCP_TIMEOUT)
 467                         to->to_maxval = NFS_MAX_TCP_TIMEOUT;
 468                 if (to->to_maxval < to->to_initval)
 469                         to->to_maxval = to->to_initval;
 470                 to->to_exponential = 0;
 471                 break;
 472         case XPRT_TRANSPORT_UDP:
 473                 if (retrans == NFS_UNSPEC_RETRANS)
 474                         to->to_retries = NFS_DEF_UDP_RETRANS;
 475                 if (timeo == NFS_UNSPEC_TIMEO || to->to_initval == 0)
 476                         to->to_initval = NFS_DEF_UDP_TIMEO * HZ / 10;
 477                 if (to->to_initval > NFS_MAX_UDP_TIMEOUT)
 478                         to->to_initval = NFS_MAX_UDP_TIMEOUT;
 479                 to->to_maxval = NFS_MAX_UDP_TIMEOUT;
 480                 to->to_exponential = 1;
 481                 break;
 482         default:
 483                 BUG();
 484         }
 485 }
 486 EXPORT_SYMBOL_GPL(nfs_init_timeout_values);
 487 
 488 /*
 489  * Create an RPC client handle
 490  */
 491 int nfs_create_rpc_client(struct nfs_client *clp,
 492                           const struct nfs_client_initdata *cl_init,
 493                           rpc_authflavor_t flavor)
 494 {
 495         struct rpc_clnt         *clnt = NULL;
 496         struct rpc_create_args args = {
 497                 .net            = clp->cl_net,
 498                 .protocol       = clp->cl_proto,
 499                 .nconnect       = clp->cl_nconnect,
 500                 .address        = (struct sockaddr *)&clp->cl_addr,
 501                 .addrsize       = clp->cl_addrlen,
 502                 .timeout        = cl_init->timeparms,
 503                 .servername     = clp->cl_hostname,
 504                 .nodename       = cl_init->nodename,
 505                 .program        = &nfs_program,
 506                 .version        = clp->rpc_ops->version,
 507                 .authflavor     = flavor,
 508                 .cred           = cl_init->cred,
 509         };
 510 
 511         if (test_bit(NFS_CS_DISCRTRY, &clp->cl_flags))
 512                 args.flags |= RPC_CLNT_CREATE_DISCRTRY;
 513         if (test_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags))
 514                 args.flags |= RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT;
 515         if (test_bit(NFS_CS_NORESVPORT, &clp->cl_flags))
 516                 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
 517         if (test_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags))
 518                 args.flags |= RPC_CLNT_CREATE_INFINITE_SLOTS;
 519 
 520         if (!IS_ERR(clp->cl_rpcclient))
 521                 return 0;
 522 
 523         clnt = rpc_create(&args);
 524         if (IS_ERR(clnt)) {
 525                 dprintk("%s: cannot create RPC client. Error = %ld\n",
 526                                 __func__, PTR_ERR(clnt));
 527                 return PTR_ERR(clnt);
 528         }
 529 
 530         clnt->cl_principal = clp->cl_principal;
 531         clp->cl_rpcclient = clnt;
 532         return 0;
 533 }
 534 EXPORT_SYMBOL_GPL(nfs_create_rpc_client);
 535 
 536 /*
 537  * Version 2 or 3 client destruction
 538  */
 539 static void nfs_destroy_server(struct nfs_server *server)
 540 {
 541         if (server->nlm_host)
 542                 nlmclnt_done(server->nlm_host);
 543 }
 544 
 545 /*
 546  * Version 2 or 3 lockd setup
 547  */
 548 static int nfs_start_lockd(struct nfs_server *server)
 549 {
 550         struct nlm_host *host;
 551         struct nfs_client *clp = server->nfs_client;
 552         struct nlmclnt_initdata nlm_init = {
 553                 .hostname       = clp->cl_hostname,
 554                 .address        = (struct sockaddr *)&clp->cl_addr,
 555                 .addrlen        = clp->cl_addrlen,
 556                 .nfs_version    = clp->rpc_ops->version,
 557                 .noresvport     = server->flags & NFS_MOUNT_NORESVPORT ?
 558                                         1 : 0,
 559                 .net            = clp->cl_net,
 560                 .nlmclnt_ops    = clp->cl_nfs_mod->rpc_ops->nlmclnt_ops,
 561                 .cred           = current_cred(),
 562         };
 563 
 564         if (nlm_init.nfs_version > 3)
 565                 return 0;
 566         if ((server->flags & NFS_MOUNT_LOCAL_FLOCK) &&
 567                         (server->flags & NFS_MOUNT_LOCAL_FCNTL))
 568                 return 0;
 569 
 570         switch (clp->cl_proto) {
 571                 default:
 572                         nlm_init.protocol = IPPROTO_TCP;
 573                         break;
 574                 case XPRT_TRANSPORT_UDP:
 575                         nlm_init.protocol = IPPROTO_UDP;
 576         }
 577 
 578         host = nlmclnt_init(&nlm_init);
 579         if (IS_ERR(host))
 580                 return PTR_ERR(host);
 581 
 582         server->nlm_host = host;
 583         server->destroy = nfs_destroy_server;
 584         return 0;
 585 }
 586 
 587 /*
 588  * Create a general RPC client
 589  */
 590 int nfs_init_server_rpcclient(struct nfs_server *server,
 591                 const struct rpc_timeout *timeo,
 592                 rpc_authflavor_t pseudoflavour)
 593 {
 594         struct nfs_client *clp = server->nfs_client;
 595 
 596         server->client = rpc_clone_client_set_auth(clp->cl_rpcclient,
 597                                                         pseudoflavour);
 598         if (IS_ERR(server->client)) {
 599                 dprintk("%s: couldn't create rpc_client!\n", __func__);
 600                 return PTR_ERR(server->client);
 601         }
 602 
 603         memcpy(&server->client->cl_timeout_default,
 604                         timeo,
 605                         sizeof(server->client->cl_timeout_default));
 606         server->client->cl_timeout = &server->client->cl_timeout_default;
 607         server->client->cl_softrtry = 0;
 608         if (server->flags & NFS_MOUNT_SOFTERR)
 609                 server->client->cl_softerr = 1;
 610         if (server->flags & NFS_MOUNT_SOFT)
 611                 server->client->cl_softrtry = 1;
 612 
 613         return 0;
 614 }
 615 EXPORT_SYMBOL_GPL(nfs_init_server_rpcclient);
 616 
 617 /**
 618  * nfs_init_client - Initialise an NFS2 or NFS3 client
 619  *
 620  * @clp: nfs_client to initialise
 621  * @cl_init: Initialisation parameters
 622  *
 623  * Returns pointer to an NFS client, or an ERR_PTR value.
 624  */
 625 struct nfs_client *nfs_init_client(struct nfs_client *clp,
 626                                    const struct nfs_client_initdata *cl_init)
 627 {
 628         int error;
 629 
 630         /* the client is already initialised */
 631         if (clp->cl_cons_state == NFS_CS_READY)
 632                 return clp;
 633 
 634         /*
 635          * Create a client RPC handle for doing FSSTAT with UNIX auth only
 636          * - RFC 2623, sec 2.3.2
 637          */
 638         error = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_UNIX);
 639         nfs_mark_client_ready(clp, error == 0 ? NFS_CS_READY : error);
 640         if (error < 0) {
 641                 nfs_put_client(clp);
 642                 clp = ERR_PTR(error);
 643         }
 644         return clp;
 645 }
 646 EXPORT_SYMBOL_GPL(nfs_init_client);
 647 
 648 /*
 649  * Create a version 2 or 3 client
 650  */
 651 static int nfs_init_server(struct nfs_server *server,
 652                            const struct nfs_parsed_mount_data *data,
 653                            struct nfs_subversion *nfs_mod)
 654 {
 655         struct rpc_timeout timeparms;
 656         struct nfs_client_initdata cl_init = {
 657                 .hostname = data->nfs_server.hostname,
 658                 .addr = (const struct sockaddr *)&data->nfs_server.address,
 659                 .addrlen = data->nfs_server.addrlen,
 660                 .nfs_mod = nfs_mod,
 661                 .proto = data->nfs_server.protocol,
 662                 .net = data->net,
 663                 .timeparms = &timeparms,
 664                 .cred = server->cred,
 665                 .nconnect = data->nfs_server.nconnect,
 666         };
 667         struct nfs_client *clp;
 668         int error;
 669 
 670         nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
 671                         data->timeo, data->retrans);
 672         if (data->flags & NFS_MOUNT_NORESVPORT)
 673                 set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
 674 
 675         /* Allocate or find a client reference we can use */
 676         clp = nfs_get_client(&cl_init);
 677         if (IS_ERR(clp))
 678                 return PTR_ERR(clp);
 679 
 680         server->nfs_client = clp;
 681 
 682         /* Initialise the client representation from the mount data */
 683         server->flags = data->flags;
 684         server->options = data->options;
 685         server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
 686                 NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP|
 687                 NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME;
 688 
 689         if (data->rsize)
 690                 server->rsize = nfs_block_size(data->rsize, NULL);
 691         if (data->wsize)
 692                 server->wsize = nfs_block_size(data->wsize, NULL);
 693 
 694         server->acregmin = data->acregmin * HZ;
 695         server->acregmax = data->acregmax * HZ;
 696         server->acdirmin = data->acdirmin * HZ;
 697         server->acdirmax = data->acdirmax * HZ;
 698 
 699         /* Start lockd here, before we might error out */
 700         error = nfs_start_lockd(server);
 701         if (error < 0)
 702                 goto error;
 703 
 704         server->port = data->nfs_server.port;
 705         server->auth_info = data->auth_info;
 706 
 707         error = nfs_init_server_rpcclient(server, &timeparms,
 708                                           data->selected_flavor);
 709         if (error < 0)
 710                 goto error;
 711 
 712         /* Preserve the values of mount_server-related mount options */
 713         if (data->mount_server.addrlen) {
 714                 memcpy(&server->mountd_address, &data->mount_server.address,
 715                         data->mount_server.addrlen);
 716                 server->mountd_addrlen = data->mount_server.addrlen;
 717         }
 718         server->mountd_version = data->mount_server.version;
 719         server->mountd_port = data->mount_server.port;
 720         server->mountd_protocol = data->mount_server.protocol;
 721 
 722         server->namelen  = data->namlen;
 723         return 0;
 724 
 725 error:
 726         server->nfs_client = NULL;
 727         nfs_put_client(clp);
 728         return error;
 729 }
 730 
 731 /*
 732  * Load up the server record from information gained in an fsinfo record
 733  */
 734 static void nfs_server_set_fsinfo(struct nfs_server *server,
 735                                   struct nfs_fsinfo *fsinfo)
 736 {
 737         unsigned long max_rpc_payload;
 738 
 739         /* Work out a lot of parameters */
 740         if (server->rsize == 0)
 741                 server->rsize = nfs_block_size(fsinfo->rtpref, NULL);
 742         if (server->wsize == 0)
 743                 server->wsize = nfs_block_size(fsinfo->wtpref, NULL);
 744 
 745         if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax)
 746                 server->rsize = nfs_block_size(fsinfo->rtmax, NULL);
 747         if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax)
 748                 server->wsize = nfs_block_size(fsinfo->wtmax, NULL);
 749 
 750         max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
 751         if (server->rsize > max_rpc_payload)
 752                 server->rsize = max_rpc_payload;
 753         if (server->rsize > NFS_MAX_FILE_IO_SIZE)
 754                 server->rsize = NFS_MAX_FILE_IO_SIZE;
 755         server->rpages = (server->rsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
 756 
 757         if (server->wsize > max_rpc_payload)
 758                 server->wsize = max_rpc_payload;
 759         if (server->wsize > NFS_MAX_FILE_IO_SIZE)
 760                 server->wsize = NFS_MAX_FILE_IO_SIZE;
 761         server->wpages = (server->wsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
 762 
 763         server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 764 
 765         server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
 766         if (server->dtsize > PAGE_SIZE * NFS_MAX_READDIR_PAGES)
 767                 server->dtsize = PAGE_SIZE * NFS_MAX_READDIR_PAGES;
 768         if (server->dtsize > server->rsize)
 769                 server->dtsize = server->rsize;
 770 
 771         if (server->flags & NFS_MOUNT_NOAC) {
 772                 server->acregmin = server->acregmax = 0;
 773                 server->acdirmin = server->acdirmax = 0;
 774         }
 775 
 776         server->maxfilesize = fsinfo->maxfilesize;
 777 
 778         server->time_delta = fsinfo->time_delta;
 779 
 780         server->clone_blksize = fsinfo->clone_blksize;
 781         /* We're airborne Set socket buffersize */
 782         rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
 783 }
 784 
 785 /*
 786  * Probe filesystem information, including the FSID on v2/v3
 787  */
 788 int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr)
 789 {
 790         struct nfs_fsinfo fsinfo;
 791         struct nfs_client *clp = server->nfs_client;
 792         int error;
 793 
 794         if (clp->rpc_ops->set_capabilities != NULL) {
 795                 error = clp->rpc_ops->set_capabilities(server, mntfh);
 796                 if (error < 0)
 797                         return error;
 798         }
 799 
 800         fsinfo.fattr = fattr;
 801         fsinfo.nlayouttypes = 0;
 802         memset(fsinfo.layouttype, 0, sizeof(fsinfo.layouttype));
 803         error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
 804         if (error < 0)
 805                 return error;
 806 
 807         nfs_server_set_fsinfo(server, &fsinfo);
 808 
 809         /* Get some general file system info */
 810         if (server->namelen == 0) {
 811                 struct nfs_pathconf pathinfo;
 812 
 813                 pathinfo.fattr = fattr;
 814                 nfs_fattr_init(fattr);
 815 
 816                 if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0)
 817                         server->namelen = pathinfo.max_namelen;
 818         }
 819 
 820         return 0;
 821 }
 822 EXPORT_SYMBOL_GPL(nfs_probe_fsinfo);
 823 
 824 /*
 825  * Copy useful information when duplicating a server record
 826  */
 827 void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source)
 828 {
 829         target->flags = source->flags;
 830         target->rsize = source->rsize;
 831         target->wsize = source->wsize;
 832         target->acregmin = source->acregmin;
 833         target->acregmax = source->acregmax;
 834         target->acdirmin = source->acdirmin;
 835         target->acdirmax = source->acdirmax;
 836         target->caps = source->caps;
 837         target->options = source->options;
 838         target->auth_info = source->auth_info;
 839         target->port = source->port;
 840 }
 841 EXPORT_SYMBOL_GPL(nfs_server_copy_userdata);
 842 
 843 void nfs_server_insert_lists(struct nfs_server *server)
 844 {
 845         struct nfs_client *clp = server->nfs_client;
 846         struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
 847 
 848         spin_lock(&nn->nfs_client_lock);
 849         list_add_tail_rcu(&server->client_link, &clp->cl_superblocks);
 850         list_add_tail(&server->master_link, &nn->nfs_volume_list);
 851         clear_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
 852         spin_unlock(&nn->nfs_client_lock);
 853 
 854 }
 855 EXPORT_SYMBOL_GPL(nfs_server_insert_lists);
 856 
 857 void nfs_server_remove_lists(struct nfs_server *server)
 858 {
 859         struct nfs_client *clp = server->nfs_client;
 860         struct nfs_net *nn;
 861 
 862         if (clp == NULL)
 863                 return;
 864         nn = net_generic(clp->cl_net, nfs_net_id);
 865         spin_lock(&nn->nfs_client_lock);
 866         list_del_rcu(&server->client_link);
 867         if (list_empty(&clp->cl_superblocks))
 868                 set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
 869         list_del(&server->master_link);
 870         spin_unlock(&nn->nfs_client_lock);
 871 
 872         synchronize_rcu();
 873 }
 874 EXPORT_SYMBOL_GPL(nfs_server_remove_lists);
 875 
 876 /*
 877  * Allocate and initialise a server record
 878  */
 879 struct nfs_server *nfs_alloc_server(void)
 880 {
 881         struct nfs_server *server;
 882 
 883         server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL);
 884         if (!server)
 885                 return NULL;
 886 
 887         server->client = server->client_acl = ERR_PTR(-EINVAL);
 888 
 889         /* Zero out the NFS state stuff */
 890         INIT_LIST_HEAD(&server->client_link);
 891         INIT_LIST_HEAD(&server->master_link);
 892         INIT_LIST_HEAD(&server->delegations);
 893         INIT_LIST_HEAD(&server->layouts);
 894         INIT_LIST_HEAD(&server->state_owners_lru);
 895         INIT_LIST_HEAD(&server->ss_copies);
 896 
 897         atomic_set(&server->active, 0);
 898 
 899         server->io_stats = nfs_alloc_iostats();
 900         if (!server->io_stats) {
 901                 kfree(server);
 902                 return NULL;
 903         }
 904 
 905         ida_init(&server->openowner_id);
 906         ida_init(&server->lockowner_id);
 907         pnfs_init_server(server);
 908         rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC");
 909 
 910         return server;
 911 }
 912 EXPORT_SYMBOL_GPL(nfs_alloc_server);
 913 
 914 /*
 915  * Free up a server record
 916  */
 917 void nfs_free_server(struct nfs_server *server)
 918 {
 919         nfs_server_remove_lists(server);
 920 
 921         if (server->destroy != NULL)
 922                 server->destroy(server);
 923 
 924         if (!IS_ERR(server->client_acl))
 925                 rpc_shutdown_client(server->client_acl);
 926         if (!IS_ERR(server->client))
 927                 rpc_shutdown_client(server->client);
 928 
 929         nfs_put_client(server->nfs_client);
 930 
 931         ida_destroy(&server->lockowner_id);
 932         ida_destroy(&server->openowner_id);
 933         nfs_free_iostats(server->io_stats);
 934         put_cred(server->cred);
 935         kfree(server);
 936         nfs_release_automount_timer();
 937 }
 938 EXPORT_SYMBOL_GPL(nfs_free_server);
 939 
 940 /*
 941  * Create a version 2 or 3 volume record
 942  * - keyed on server and FSID
 943  */
 944 struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
 945                                      struct nfs_subversion *nfs_mod)
 946 {
 947         struct nfs_server *server;
 948         struct nfs_fattr *fattr;
 949         int error;
 950 
 951         server = nfs_alloc_server();
 952         if (!server)
 953                 return ERR_PTR(-ENOMEM);
 954 
 955         server->cred = get_cred(current_cred());
 956 
 957         error = -ENOMEM;
 958         fattr = nfs_alloc_fattr();
 959         if (fattr == NULL)
 960                 goto error;
 961 
 962         /* Get a client representation */
 963         error = nfs_init_server(server, mount_info->parsed, nfs_mod);
 964         if (error < 0)
 965                 goto error;
 966 
 967         /* Probe the root fh to retrieve its FSID */
 968         error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr);
 969         if (error < 0)
 970                 goto error;
 971         if (server->nfs_client->rpc_ops->version == 3) {
 972                 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
 973                         server->namelen = NFS3_MAXNAMLEN;
 974                 if (!(mount_info->parsed->flags & NFS_MOUNT_NORDIRPLUS))
 975                         server->caps |= NFS_CAP_READDIRPLUS;
 976         } else {
 977                 if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)
 978                         server->namelen = NFS2_MAXNAMLEN;
 979         }
 980 
 981         if (!(fattr->valid & NFS_ATTR_FATTR)) {
 982                 error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh,
 983                                 fattr, NULL, NULL);
 984                 if (error < 0) {
 985                         dprintk("nfs_create_server: getattr error = %d\n", -error);
 986                         goto error;
 987                 }
 988         }
 989         memcpy(&server->fsid, &fattr->fsid, sizeof(server->fsid));
 990 
 991         dprintk("Server FSID: %llx:%llx\n",
 992                 (unsigned long long) server->fsid.major,
 993                 (unsigned long long) server->fsid.minor);
 994 
 995         nfs_server_insert_lists(server);
 996         server->mount_time = jiffies;
 997         nfs_free_fattr(fattr);
 998         return server;
 999 
1000 error:
1001         nfs_free_fattr(fattr);
1002         nfs_free_server(server);
1003         return ERR_PTR(error);
1004 }
1005 EXPORT_SYMBOL_GPL(nfs_create_server);
1006 
1007 /*
1008  * Clone an NFS2, NFS3 or NFS4 server record
1009  */
1010 struct nfs_server *nfs_clone_server(struct nfs_server *source,
1011                                     struct nfs_fh *fh,
1012                                     struct nfs_fattr *fattr,
1013                                     rpc_authflavor_t flavor)
1014 {
1015         struct nfs_server *server;
1016         struct nfs_fattr *fattr_fsinfo;
1017         int error;
1018 
1019         server = nfs_alloc_server();
1020         if (!server)
1021                 return ERR_PTR(-ENOMEM);
1022 
1023         server->cred = get_cred(source->cred);
1024 
1025         error = -ENOMEM;
1026         fattr_fsinfo = nfs_alloc_fattr();
1027         if (fattr_fsinfo == NULL)
1028                 goto out_free_server;
1029 
1030         /* Copy data from the source */
1031         server->nfs_client = source->nfs_client;
1032         server->destroy = source->destroy;
1033         refcount_inc(&server->nfs_client->cl_count);
1034         nfs_server_copy_userdata(server, source);
1035 
1036         server->fsid = fattr->fsid;
1037 
1038         error = nfs_init_server_rpcclient(server,
1039                         source->client->cl_timeout,
1040                         flavor);
1041         if (error < 0)
1042                 goto out_free_server;
1043 
1044         /* probe the filesystem info for this server filesystem */
1045         error = nfs_probe_fsinfo(server, fh, fattr_fsinfo);
1046         if (error < 0)
1047                 goto out_free_server;
1048 
1049         if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
1050                 server->namelen = NFS4_MAXNAMLEN;
1051 
1052         error = nfs_start_lockd(server);
1053         if (error < 0)
1054                 goto out_free_server;
1055 
1056         nfs_server_insert_lists(server);
1057         server->mount_time = jiffies;
1058 
1059         nfs_free_fattr(fattr_fsinfo);
1060         return server;
1061 
1062 out_free_server:
1063         nfs_free_fattr(fattr_fsinfo);
1064         nfs_free_server(server);
1065         return ERR_PTR(error);
1066 }
1067 EXPORT_SYMBOL_GPL(nfs_clone_server);
1068 
1069 void nfs_clients_init(struct net *net)
1070 {
1071         struct nfs_net *nn = net_generic(net, nfs_net_id);
1072 
1073         INIT_LIST_HEAD(&nn->nfs_client_list);
1074         INIT_LIST_HEAD(&nn->nfs_volume_list);
1075 #if IS_ENABLED(CONFIG_NFS_V4)
1076         idr_init(&nn->cb_ident_idr);
1077 #endif
1078         spin_lock_init(&nn->nfs_client_lock);
1079         nn->boot_time = ktime_get_real();
1080 
1081         nfs_netns_sysfs_setup(nn, net);
1082 }
1083 
1084 void nfs_clients_exit(struct net *net)
1085 {
1086         struct nfs_net *nn = net_generic(net, nfs_net_id);
1087 
1088         nfs_netns_sysfs_destroy(nn);
1089         nfs_cleanup_cb_ident_idr(net);
1090         WARN_ON_ONCE(!list_empty(&nn->nfs_client_list));
1091         WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list));
1092 }
1093 
1094 #ifdef CONFIG_PROC_FS
1095 static void *nfs_server_list_start(struct seq_file *p, loff_t *pos);
1096 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos);
1097 static void nfs_server_list_stop(struct seq_file *p, void *v);
1098 static int nfs_server_list_show(struct seq_file *m, void *v);
1099 
1100 static const struct seq_operations nfs_server_list_ops = {
1101         .start  = nfs_server_list_start,
1102         .next   = nfs_server_list_next,
1103         .stop   = nfs_server_list_stop,
1104         .show   = nfs_server_list_show,
1105 };
1106 
1107 static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos);
1108 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos);
1109 static void nfs_volume_list_stop(struct seq_file *p, void *v);
1110 static int nfs_volume_list_show(struct seq_file *m, void *v);
1111 
1112 static const struct seq_operations nfs_volume_list_ops = {
1113         .start  = nfs_volume_list_start,
1114         .next   = nfs_volume_list_next,
1115         .stop   = nfs_volume_list_stop,
1116         .show   = nfs_volume_list_show,
1117 };
1118 
1119 /*
1120  * set up the iterator to start reading from the server list and return the first item
1121  */
1122 static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos)
1123                                 __acquires(&nn->nfs_client_lock)
1124 {
1125         struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1126 
1127         /* lock the list against modification */
1128         spin_lock(&nn->nfs_client_lock);
1129         return seq_list_start_head(&nn->nfs_client_list, *_pos);
1130 }
1131 
1132 /*
1133  * move to next server
1134  */
1135 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos)
1136 {
1137         struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1138 
1139         return seq_list_next(v, &nn->nfs_client_list, pos);
1140 }
1141 
1142 /*
1143  * clean up after reading from the transports list
1144  */
1145 static void nfs_server_list_stop(struct seq_file *p, void *v)
1146                                 __releases(&nn->nfs_client_lock)
1147 {
1148         struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1149 
1150         spin_unlock(&nn->nfs_client_lock);
1151 }
1152 
1153 /*
1154  * display a header line followed by a load of call lines
1155  */
1156 static int nfs_server_list_show(struct seq_file *m, void *v)
1157 {
1158         struct nfs_client *clp;
1159         struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1160 
1161         /* display header on line 1 */
1162         if (v == &nn->nfs_client_list) {
1163                 seq_puts(m, "NV SERVER   PORT USE HOSTNAME\n");
1164                 return 0;
1165         }
1166 
1167         /* display one transport per line on subsequent lines */
1168         clp = list_entry(v, struct nfs_client, cl_share_link);
1169 
1170         /* Check if the client is initialized */
1171         if (clp->cl_cons_state != NFS_CS_READY)
1172                 return 0;
1173 
1174         rcu_read_lock();
1175         seq_printf(m, "v%u %s %s %3d %s\n",
1176                    clp->rpc_ops->version,
1177                    rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
1178                    rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
1179                    refcount_read(&clp->cl_count),
1180                    clp->cl_hostname);
1181         rcu_read_unlock();
1182 
1183         return 0;
1184 }
1185 
1186 /*
1187  * set up the iterator to start reading from the volume list and return the first item
1188  */
1189 static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos)
1190                                 __acquires(&nn->nfs_client_lock)
1191 {
1192         struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1193 
1194         /* lock the list against modification */
1195         spin_lock(&nn->nfs_client_lock);
1196         return seq_list_start_head(&nn->nfs_volume_list, *_pos);
1197 }
1198 
1199 /*
1200  * move to next volume
1201  */
1202 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos)
1203 {
1204         struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1205 
1206         return seq_list_next(v, &nn->nfs_volume_list, pos);
1207 }
1208 
1209 /*
1210  * clean up after reading from the transports list
1211  */
1212 static void nfs_volume_list_stop(struct seq_file *p, void *v)
1213                                 __releases(&nn->nfs_client_lock)
1214 {
1215         struct nfs_net *nn = net_generic(seq_file_net(p), nfs_net_id);
1216 
1217         spin_unlock(&nn->nfs_client_lock);
1218 }
1219 
1220 /*
1221  * display a header line followed by a load of call lines
1222  */
1223 static int nfs_volume_list_show(struct seq_file *m, void *v)
1224 {
1225         struct nfs_server *server;
1226         struct nfs_client *clp;
1227         char dev[13];   // 8 for 2^24, 1 for ':', 3 for 2^8, 1 for '\0'
1228         char fsid[34];  // 2 * 16 for %llx, 1 for ':', 1 for '\0'
1229         struct nfs_net *nn = net_generic(seq_file_net(m), nfs_net_id);
1230 
1231         /* display header on line 1 */
1232         if (v == &nn->nfs_volume_list) {
1233                 seq_puts(m, "NV SERVER   PORT DEV          FSID"
1234                             "                              FSC\n");
1235                 return 0;
1236         }
1237         /* display one transport per line on subsequent lines */
1238         server = list_entry(v, struct nfs_server, master_link);
1239         clp = server->nfs_client;
1240 
1241         snprintf(dev, sizeof(dev), "%u:%u",
1242                  MAJOR(server->s_dev), MINOR(server->s_dev));
1243 
1244         snprintf(fsid, sizeof(fsid), "%llx:%llx",
1245                  (unsigned long long) server->fsid.major,
1246                  (unsigned long long) server->fsid.minor);
1247 
1248         rcu_read_lock();
1249         seq_printf(m, "v%u %s %s %-12s %-33s %s\n",
1250                    clp->rpc_ops->version,
1251                    rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_ADDR),
1252                    rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_HEX_PORT),
1253                    dev,
1254                    fsid,
1255                    nfs_server_fscache_state(server));
1256         rcu_read_unlock();
1257 
1258         return 0;
1259 }
1260 
1261 int nfs_fs_proc_net_init(struct net *net)
1262 {
1263         struct nfs_net *nn = net_generic(net, nfs_net_id);
1264         struct proc_dir_entry *p;
1265 
1266         nn->proc_nfsfs = proc_net_mkdir(net, "nfsfs", net->proc_net);
1267         if (!nn->proc_nfsfs)
1268                 goto error_0;
1269 
1270         /* a file of servers with which we're dealing */
1271         p = proc_create_net("servers", S_IFREG|S_IRUGO, nn->proc_nfsfs,
1272                         &nfs_server_list_ops, sizeof(struct seq_net_private));
1273         if (!p)
1274                 goto error_1;
1275 
1276         /* a file of volumes that we have mounted */
1277         p = proc_create_net("volumes", S_IFREG|S_IRUGO, nn->proc_nfsfs,
1278                         &nfs_volume_list_ops, sizeof(struct seq_net_private));
1279         if (!p)
1280                 goto error_1;
1281         return 0;
1282 
1283 error_1:
1284         remove_proc_subtree("nfsfs", net->proc_net);
1285 error_0:
1286         return -ENOMEM;
1287 }
1288 
1289 void nfs_fs_proc_net_exit(struct net *net)
1290 {
1291         remove_proc_subtree("nfsfs", net->proc_net);
1292 }
1293 
1294 /*
1295  * initialise the /proc/fs/nfsfs/ directory
1296  */
1297 int __init nfs_fs_proc_init(void)
1298 {
1299         if (!proc_mkdir("fs/nfsfs", NULL))
1300                 goto error_0;
1301 
1302         /* a file of servers with which we're dealing */
1303         if (!proc_symlink("fs/nfsfs/servers", NULL, "../../net/nfsfs/servers"))
1304                 goto error_1;
1305 
1306         /* a file of volumes that we have mounted */
1307         if (!proc_symlink("fs/nfsfs/volumes", NULL, "../../net/nfsfs/volumes"))
1308                 goto error_1;
1309 
1310         return 0;
1311 error_1:
1312         remove_proc_subtree("fs/nfsfs", NULL);
1313 error_0:
1314         return -ENOMEM;
1315 }
1316 
1317 /*
1318  * clean up the /proc/fs/nfsfs/ directory
1319  */
1320 void nfs_fs_proc_exit(void)
1321 {
1322         remove_proc_subtree("fs/nfsfs", NULL);
1323 }
1324 
1325 #endif /* CONFIG_PROC_FS */

/* [<][>][^][v][top][bottom][index][help] */