1 /* client.c: NFS client sharing and management code 2 * 3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 13 #include <linux/config.h> 14 #include <linux/module.h> 15 #include <linux/init.h> 16 17 #include <linux/time.h> 18 #include <linux/kernel.h> 19 #include <linux/mm.h> 20 #include <linux/string.h> 21 #include <linux/stat.h> 22 #include <linux/errno.h> 23 #include <linux/unistd.h> 24 #include <linux/sunrpc/clnt.h> 25 #include <linux/sunrpc/stats.h> 26 #include <linux/sunrpc/metrics.h> 27 #include <linux/nfs_fs.h> 28 #include <linux/nfs_mount.h> 29 #include <linux/nfs4_mount.h> 30 #include <linux/lockd/bind.h> 31 #include <linux/smp_lock.h> 32 #include <linux/seq_file.h> 33 #include <linux/mount.h> 34 #include <linux/nfs_idmap.h> 35 #include <linux/vfs.h> 36 #include <linux/inet.h> 37 #include <linux/nfs_xdr.h> 38 39 #include <asm/system.h> 40 41 #include "nfs4_fs.h" 42 #include "callback.h" 43 #include "delegation.h" 44 #include "iostat.h" 45 #include "internal.h" 46 47 #define NFSDBG_FACILITY NFSDBG_CLIENT 48 49 static DEFINE_SPINLOCK(nfs_client_lock); 50 static LIST_HEAD(nfs_client_list); 51 static LIST_HEAD(nfs_volume_list); 52 static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq); 53 54 /* 55 * RPC cruft for NFS 56 */ 57 static struct rpc_version *nfs_version[5] = { 58 [2] = &nfs_version2, 59 #ifdef CONFIG_NFS_V3 60 [3] = &nfs_version3, 61 #endif 62 #ifdef CONFIG_NFS_V4 63 [4] = &nfs_version4, 64 #endif 65 }; 66 67 struct rpc_program nfs_program = { 68 .name = "nfs", 69 .number = NFS_PROGRAM, 70 .nrvers = ARRAY_SIZE(nfs_version), 71 .version = nfs_version, 72 .stats = &nfs_rpcstat, 73 .pipe_dir_name = "/nfs", 74 }; 75 76 struct rpc_stat nfs_rpcstat = { 77 .program = &nfs_program 78 }; 79 80 81 #ifdef CONFIG_NFS_V3_ACL 82 static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; 83 static struct rpc_version * nfsacl_version[] = { 84 [3] = &nfsacl_version3, 85 }; 86 87 struct rpc_program nfsacl_program = { 88 .name = "nfsacl", 89 .number = NFS_ACL_PROGRAM, 90 .nrvers = ARRAY_SIZE(nfsacl_version), 91 .version = nfsacl_version, 92 .stats = &nfsacl_rpcstat, 93 }; 94 #endif /* CONFIG_NFS_V3_ACL */ 95 96 /* 97 * Allocate a shared client record 98 * 99 * Since these are allocated/deallocated very rarely, we don't 100 * bother putting them in a slab cache... 101 */ 102 static struct nfs_client *nfs_alloc_client(const char *hostname, 103 const struct sockaddr_in *addr, 104 int nfsversion) 105 { 106 struct nfs_client *clp; 107 int error; 108 109 if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) 110 goto error_0; 111 112 error = rpciod_up(); 113 if (error < 0) { 114 dprintk("%s: couldn't start rpciod! Error = %d\n", 115 __FUNCTION__, error); 116 goto error_1; 117 } 118 __set_bit(NFS_CS_RPCIOD, &clp->cl_res_state); 119 120 if (nfsversion == 4) { 121 if (nfs_callback_up() < 0) 122 goto error_2; 123 __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); 124 } 125 126 atomic_set(&clp->cl_count, 1); 127 clp->cl_cons_state = NFS_CS_INITING; 128 129 clp->cl_nfsversion = nfsversion; 130 memcpy(&clp->cl_addr, addr, sizeof(clp->cl_addr)); 131 132 if (hostname) { 133 clp->cl_hostname = kstrdup(hostname, GFP_KERNEL); 134 if (!clp->cl_hostname) 135 goto error_3; 136 } 137 138 INIT_LIST_HEAD(&clp->cl_superblocks); 139 clp->cl_rpcclient = ERR_PTR(-EINVAL); 140 141 #ifdef CONFIG_NFS_V4 142 init_rwsem(&clp->cl_sem); 143 INIT_LIST_HEAD(&clp->cl_delegations); 144 INIT_LIST_HEAD(&clp->cl_state_owners); 145 INIT_LIST_HEAD(&clp->cl_unused); 146 spin_lock_init(&clp->cl_lock); 147 INIT_WORK(&clp->cl_renewd, nfs4_renew_state, clp); 148 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); 149 clp->cl_boot_time = CURRENT_TIME; 150 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; 151 #endif 152 153 return clp; 154 155 error_3: 156 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) 157 nfs_callback_down(); 158 error_2: 159 rpciod_down(); 160 __clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state); 161 error_1: 162 kfree(clp); 163 error_0: 164 return NULL; 165 } 166 167 static void nfs4_shutdown_client(struct nfs_client *clp) 168 { 169 #ifdef CONFIG_NFS_V4 170 if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) 171 nfs4_kill_renewd(clp); 172 while (!list_empty(&clp->cl_unused)) { 173 struct nfs4_state_owner *sp; 174 175 sp = list_entry(clp->cl_unused.next, 176 struct nfs4_state_owner, 177 so_list); 178 list_del(&sp->so_list); 179 kfree(sp); 180 } 181 BUG_ON(!list_empty(&clp->cl_state_owners)); 182 if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) 183 nfs_idmap_delete(clp); 184 #endif 185 } 186 187 /* 188 * Destroy a shared client record 189 */ 190 static void nfs_free_client(struct nfs_client *clp) 191 { 192 dprintk("--> nfs_free_client(%d)\n", clp->cl_nfsversion); 193 194 nfs4_shutdown_client(clp); 195 196 /* -EIO all pending I/O */ 197 if (!IS_ERR(clp->cl_rpcclient)) 198 rpc_shutdown_client(clp->cl_rpcclient); 199 200 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) 201 nfs_callback_down(); 202 203 if (__test_and_clear_bit(NFS_CS_RPCIOD, &clp->cl_res_state)) 204 rpciod_down(); 205 206 kfree(clp->cl_hostname); 207 kfree(clp); 208 209 dprintk("<-- nfs_free_client()\n"); 210 } 211 212 /* 213 * Release a reference to a shared client record 214 */ 215 void nfs_put_client(struct nfs_client *clp) 216 { 217 if (!clp) 218 return; 219 220 dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count)); 221 222 if (atomic_dec_and_lock(&clp->cl_count, &nfs_client_lock)) { 223 list_del(&clp->cl_share_link); 224 spin_unlock(&nfs_client_lock); 225 226 BUG_ON(!list_empty(&clp->cl_superblocks)); 227 228 nfs_free_client(clp); 229 } 230 } 231 232 /* 233 * Find a client by address 234 * - caller must hold nfs_client_lock 235 */ 236 static struct nfs_client *__nfs_find_client(const struct sockaddr_in *addr, int nfsversion) 237 { 238 struct nfs_client *clp; 239 240 list_for_each_entry(clp, &nfs_client_list, cl_share_link) { 241 /* Different NFS versions cannot share the same nfs_client */ 242 if (clp->cl_nfsversion != nfsversion) 243 continue; 244 245 if (memcmp(&clp->cl_addr.sin_addr, &addr->sin_addr, 246 sizeof(clp->cl_addr.sin_addr)) != 0) 247 continue; 248 249 if (clp->cl_addr.sin_port == addr->sin_port) 250 goto found; 251 } 252 253 return NULL; 254 255 found: 256 atomic_inc(&clp->cl_count); 257 return clp; 258 } 259 260 /* 261 * Find a client by IP address and protocol version 262 * - returns NULL if no such client 263 */ 264 struct nfs_client *nfs_find_client(const struct sockaddr_in *addr, int nfsversion) 265 { 266 struct nfs_client *clp; 267 268 spin_lock(&nfs_client_lock); 269 clp = __nfs_find_client(addr, nfsversion); 270 spin_unlock(&nfs_client_lock); 271 272 BUG_ON(clp && clp->cl_cons_state == 0); 273 274 return clp; 275 } 276 277 /* 278 * Look up a client by IP address and protocol version 279 * - creates a new record if one doesn't yet exist 280 */ 281 static struct nfs_client *nfs_get_client(const char *hostname, 282 const struct sockaddr_in *addr, 283 int nfsversion) 284 { 285 struct nfs_client *clp, *new = NULL; 286 int error; 287 288 dprintk("--> nfs_get_client(%s,"NIPQUAD_FMT":%d,%d)\n", 289 hostname ?: "", NIPQUAD(addr->sin_addr), 290 addr->sin_port, nfsversion); 291 292 /* see if the client already exists */ 293 do { 294 spin_lock(&nfs_client_lock); 295 296 clp = __nfs_find_client(addr, nfsversion); 297 if (clp) 298 goto found_client; 299 if (new) 300 goto install_client; 301 302 spin_unlock(&nfs_client_lock); 303 304 new = nfs_alloc_client(hostname, addr, nfsversion); 305 } while (new); 306 307 return ERR_PTR(-ENOMEM); 308 309 /* install a new client and return with it unready */ 310 install_client: 311 clp = new; 312 list_add(&clp->cl_share_link, &nfs_client_list); 313 spin_unlock(&nfs_client_lock); 314 dprintk("--> nfs_get_client() = %p [new]\n", clp); 315 return clp; 316 317 /* found an existing client 318 * - make sure it's ready before returning 319 */ 320 found_client: 321 spin_unlock(&nfs_client_lock); 322 323 if (new) 324 nfs_free_client(new); 325 326 if (clp->cl_cons_state == NFS_CS_INITING) { 327 DECLARE_WAITQUEUE(myself, current); 328 329 add_wait_queue(&nfs_client_active_wq, &myself); 330 331 for (;;) { 332 set_current_state(TASK_INTERRUPTIBLE); 333 if (signal_pending(current) || 334 clp->cl_cons_state > NFS_CS_READY) 335 break; 336 schedule(); 337 } 338 339 remove_wait_queue(&nfs_client_active_wq, &myself); 340 341 if (signal_pending(current)) { 342 nfs_put_client(clp); 343 return ERR_PTR(-ERESTARTSYS); 344 } 345 } 346 347 if (clp->cl_cons_state < NFS_CS_READY) { 348 error = clp->cl_cons_state; 349 nfs_put_client(clp); 350 return ERR_PTR(error); 351 } 352 353 BUG_ON(clp->cl_cons_state != NFS_CS_READY); 354 355 dprintk("--> nfs_get_client() = %p [share]\n", clp); 356 return clp; 357 } 358 359 /* 360 * Mark a server as ready or failed 361 */ 362 static void nfs_mark_client_ready(struct nfs_client *clp, int state) 363 { 364 clp->cl_cons_state = state; 365 wake_up_all(&nfs_client_active_wq); 366 } 367 368 /* 369 * Initialise the timeout values for a connection 370 */ 371 static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, 372 unsigned int timeo, unsigned int retrans) 373 { 374 to->to_initval = timeo * HZ / 10; 375 to->to_retries = retrans; 376 if (!to->to_retries) 377 to->to_retries = 2; 378 379 switch (proto) { 380 case IPPROTO_TCP: 381 if (!to->to_initval) 382 to->to_initval = 60 * HZ; 383 if (to->to_initval > NFS_MAX_TCP_TIMEOUT) 384 to->to_initval = NFS_MAX_TCP_TIMEOUT; 385 to->to_increment = to->to_initval; 386 to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); 387 to->to_exponential = 0; 388 break; 389 case IPPROTO_UDP: 390 default: 391 if (!to->to_initval) 392 to->to_initval = 11 * HZ / 10; 393 if (to->to_initval > NFS_MAX_UDP_TIMEOUT) 394 to->to_initval = NFS_MAX_UDP_TIMEOUT; 395 to->to_maxval = NFS_MAX_UDP_TIMEOUT; 396 to->to_exponential = 1; 397 break; 398 } 399 } 400 401 /* 402 * Create an RPC client handle 403 */ 404 static int nfs_create_rpc_client(struct nfs_client *clp, int proto, 405 unsigned int timeo, 406 unsigned int retrans, 407 rpc_authflavor_t flavor) 408 { 409 struct rpc_timeout timeparms; 410 struct rpc_clnt *clnt = NULL; 411 struct rpc_create_args args = { 412 .protocol = proto, 413 .address = (struct sockaddr *)&clp->cl_addr, 414 .addrsize = sizeof(clp->cl_addr), 415 .timeout = &timeparms, 416 .servername = clp->cl_hostname, 417 .program = &nfs_program, 418 .version = clp->rpc_ops->version, 419 .authflavor = flavor, 420 }; 421 422 if (!IS_ERR(clp->cl_rpcclient)) 423 return 0; 424 425 nfs_init_timeout_values(&timeparms, proto, timeo, retrans); 426 clp->retrans_timeo = timeparms.to_initval; 427 clp->retrans_count = timeparms.to_retries; 428 429 clnt = rpc_create(&args); 430 if (IS_ERR(clnt)) { 431 dprintk("%s: cannot create RPC client. Error = %ld\n", 432 __FUNCTION__, PTR_ERR(clnt)); 433 return PTR_ERR(clnt); 434 } 435 436 clp->cl_rpcclient = clnt; 437 return 0; 438 } 439 440 /* 441 * Version 2 or 3 client destruction 442 */ 443 static void nfs_destroy_server(struct nfs_server *server) 444 { 445 if (!IS_ERR(server->client_acl)) 446 rpc_shutdown_client(server->client_acl); 447 448 if (!(server->flags & NFS_MOUNT_NONLM)) 449 lockd_down(); /* release rpc.lockd */ 450 } 451 452 /* 453 * Version 2 or 3 lockd setup 454 */ 455 static int nfs_start_lockd(struct nfs_server *server) 456 { 457 int error = 0; 458 459 if (server->nfs_client->cl_nfsversion > 3) 460 goto out; 461 if (server->flags & NFS_MOUNT_NONLM) 462 goto out; 463 error = lockd_up((server->flags & NFS_MOUNT_TCP) ? 464 IPPROTO_TCP : IPPROTO_UDP); 465 if (error < 0) 466 server->flags |= NFS_MOUNT_NONLM; 467 else 468 server->destroy = nfs_destroy_server; 469 out: 470 return error; 471 } 472 473 /* 474 * Initialise an NFSv3 ACL client connection 475 */ 476 #ifdef CONFIG_NFS_V3_ACL 477 static void nfs_init_server_aclclient(struct nfs_server *server) 478 { 479 if (server->nfs_client->cl_nfsversion != 3) 480 goto out_noacl; 481 if (server->flags & NFS_MOUNT_NOACL) 482 goto out_noacl; 483 484 server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); 485 if (IS_ERR(server->client_acl)) 486 goto out_noacl; 487 488 /* No errors! Assume that Sun nfsacls are supported */ 489 server->caps |= NFS_CAP_ACLS; 490 return; 491 492 out_noacl: 493 server->caps &= ~NFS_CAP_ACLS; 494 } 495 #else 496 static inline void nfs_init_server_aclclient(struct nfs_server *server) 497 { 498 server->flags &= ~NFS_MOUNT_NOACL; 499 server->caps &= ~NFS_CAP_ACLS; 500 } 501 #endif 502 503 /* 504 * Create a general RPC client 505 */ 506 static int nfs_init_server_rpcclient(struct nfs_server *server, rpc_authflavor_t pseudoflavour) 507 { 508 struct nfs_client *clp = server->nfs_client; 509 510 server->client = rpc_clone_client(clp->cl_rpcclient); 511 if (IS_ERR(server->client)) { 512 dprintk("%s: couldn't create rpc_client!\n", __FUNCTION__); 513 return PTR_ERR(server->client); 514 } 515 516 if (pseudoflavour != clp->cl_rpcclient->cl_auth->au_flavor) { 517 struct rpc_auth *auth; 518 519 auth = rpcauth_create(pseudoflavour, server->client); 520 if (IS_ERR(auth)) { 521 dprintk("%s: couldn't create credcache!\n", __FUNCTION__); 522 return PTR_ERR(auth); 523 } 524 } 525 server->client->cl_softrtry = 0; 526 if (server->flags & NFS_MOUNT_SOFT) 527 server->client->cl_softrtry = 1; 528 529 server->client->cl_intr = 0; 530 if (server->flags & NFS4_MOUNT_INTR) 531 server->client->cl_intr = 1; 532 533 return 0; 534 } 535 536 /* 537 * Initialise an NFS2 or NFS3 client 538 */ 539 static int nfs_init_client(struct nfs_client *clp, const struct nfs_mount_data *data) 540 { 541 int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; 542 int error; 543 544 if (clp->cl_cons_state == NFS_CS_READY) { 545 /* the client is already initialised */ 546 dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp); 547 return 0; 548 } 549 550 /* Check NFS protocol revision and initialize RPC op vector */ 551 clp->rpc_ops = &nfs_v2_clientops; 552 #ifdef CONFIG_NFS_V3 553 if (clp->cl_nfsversion == 3) 554 clp->rpc_ops = &nfs_v3_clientops; 555 #endif 556 /* 557 * Create a client RPC handle for doing FSSTAT with UNIX auth only 558 * - RFC 2623, sec 2.3.2 559 */ 560 error = nfs_create_rpc_client(clp, proto, data->timeo, data->retrans, 561 RPC_AUTH_UNIX); 562 if (error < 0) 563 goto error; 564 nfs_mark_client_ready(clp, NFS_CS_READY); 565 return 0; 566 567 error: 568 nfs_mark_client_ready(clp, error); 569 dprintk("<-- nfs_init_client() = xerror %d\n", error); 570 return error; 571 } 572 573 /* 574 * Create a version 2 or 3 client 575 */ 576 static int nfs_init_server(struct nfs_server *server, const struct nfs_mount_data *data) 577 { 578 struct nfs_client *clp; 579 int error, nfsvers = 2; 580 581 dprintk("--> nfs_init_server()\n"); 582 583 #ifdef CONFIG_NFS_V3 584 if (data->flags & NFS_MOUNT_VER3) 585 nfsvers = 3; 586 #endif 587 588 /* Allocate or find a client reference we can use */ 589 clp = nfs_get_client(data->hostname, &data->addr, nfsvers); 590 if (IS_ERR(clp)) { 591 dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp)); 592 return PTR_ERR(clp); 593 } 594 595 error = nfs_init_client(clp, data); 596 if (error < 0) 597 goto error; 598 599 server->nfs_client = clp; 600 601 /* Initialise the client representation from the mount data */ 602 server->flags = data->flags & NFS_MOUNT_FLAGMASK; 603 604 if (data->rsize) 605 server->rsize = nfs_block_size(data->rsize, NULL); 606 if (data->wsize) 607 server->wsize = nfs_block_size(data->wsize, NULL); 608 609 server->acregmin = data->acregmin * HZ; 610 server->acregmax = data->acregmax * HZ; 611 server->acdirmin = data->acdirmin * HZ; 612 server->acdirmax = data->acdirmax * HZ; 613 614 /* Start lockd here, before we might error out */ 615 error = nfs_start_lockd(server); 616 if (error < 0) 617 goto error; 618 619 error = nfs_init_server_rpcclient(server, data->pseudoflavor); 620 if (error < 0) 621 goto error; 622 623 server->namelen = data->namlen; 624 /* Create a client RPC handle for the NFSv3 ACL management interface */ 625 nfs_init_server_aclclient(server); 626 if (clp->cl_nfsversion == 3) { 627 if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) 628 server->namelen = NFS3_MAXNAMLEN; 629 server->caps |= NFS_CAP_READDIRPLUS; 630 } else { 631 if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) 632 server->namelen = NFS2_MAXNAMLEN; 633 } 634 635 dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp); 636 return 0; 637 638 error: 639 server->nfs_client = NULL; 640 nfs_put_client(clp); 641 dprintk("<-- nfs_init_server() = xerror %d\n", error); 642 return error; 643 } 644 645 /* 646 * Load up the server record from information gained in an fsinfo record 647 */ 648 static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *fsinfo) 649 { 650 unsigned long max_rpc_payload; 651 652 /* Work out a lot of parameters */ 653 if (server->rsize == 0) 654 server->rsize = nfs_block_size(fsinfo->rtpref, NULL); 655 if (server->wsize == 0) 656 server->wsize = nfs_block_size(fsinfo->wtpref, NULL); 657 658 if (fsinfo->rtmax >= 512 && server->rsize > fsinfo->rtmax) 659 server->rsize = nfs_block_size(fsinfo->rtmax, NULL); 660 if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) 661 server->wsize = nfs_block_size(fsinfo->wtmax, NULL); 662 663 max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); 664 if (server->rsize > max_rpc_payload) 665 server->rsize = max_rpc_payload; 666 if (server->rsize > NFS_MAX_FILE_IO_SIZE) 667 server->rsize = NFS_MAX_FILE_IO_SIZE; 668 server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 669 server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; 670 671 if (server->wsize > max_rpc_payload) 672 server->wsize = max_rpc_payload; 673 if (server->wsize > NFS_MAX_FILE_IO_SIZE) 674 server->wsize = NFS_MAX_FILE_IO_SIZE; 675 server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 676 server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); 677 678 server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); 679 if (server->dtsize > PAGE_CACHE_SIZE) 680 server->dtsize = PAGE_CACHE_SIZE; 681 if (server->dtsize > server->rsize) 682 server->dtsize = server->rsize; 683 684 if (server->flags & NFS_MOUNT_NOAC) { 685 server->acregmin = server->acregmax = 0; 686 server->acdirmin = server->acdirmax = 0; 687 } 688 689 server->maxfilesize = fsinfo->maxfilesize; 690 691 /* We're airborne Set socket buffersize */ 692 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); 693 } 694 695 /* 696 * Probe filesystem information, including the FSID on v2/v3 697 */ 698 static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs_fattr *fattr) 699 { 700 struct nfs_fsinfo fsinfo; 701 struct nfs_client *clp = server->nfs_client; 702 int error; 703 704 dprintk("--> nfs_probe_fsinfo()\n"); 705 706 if (clp->rpc_ops->set_capabilities != NULL) { 707 error = clp->rpc_ops->set_capabilities(server, mntfh); 708 if (error < 0) 709 goto out_error; 710 } 711 712 fsinfo.fattr = fattr; 713 nfs_fattr_init(fattr); 714 error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo); 715 if (error < 0) 716 goto out_error; 717 718 nfs_server_set_fsinfo(server, &fsinfo); 719 720 /* Get some general file system info */ 721 if (server->namelen == 0) { 722 struct nfs_pathconf pathinfo; 723 724 pathinfo.fattr = fattr; 725 nfs_fattr_init(fattr); 726 727 if (clp->rpc_ops->pathconf(server, mntfh, &pathinfo) >= 0) 728 server->namelen = pathinfo.max_namelen; 729 } 730 731 dprintk("<-- nfs_probe_fsinfo() = 0\n"); 732 return 0; 733 734 out_error: 735 dprintk("nfs_probe_fsinfo: error = %d\n", -error); 736 return error; 737 } 738 739 /* 740 * Copy useful information when duplicating a server record 741 */ 742 static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) 743 { 744 target->flags = source->flags; 745 target->acregmin = source->acregmin; 746 target->acregmax = source->acregmax; 747 target->acdirmin = source->acdirmin; 748 target->acdirmax = source->acdirmax; 749 target->caps = source->caps; 750 } 751 752 /* 753 * Allocate and initialise a server record 754 */ 755 static struct nfs_server *nfs_alloc_server(void) 756 { 757 struct nfs_server *server; 758 759 server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); 760 if (!server) 761 return NULL; 762 763 server->client = server->client_acl = ERR_PTR(-EINVAL); 764 765 /* Zero out the NFS state stuff */ 766 INIT_LIST_HEAD(&server->client_link); 767 INIT_LIST_HEAD(&server->master_link); 768 769 server->io_stats = nfs_alloc_iostats(); 770 if (!server->io_stats) { 771 kfree(server); 772 return NULL; 773 } 774 775 return server; 776 } 777 778 /* 779 * Free up a server record 780 */ 781 void nfs_free_server(struct nfs_server *server) 782 { 783 dprintk("--> nfs_free_server()\n"); 784 785 spin_lock(&nfs_client_lock); 786 list_del(&server->client_link); 787 list_del(&server->master_link); 788 spin_unlock(&nfs_client_lock); 789 790 if (server->destroy != NULL) 791 server->destroy(server); 792 if (!IS_ERR(server->client)) 793 rpc_shutdown_client(server->client); 794 795 nfs_put_client(server->nfs_client); 796 797 nfs_free_iostats(server->io_stats); 798 kfree(server); 799 nfs_release_automount_timer(); 800 dprintk("<-- nfs_free_server()\n"); 801 } 802 803 /* 804 * Create a version 2 or 3 volume record 805 * - keyed on server and FSID 806 */ 807 struct nfs_server *nfs_create_server(const struct nfs_mount_data *data, 808 struct nfs_fh *mntfh) 809 { 810 struct nfs_server *server; 811 struct nfs_fattr fattr; 812 int error; 813 814 server = nfs_alloc_server(); 815 if (!server) 816 return ERR_PTR(-ENOMEM); 817 818 /* Get a client representation */ 819 error = nfs_init_server(server, data); 820 if (error < 0) 821 goto error; 822 823 BUG_ON(!server->nfs_client); 824 BUG_ON(!server->nfs_client->rpc_ops); 825 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 826 827 /* Probe the root fh to retrieve its FSID */ 828 error = nfs_probe_fsinfo(server, mntfh, &fattr); 829 if (error < 0) 830 goto error; 831 if (!(fattr.valid & NFS_ATTR_FATTR)) { 832 error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); 833 if (error < 0) { 834 dprintk("nfs_create_server: getattr error = %d\n", -error); 835 goto error; 836 } 837 } 838 memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); 839 840 dprintk("Server FSID: %llx:%llx\n", 841 (unsigned long long) server->fsid.major, 842 (unsigned long long) server->fsid.minor); 843 844 BUG_ON(!server->nfs_client); 845 BUG_ON(!server->nfs_client->rpc_ops); 846 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 847 848 spin_lock(&nfs_client_lock); 849 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); 850 list_add_tail(&server->master_link, &nfs_volume_list); 851 spin_unlock(&nfs_client_lock); 852 853 server->mount_time = jiffies; 854 return server; 855 856 error: 857 nfs_free_server(server); 858 return ERR_PTR(error); 859 } 860 861 #ifdef CONFIG_NFS_V4 862 /* 863 * Initialise an NFS4 client record 864 */ 865 static int nfs4_init_client(struct nfs_client *clp, 866 int proto, int timeo, int retrans, 867 rpc_authflavor_t authflavour) 868 { 869 int error; 870 871 if (clp->cl_cons_state == NFS_CS_READY) { 872 /* the client is initialised already */ 873 dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); 874 return 0; 875 } 876 877 /* Check NFS protocol revision and initialize RPC op vector */ 878 clp->rpc_ops = &nfs_v4_clientops; 879 880 error = nfs_create_rpc_client(clp, proto, timeo, retrans, authflavour); 881 if (error < 0) 882 goto error; 883 884 error = nfs_idmap_new(clp); 885 if (error < 0) { 886 dprintk("%s: failed to create idmapper. Error = %d\n", 887 __FUNCTION__, error); 888 goto error; 889 } 890 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); 891 892 nfs_mark_client_ready(clp, NFS_CS_READY); 893 return 0; 894 895 error: 896 nfs_mark_client_ready(clp, error); 897 dprintk("<-- nfs4_init_client() = xerror %d\n", error); 898 return error; 899 } 900 901 /* 902 * Set up an NFS4 client 903 */ 904 static int nfs4_set_client(struct nfs_server *server, 905 const char *hostname, const struct sockaddr_in *addr, 906 rpc_authflavor_t authflavour, 907 int proto, int timeo, int retrans) 908 { 909 struct nfs_client *clp; 910 int error; 911 912 dprintk("--> nfs4_set_client()\n"); 913 914 /* Allocate or find a client reference we can use */ 915 clp = nfs_get_client(hostname, addr, 4); 916 if (IS_ERR(clp)) { 917 error = PTR_ERR(clp); 918 goto error; 919 } 920 error = nfs4_init_client(clp, proto, timeo, retrans, authflavour); 921 if (error < 0) 922 goto error_put; 923 924 server->nfs_client = clp; 925 dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); 926 return 0; 927 928 error_put: 929 nfs_put_client(clp); 930 error: 931 dprintk("<-- nfs4_set_client() = xerror %d\n", error); 932 return error; 933 } 934 935 /* 936 * Create a version 4 volume record 937 */ 938 static int nfs4_init_server(struct nfs_server *server, 939 const struct nfs4_mount_data *data, rpc_authflavor_t authflavour) 940 { 941 int error; 942 943 dprintk("--> nfs4_init_server()\n"); 944 945 /* Initialise the client representation from the mount data */ 946 server->flags = data->flags & NFS_MOUNT_FLAGMASK; 947 server->caps |= NFS_CAP_ATOMIC_OPEN; 948 949 if (data->rsize) 950 server->rsize = nfs_block_size(data->rsize, NULL); 951 if (data->wsize) 952 server->wsize = nfs_block_size(data->wsize, NULL); 953 954 server->acregmin = data->acregmin * HZ; 955 server->acregmax = data->acregmax * HZ; 956 server->acdirmin = data->acdirmin * HZ; 957 server->acdirmax = data->acdirmax * HZ; 958 959 error = nfs_init_server_rpcclient(server, authflavour); 960 961 /* Done */ 962 dprintk("<-- nfs4_init_server() = %d\n", error); 963 return error; 964 } 965 966 /* 967 * Create a version 4 volume record 968 * - keyed on server and FSID 969 */ 970 struct nfs_server *nfs4_create_server(const struct nfs4_mount_data *data, 971 const char *hostname, 972 const struct sockaddr_in *addr, 973 const char *mntpath, 974 const char *ip_addr, 975 rpc_authflavor_t authflavour, 976 struct nfs_fh *mntfh) 977 { 978 struct nfs_fattr fattr; 979 struct nfs_server *server; 980 int error; 981 982 dprintk("--> nfs4_create_server()\n"); 983 984 server = nfs_alloc_server(); 985 if (!server) 986 return ERR_PTR(-ENOMEM); 987 988 /* Get a client record */ 989 error = nfs4_set_client(server, hostname, addr, authflavour, 990 data->proto, data->timeo, data->retrans); 991 if (error < 0) 992 goto error; 993 994 /* set up the general RPC client */ 995 error = nfs4_init_server(server, data, authflavour); 996 if (error < 0) 997 goto error; 998 999 BUG_ON(!server->nfs_client); 1000 BUG_ON(!server->nfs_client->rpc_ops); 1001 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 1002 1003 /* Probe the root fh to retrieve its FSID */ 1004 error = nfs4_path_walk(server, mntfh, mntpath); 1005 if (error < 0) 1006 goto error; 1007 1008 dprintk("Server FSID: %llx:%llx\n", 1009 (unsigned long long) server->fsid.major, 1010 (unsigned long long) server->fsid.minor); 1011 dprintk("Mount FH: %d\n", mntfh->size); 1012 1013 error = nfs_probe_fsinfo(server, mntfh, &fattr); 1014 if (error < 0) 1015 goto error; 1016 1017 BUG_ON(!server->nfs_client); 1018 BUG_ON(!server->nfs_client->rpc_ops); 1019 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 1020 1021 spin_lock(&nfs_client_lock); 1022 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); 1023 list_add_tail(&server->master_link, &nfs_volume_list); 1024 spin_unlock(&nfs_client_lock); 1025 1026 server->mount_time = jiffies; 1027 dprintk("<-- nfs4_create_server() = %p\n", server); 1028 return server; 1029 1030 error: 1031 nfs_free_server(server); 1032 dprintk("<-- nfs4_create_server() = error %d\n", error); 1033 return ERR_PTR(error); 1034 } 1035 1036 /* 1037 * Create an NFS4 referral server record 1038 */ 1039 struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, 1040 struct nfs_fh *fh) 1041 { 1042 struct nfs_client *parent_client; 1043 struct nfs_server *server, *parent_server; 1044 struct nfs_fattr fattr; 1045 int error; 1046 1047 dprintk("--> nfs4_create_referral_server()\n"); 1048 1049 server = nfs_alloc_server(); 1050 if (!server) 1051 return ERR_PTR(-ENOMEM); 1052 1053 parent_server = NFS_SB(data->sb); 1054 parent_client = parent_server->nfs_client; 1055 1056 /* Get a client representation. 1057 * Note: NFSv4 always uses TCP, */ 1058 error = nfs4_set_client(server, data->hostname, data->addr, 1059 data->authflavor, 1060 parent_server->client->cl_xprt->prot, 1061 parent_client->retrans_timeo, 1062 parent_client->retrans_count); 1063 if (error < 0) 1064 goto error; 1065 1066 /* Initialise the client representation from the parent server */ 1067 nfs_server_copy_userdata(server, parent_server); 1068 server->caps |= NFS_CAP_ATOMIC_OPEN; 1069 1070 error = nfs_init_server_rpcclient(server, data->authflavor); 1071 if (error < 0) 1072 goto error; 1073 1074 BUG_ON(!server->nfs_client); 1075 BUG_ON(!server->nfs_client->rpc_ops); 1076 BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); 1077 1078 /* probe the filesystem info for this server filesystem */ 1079 error = nfs_probe_fsinfo(server, fh, &fattr); 1080 if (error < 0) 1081 goto error; 1082 1083 dprintk("Referral FSID: %llx:%llx\n", 1084 (unsigned long long) server->fsid.major, 1085 (unsigned long long) server->fsid.minor); 1086 1087 spin_lock(&nfs_client_lock); 1088 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); 1089 list_add_tail(&server->master_link, &nfs_volume_list); 1090 spin_unlock(&nfs_client_lock); 1091 1092 server->mount_time = jiffies; 1093 1094 dprintk("<-- nfs_create_referral_server() = %p\n", server); 1095 return server; 1096 1097 error: 1098 nfs_free_server(server); 1099 dprintk("<-- nfs4_create_referral_server() = error %d\n", error); 1100 return ERR_PTR(error); 1101 } 1102 1103 #endif /* CONFIG_NFS_V4 */ 1104 1105 /* 1106 * Clone an NFS2, NFS3 or NFS4 server record 1107 */ 1108 struct nfs_server *nfs_clone_server(struct nfs_server *source, 1109 struct nfs_fh *fh, 1110 struct nfs_fattr *fattr) 1111 { 1112 struct nfs_server *server; 1113 struct nfs_fattr fattr_fsinfo; 1114 int error; 1115 1116 dprintk("--> nfs_clone_server(,%llx:%llx,)\n", 1117 (unsigned long long) fattr->fsid.major, 1118 (unsigned long long) fattr->fsid.minor); 1119 1120 server = nfs_alloc_server(); 1121 if (!server) 1122 return ERR_PTR(-ENOMEM); 1123 1124 /* Copy data from the source */ 1125 server->nfs_client = source->nfs_client; 1126 atomic_inc(&server->nfs_client->cl_count); 1127 nfs_server_copy_userdata(server, source); 1128 1129 server->fsid = fattr->fsid; 1130 1131 error = nfs_init_server_rpcclient(server, source->client->cl_auth->au_flavor); 1132 if (error < 0) 1133 goto out_free_server; 1134 if (!IS_ERR(source->client_acl)) 1135 nfs_init_server_aclclient(server); 1136 1137 /* probe the filesystem info for this server filesystem */ 1138 error = nfs_probe_fsinfo(server, fh, &fattr_fsinfo); 1139 if (error < 0) 1140 goto out_free_server; 1141 1142 dprintk("Cloned FSID: %llx:%llx\n", 1143 (unsigned long long) server->fsid.major, 1144 (unsigned long long) server->fsid.minor); 1145 1146 error = nfs_start_lockd(server); 1147 if (error < 0) 1148 goto out_free_server; 1149 1150 spin_lock(&nfs_client_lock); 1151 list_add_tail(&server->client_link, &server->nfs_client->cl_superblocks); 1152 list_add_tail(&server->master_link, &nfs_volume_list); 1153 spin_unlock(&nfs_client_lock); 1154 1155 server->mount_time = jiffies; 1156 1157 dprintk("<-- nfs_clone_server() = %p\n", server); 1158 return server; 1159 1160 out_free_server: 1161 nfs_free_server(server); 1162 dprintk("<-- nfs_clone_server() = error %d\n", error); 1163 return ERR_PTR(error); 1164 } 1165 1166 #ifdef CONFIG_PROC_FS 1167 static struct proc_dir_entry *proc_fs_nfs; 1168 1169 static int nfs_server_list_open(struct inode *inode, struct file *file); 1170 static void *nfs_server_list_start(struct seq_file *p, loff_t *pos); 1171 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos); 1172 static void nfs_server_list_stop(struct seq_file *p, void *v); 1173 static int nfs_server_list_show(struct seq_file *m, void *v); 1174 1175 static struct seq_operations nfs_server_list_ops = { 1176 .start = nfs_server_list_start, 1177 .next = nfs_server_list_next, 1178 .stop = nfs_server_list_stop, 1179 .show = nfs_server_list_show, 1180 }; 1181 1182 static struct file_operations nfs_server_list_fops = { 1183 .open = nfs_server_list_open, 1184 .read = seq_read, 1185 .llseek = seq_lseek, 1186 .release = seq_release, 1187 }; 1188 1189 static int nfs_volume_list_open(struct inode *inode, struct file *file); 1190 static void *nfs_volume_list_start(struct seq_file *p, loff_t *pos); 1191 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos); 1192 static void nfs_volume_list_stop(struct seq_file *p, void *v); 1193 static int nfs_volume_list_show(struct seq_file *m, void *v); 1194 1195 static struct seq_operations nfs_volume_list_ops = { 1196 .start = nfs_volume_list_start, 1197 .next = nfs_volume_list_next, 1198 .stop = nfs_volume_list_stop, 1199 .show = nfs_volume_list_show, 1200 }; 1201 1202 static struct file_operations nfs_volume_list_fops = { 1203 .open = nfs_volume_list_open, 1204 .read = seq_read, 1205 .llseek = seq_lseek, 1206 .release = seq_release, 1207 }; 1208 1209 /* 1210 * open "/proc/fs/nfsfs/servers" which provides a summary of servers with which 1211 * we're dealing 1212 */ 1213 static int nfs_server_list_open(struct inode *inode, struct file *file) 1214 { 1215 struct seq_file *m; 1216 int ret; 1217 1218 ret = seq_open(file, &nfs_server_list_ops); 1219 if (ret < 0) 1220 return ret; 1221 1222 m = file->private_data; 1223 m->private = PDE(inode)->data; 1224 1225 return 0; 1226 } 1227 1228 /* 1229 * set up the iterator to start reading from the server list and return the first item 1230 */ 1231 static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) 1232 { 1233 struct list_head *_p; 1234 loff_t pos = *_pos; 1235 1236 /* lock the list against modification */ 1237 spin_lock(&nfs_client_lock); 1238 1239 /* allow for the header line */ 1240 if (!pos) 1241 return SEQ_START_TOKEN; 1242 pos--; 1243 1244 /* find the n'th element in the list */ 1245 list_for_each(_p, &nfs_client_list) 1246 if (!pos--) 1247 break; 1248 1249 return _p != &nfs_client_list ? _p : NULL; 1250 } 1251 1252 /* 1253 * move to next server 1254 */ 1255 static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) 1256 { 1257 struct list_head *_p; 1258 1259 (*pos)++; 1260 1261 _p = v; 1262 _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next; 1263 1264 return _p != &nfs_client_list ? _p : NULL; 1265 } 1266 1267 /* 1268 * clean up after reading from the transports list 1269 */ 1270 static void nfs_server_list_stop(struct seq_file *p, void *v) 1271 { 1272 spin_unlock(&nfs_client_lock); 1273 } 1274 1275 /* 1276 * display a header line followed by a load of call lines 1277 */ 1278 static int nfs_server_list_show(struct seq_file *m, void *v) 1279 { 1280 struct nfs_client *clp; 1281 1282 /* display header on line 1 */ 1283 if (v == SEQ_START_TOKEN) { 1284 seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); 1285 return 0; 1286 } 1287 1288 /* display one transport per line on subsequent lines */ 1289 clp = list_entry(v, struct nfs_client, cl_share_link); 1290 1291 seq_printf(m, "v%d %02x%02x%02x%02x %4hx %3d %s\n", 1292 clp->cl_nfsversion, 1293 NIPQUAD(clp->cl_addr.sin_addr), 1294 ntohs(clp->cl_addr.sin_port), 1295 atomic_read(&clp->cl_count), 1296 clp->cl_hostname); 1297 1298 return 0; 1299 } 1300 1301 /* 1302 * open "/proc/fs/nfsfs/volumes" which provides a summary of extant volumes 1303 */ 1304 static int nfs_volume_list_open(struct inode *inode, struct file *file) 1305 { 1306 struct seq_file *m; 1307 int ret; 1308 1309 ret = seq_open(file, &nfs_volume_list_ops); 1310 if (ret < 0) 1311 return ret; 1312 1313 m = file->private_data; 1314 m->private = PDE(inode)->data; 1315 1316 return 0; 1317 } 1318 1319 /* 1320 * set up the iterator to start reading from the volume list and return the first item 1321 */ 1322 static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) 1323 { 1324 struct list_head *_p; 1325 loff_t pos = *_pos; 1326 1327 /* lock the list against modification */ 1328 spin_lock(&nfs_client_lock); 1329 1330 /* allow for the header line */ 1331 if (!pos) 1332 return SEQ_START_TOKEN; 1333 pos--; 1334 1335 /* find the n'th element in the list */ 1336 list_for_each(_p, &nfs_volume_list) 1337 if (!pos--) 1338 break; 1339 1340 return _p != &nfs_volume_list ? _p : NULL; 1341 } 1342 1343 /* 1344 * move to next volume 1345 */ 1346 static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) 1347 { 1348 struct list_head *_p; 1349 1350 (*pos)++; 1351 1352 _p = v; 1353 _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next; 1354 1355 return _p != &nfs_volume_list ? _p : NULL; 1356 } 1357 1358 /* 1359 * clean up after reading from the transports list 1360 */ 1361 static void nfs_volume_list_stop(struct seq_file *p, void *v) 1362 { 1363 spin_unlock(&nfs_client_lock); 1364 } 1365 1366 /* 1367 * display a header line followed by a load of call lines 1368 */ 1369 static int nfs_volume_list_show(struct seq_file *m, void *v) 1370 { 1371 struct nfs_server *server; 1372 struct nfs_client *clp; 1373 char dev[8], fsid[17]; 1374 1375 /* display header on line 1 */ 1376 if (v == SEQ_START_TOKEN) { 1377 seq_puts(m, "NV SERVER PORT DEV FSID\n"); 1378 return 0; 1379 } 1380 /* display one transport per line on subsequent lines */ 1381 server = list_entry(v, struct nfs_server, master_link); 1382 clp = server->nfs_client; 1383 1384 snprintf(dev, 8, "%u:%u", 1385 MAJOR(server->s_dev), MINOR(server->s_dev)); 1386 1387 snprintf(fsid, 17, "%llx:%llx", 1388 (unsigned long long) server->fsid.major, 1389 (unsigned long long) server->fsid.minor); 1390 1391 seq_printf(m, "v%d %02x%02x%02x%02x %4hx %-7s %-17s\n", 1392 clp->cl_nfsversion, 1393 NIPQUAD(clp->cl_addr.sin_addr), 1394 ntohs(clp->cl_addr.sin_port), 1395 dev, 1396 fsid); 1397 1398 return 0; 1399 } 1400 1401 /* 1402 * initialise the /proc/fs/nfsfs/ directory 1403 */ 1404 int __init nfs_fs_proc_init(void) 1405 { 1406 struct proc_dir_entry *p; 1407 1408 proc_fs_nfs = proc_mkdir("nfsfs", proc_root_fs); 1409 if (!proc_fs_nfs) 1410 goto error_0; 1411 1412 proc_fs_nfs->owner = THIS_MODULE; 1413 1414 /* a file of servers with which we're dealing */ 1415 p = create_proc_entry("servers", S_IFREG|S_IRUGO, proc_fs_nfs); 1416 if (!p) 1417 goto error_1; 1418 1419 p->proc_fops = &nfs_server_list_fops; 1420 p->owner = THIS_MODULE; 1421 1422 /* a file of volumes that we have mounted */ 1423 p = create_proc_entry("volumes", S_IFREG|S_IRUGO, proc_fs_nfs); 1424 if (!p) 1425 goto error_2; 1426 1427 p->proc_fops = &nfs_volume_list_fops; 1428 p->owner = THIS_MODULE; 1429 return 0; 1430 1431 error_2: 1432 remove_proc_entry("servers", proc_fs_nfs); 1433 error_1: 1434 remove_proc_entry("nfsfs", proc_root_fs); 1435 error_0: 1436 return -ENOMEM; 1437 } 1438 1439 /* 1440 * clean up the /proc/fs/nfsfs/ directory 1441 */ 1442 void nfs_fs_proc_exit(void) 1443 { 1444 remove_proc_entry("volumes", proc_fs_nfs); 1445 remove_proc_entry("servers", proc_fs_nfs); 1446 remove_proc_entry("nfsfs", proc_root_fs); 1447 } 1448 1449 #endif /* CONFIG_PROC_FS */ 1450