1 /* 2 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. 3 * Written by David Howells (dhowells@redhat.com) 4 */ 5 #include <linux/module.h> 6 #include <linux/nfs_fs.h> 7 #include <linux/nfs_idmap.h> 8 #include <linux/nfs_mount.h> 9 #include <linux/sunrpc/addr.h> 10 #include <linux/sunrpc/auth.h> 11 #include <linux/sunrpc/xprt.h> 12 #include <linux/sunrpc/bc_xprt.h> 13 #include "internal.h" 14 #include "callback.h" 15 #include "delegation.h" 16 #include "nfs4session.h" 17 #include "pnfs.h" 18 #include "netns.h" 19 20 #define NFSDBG_FACILITY NFSDBG_CLIENT 21 22 /* 23 * Get a unique NFSv4.0 callback identifier which will be used 24 * by the V4.0 callback service to lookup the nfs_client struct 25 */ 26 static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion) 27 { 28 int ret = 0; 29 struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id); 30 31 if (clp->rpc_ops->version != 4 || minorversion != 0) 32 return ret; 33 idr_preload(GFP_KERNEL); 34 spin_lock(&nn->nfs_client_lock); 35 ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT); 36 if (ret >= 0) 37 clp->cl_cb_ident = ret; 38 spin_unlock(&nn->nfs_client_lock); 39 idr_preload_end(); 40 return ret < 0 ? ret : 0; 41 } 42 43 #ifdef CONFIG_NFS_V4_1 44 /** 45 * Per auth flavor data server rpc clients 46 */ 47 struct nfs4_ds_server { 48 struct list_head list; /* ds_clp->cl_ds_clients */ 49 struct rpc_clnt *rpc_clnt; 50 }; 51 52 /** 53 * Common lookup case for DS I/O 54 */ 55 static struct nfs4_ds_server * 56 nfs4_find_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor) 57 { 58 struct nfs4_ds_server *dss; 59 60 rcu_read_lock(); 61 list_for_each_entry_rcu(dss, &ds_clp->cl_ds_clients, list) { 62 if (dss->rpc_clnt->cl_auth->au_flavor != flavor) 63 continue; 64 goto out; 65 } 66 dss = NULL; 67 out: 68 rcu_read_unlock(); 69 return dss; 70 } 71 72 static struct nfs4_ds_server * 73 nfs4_add_ds_client(struct nfs_client *ds_clp, rpc_authflavor_t flavor, 74 struct nfs4_ds_server *new) 75 { 76 struct nfs4_ds_server *dss; 77 78 spin_lock(&ds_clp->cl_lock); 79 list_for_each_entry(dss, &ds_clp->cl_ds_clients, list) { 80 if (dss->rpc_clnt->cl_auth->au_flavor != flavor) 81 continue; 82 goto out; 83 } 84 if (new) 85 list_add_rcu(&new->list, &ds_clp->cl_ds_clients); 86 dss = new; 87 out: 88 spin_unlock(&ds_clp->cl_lock); /* need some lock to protect list */ 89 return dss; 90 } 91 92 static struct nfs4_ds_server * 93 nfs4_alloc_ds_server(struct nfs_client *ds_clp, rpc_authflavor_t flavor) 94 { 95 struct nfs4_ds_server *dss; 96 97 dss = kmalloc(sizeof(*dss), GFP_NOFS); 98 if (dss == NULL) 99 return ERR_PTR(-ENOMEM); 100 101 dss->rpc_clnt = rpc_clone_client_set_auth(ds_clp->cl_rpcclient, flavor); 102 if (IS_ERR(dss->rpc_clnt)) { 103 int err = PTR_ERR(dss->rpc_clnt); 104 kfree (dss); 105 return ERR_PTR(err); 106 } 107 INIT_LIST_HEAD(&dss->list); 108 109 return dss; 110 } 111 112 static void 113 nfs4_free_ds_server(struct nfs4_ds_server *dss) 114 { 115 rpc_release_client(dss->rpc_clnt); 116 kfree(dss); 117 } 118 119 /** 120 * Find or create a DS rpc client with th MDS server rpc client auth flavor 121 * in the nfs_client cl_ds_clients list. 122 */ 123 struct rpc_clnt * 124 nfs4_find_or_create_ds_client(struct nfs_client *ds_clp, struct inode *inode) 125 { 126 struct nfs4_ds_server *dss, *new; 127 rpc_authflavor_t flavor = NFS_SERVER(inode)->client->cl_auth->au_flavor; 128 129 dss = nfs4_find_ds_client(ds_clp, flavor); 130 if (dss != NULL) 131 goto out; 132 new = nfs4_alloc_ds_server(ds_clp, flavor); 133 if (IS_ERR(new)) 134 return ERR_CAST(new); 135 dss = nfs4_add_ds_client(ds_clp, flavor, new); 136 if (dss != new) 137 nfs4_free_ds_server(new); 138 out: 139 return dss->rpc_clnt; 140 } 141 EXPORT_SYMBOL_GPL(nfs4_find_or_create_ds_client); 142 143 static void 144 nfs4_shutdown_ds_clients(struct nfs_client *clp) 145 { 146 struct nfs4_ds_server *dss; 147 LIST_HEAD(shutdown_list); 148 149 while (!list_empty(&clp->cl_ds_clients)) { 150 dss = list_entry(clp->cl_ds_clients.next, 151 struct nfs4_ds_server, list); 152 list_del(&dss->list); 153 rpc_shutdown_client(dss->rpc_clnt); 154 kfree (dss); 155 } 156 } 157 158 void nfs41_shutdown_client(struct nfs_client *clp) 159 { 160 if (nfs4_has_session(clp)) { 161 nfs4_shutdown_ds_clients(clp); 162 nfs4_destroy_session(clp->cl_session); 163 nfs4_destroy_clientid(clp); 164 } 165 166 } 167 #endif /* CONFIG_NFS_V4_1 */ 168 169 void nfs40_shutdown_client(struct nfs_client *clp) 170 { 171 if (clp->cl_slot_tbl) { 172 nfs4_release_slot_table(clp->cl_slot_tbl); 173 kfree(clp->cl_slot_tbl); 174 } 175 } 176 177 struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) 178 { 179 int err; 180 struct nfs_client *clp = nfs_alloc_client(cl_init); 181 if (IS_ERR(clp)) 182 return clp; 183 184 err = nfs_get_cb_ident_idr(clp, cl_init->minorversion); 185 if (err) 186 goto error; 187 188 if (cl_init->minorversion > NFS4_MAX_MINOR_VERSION) { 189 err = -EINVAL; 190 goto error; 191 } 192 193 spin_lock_init(&clp->cl_lock); 194 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); 195 INIT_LIST_HEAD(&clp->cl_ds_clients); 196 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); 197 clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; 198 clp->cl_minorversion = cl_init->minorversion; 199 clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; 200 return clp; 201 202 error: 203 nfs_free_client(clp); 204 return ERR_PTR(err); 205 } 206 207 /* 208 * Destroy the NFS4 callback service 209 */ 210 static void nfs4_destroy_callback(struct nfs_client *clp) 211 { 212 if (__test_and_clear_bit(NFS_CS_CALLBACK, &clp->cl_res_state)) 213 nfs_callback_down(clp->cl_mvops->minor_version, clp->cl_net); 214 } 215 216 static void nfs4_shutdown_client(struct nfs_client *clp) 217 { 218 if (__test_and_clear_bit(NFS_CS_RENEWD, &clp->cl_res_state)) 219 nfs4_kill_renewd(clp); 220 clp->cl_mvops->shutdown_client(clp); 221 nfs4_destroy_callback(clp); 222 if (__test_and_clear_bit(NFS_CS_IDMAP, &clp->cl_res_state)) 223 nfs_idmap_delete(clp); 224 225 rpc_destroy_wait_queue(&clp->cl_rpcwaitq); 226 kfree(clp->cl_serverowner); 227 kfree(clp->cl_serverscope); 228 kfree(clp->cl_implid); 229 } 230 231 void nfs4_free_client(struct nfs_client *clp) 232 { 233 nfs4_shutdown_client(clp); 234 nfs_free_client(clp); 235 } 236 237 /* 238 * Initialize the NFS4 callback service 239 */ 240 static int nfs4_init_callback(struct nfs_client *clp) 241 { 242 int error; 243 244 if (clp->rpc_ops->version == 4) { 245 struct rpc_xprt *xprt; 246 247 xprt = rcu_dereference_raw(clp->cl_rpcclient->cl_xprt); 248 249 if (nfs4_has_session(clp)) { 250 error = xprt_setup_backchannel(xprt, 251 NFS41_BC_MIN_CALLBACKS); 252 if (error < 0) 253 return error; 254 } 255 256 error = nfs_callback_up(clp->cl_mvops->minor_version, xprt); 257 if (error < 0) { 258 dprintk("%s: failed to start callback. Error = %d\n", 259 __func__, error); 260 return error; 261 } 262 __set_bit(NFS_CS_CALLBACK, &clp->cl_res_state); 263 } 264 return 0; 265 } 266 267 /** 268 * nfs40_init_client - nfs_client initialization tasks for NFSv4.0 269 * @clp - nfs_client to initialize 270 * 271 * Returns zero on success, or a negative errno if some error occurred. 272 */ 273 int nfs40_init_client(struct nfs_client *clp) 274 { 275 struct nfs4_slot_table *tbl; 276 int ret; 277 278 tbl = kzalloc(sizeof(*tbl), GFP_NOFS); 279 if (tbl == NULL) 280 return -ENOMEM; 281 282 ret = nfs4_setup_slot_table(tbl, NFS4_MAX_SLOT_TABLE, 283 "NFSv4.0 transport Slot table"); 284 if (ret) { 285 kfree(tbl); 286 return ret; 287 } 288 289 clp->cl_slot_tbl = tbl; 290 return 0; 291 } 292 293 #if defined(CONFIG_NFS_V4_1) 294 295 /** 296 * nfs41_init_client - nfs_client initialization tasks for NFSv4.1+ 297 * @clp - nfs_client to initialize 298 * 299 * Returns zero on success, or a negative errno if some error occurred. 300 */ 301 int nfs41_init_client(struct nfs_client *clp) 302 { 303 struct nfs4_session *session = NULL; 304 305 /* 306 * Create the session and mark it expired. 307 * When a SEQUENCE operation encounters the expired session 308 * it will do session recovery to initialize it. 309 */ 310 session = nfs4_alloc_session(clp); 311 if (!session) 312 return -ENOMEM; 313 314 clp->cl_session = session; 315 316 /* 317 * The create session reply races with the server back 318 * channel probe. Mark the client NFS_CS_SESSION_INITING 319 * so that the client back channel can find the 320 * nfs_client struct 321 */ 322 nfs_mark_client_ready(clp, NFS_CS_SESSION_INITING); 323 return 0; 324 } 325 326 #endif /* CONFIG_NFS_V4_1 */ 327 328 /* 329 * Initialize the minor version specific parts of an NFS4 client record 330 */ 331 static int nfs4_init_client_minor_version(struct nfs_client *clp) 332 { 333 int ret; 334 335 ret = clp->cl_mvops->init_client(clp); 336 if (ret) 337 return ret; 338 return nfs4_init_callback(clp); 339 } 340 341 /** 342 * nfs4_init_client - Initialise an NFS4 client record 343 * 344 * @clp: nfs_client to initialise 345 * @timeparms: timeout parameters for underlying RPC transport 346 * @ip_addr: callback IP address in presentation format 347 * @authflavor: authentication flavor for underlying RPC transport 348 * 349 * Returns pointer to an NFS client, or an ERR_PTR value. 350 */ 351 struct nfs_client *nfs4_init_client(struct nfs_client *clp, 352 const struct rpc_timeout *timeparms, 353 const char *ip_addr) 354 { 355 char buf[INET6_ADDRSTRLEN + 1]; 356 struct nfs_client *old; 357 int error; 358 359 if (clp->cl_cons_state == NFS_CS_READY) { 360 /* the client is initialised already */ 361 dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp); 362 return clp; 363 } 364 365 /* Check NFS protocol revision and initialize RPC op vector */ 366 clp->rpc_ops = &nfs_v4_clientops; 367 368 if (clp->cl_minorversion != 0) 369 __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags); 370 __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); 371 error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I); 372 if (error == -EINVAL) 373 error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX); 374 if (error < 0) 375 goto error; 376 377 /* If no clientaddr= option was specified, find a usable cb address */ 378 if (ip_addr == NULL) { 379 struct sockaddr_storage cb_addr; 380 struct sockaddr *sap = (struct sockaddr *)&cb_addr; 381 382 error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr)); 383 if (error < 0) 384 goto error; 385 error = rpc_ntop(sap, buf, sizeof(buf)); 386 if (error < 0) 387 goto error; 388 ip_addr = (const char *)buf; 389 } 390 strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); 391 392 error = nfs_idmap_new(clp); 393 if (error < 0) { 394 dprintk("%s: failed to create idmapper. Error = %d\n", 395 __func__, error); 396 goto error; 397 } 398 __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); 399 400 error = nfs4_init_client_minor_version(clp); 401 if (error < 0) 402 goto error; 403 404 if (!nfs4_has_session(clp)) 405 nfs_mark_client_ready(clp, NFS_CS_READY); 406 407 error = nfs4_discover_server_trunking(clp, &old); 408 if (error < 0) 409 goto error; 410 nfs_put_client(clp); 411 if (clp != old) { 412 clp->cl_preserve_clid = true; 413 clp = old; 414 } 415 416 return clp; 417 418 error: 419 nfs_mark_client_ready(clp, error); 420 nfs_put_client(clp); 421 dprintk("<-- nfs4_init_client() = xerror %d\n", error); 422 return ERR_PTR(error); 423 } 424 425 /* 426 * SETCLIENTID just did a callback update with the callback ident in 427 * "drop," but server trunking discovery claims "drop" and "keep" are 428 * actually the same server. Swap the callback IDs so that "keep" 429 * will continue to use the callback ident the server now knows about, 430 * and so that "keep"'s original callback ident is destroyed when 431 * "drop" is freed. 432 */ 433 static void nfs4_swap_callback_idents(struct nfs_client *keep, 434 struct nfs_client *drop) 435 { 436 struct nfs_net *nn = net_generic(keep->cl_net, nfs_net_id); 437 unsigned int save = keep->cl_cb_ident; 438 439 if (keep->cl_cb_ident == drop->cl_cb_ident) 440 return; 441 442 dprintk("%s: keeping callback ident %u and dropping ident %u\n", 443 __func__, keep->cl_cb_ident, drop->cl_cb_ident); 444 445 spin_lock(&nn->nfs_client_lock); 446 447 idr_replace(&nn->cb_ident_idr, keep, drop->cl_cb_ident); 448 keep->cl_cb_ident = drop->cl_cb_ident; 449 450 idr_replace(&nn->cb_ident_idr, drop, save); 451 drop->cl_cb_ident = save; 452 453 spin_unlock(&nn->nfs_client_lock); 454 } 455 456 /** 457 * nfs40_walk_client_list - Find server that recognizes a client ID 458 * 459 * @new: nfs_client with client ID to test 460 * @result: OUT: found nfs_client, or new 461 * @cred: credential to use for trunking test 462 * 463 * Returns zero, a negative errno, or a negative NFS4ERR status. 464 * If zero is returned, an nfs_client pointer is planted in "result." 465 * 466 * NB: nfs40_walk_client_list() relies on the new nfs_client being 467 * the last nfs_client on the list. 468 */ 469 int nfs40_walk_client_list(struct nfs_client *new, 470 struct nfs_client **result, 471 struct rpc_cred *cred) 472 { 473 struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); 474 struct nfs_client *pos, *prev = NULL; 475 struct nfs4_setclientid_res clid = { 476 .clientid = new->cl_clientid, 477 .confirm = new->cl_confirm, 478 }; 479 int status = -NFS4ERR_STALE_CLIENTID; 480 481 spin_lock(&nn->nfs_client_lock); 482 list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { 483 /* If "pos" isn't marked ready, we can't trust the 484 * remaining fields in "pos" */ 485 if (pos->cl_cons_state > NFS_CS_READY) { 486 atomic_inc(&pos->cl_count); 487 spin_unlock(&nn->nfs_client_lock); 488 489 if (prev) 490 nfs_put_client(prev); 491 prev = pos; 492 493 status = nfs_wait_client_init_complete(pos); 494 spin_lock(&nn->nfs_client_lock); 495 if (status < 0) 496 continue; 497 } 498 if (pos->cl_cons_state != NFS_CS_READY) 499 continue; 500 501 if (pos->rpc_ops != new->rpc_ops) 502 continue; 503 504 if (pos->cl_proto != new->cl_proto) 505 continue; 506 507 if (pos->cl_minorversion != new->cl_minorversion) 508 continue; 509 510 if (pos->cl_clientid != new->cl_clientid) 511 continue; 512 513 atomic_inc(&pos->cl_count); 514 spin_unlock(&nn->nfs_client_lock); 515 516 if (prev) 517 nfs_put_client(prev); 518 prev = pos; 519 520 status = nfs4_proc_setclientid_confirm(pos, &clid, cred); 521 switch (status) { 522 case -NFS4ERR_STALE_CLIENTID: 523 break; 524 case 0: 525 nfs4_swap_callback_idents(pos, new); 526 527 prev = NULL; 528 *result = pos; 529 dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", 530 __func__, pos, atomic_read(&pos->cl_count)); 531 default: 532 goto out; 533 } 534 535 spin_lock(&nn->nfs_client_lock); 536 } 537 spin_unlock(&nn->nfs_client_lock); 538 539 /* No match found. The server lost our clientid */ 540 out: 541 if (prev) 542 nfs_put_client(prev); 543 dprintk("NFS: <-- %s status = %d\n", __func__, status); 544 return status; 545 } 546 547 #ifdef CONFIG_NFS_V4_1 548 /* 549 * Returns true if the client IDs match 550 */ 551 static bool nfs4_match_clientids(struct nfs_client *a, struct nfs_client *b) 552 { 553 if (a->cl_clientid != b->cl_clientid) { 554 dprintk("NFS: --> %s client ID %llx does not match %llx\n", 555 __func__, a->cl_clientid, b->cl_clientid); 556 return false; 557 } 558 dprintk("NFS: --> %s client ID %llx matches %llx\n", 559 __func__, a->cl_clientid, b->cl_clientid); 560 return true; 561 } 562 563 /* 564 * Returns true if the server owners match 565 */ 566 static bool 567 nfs4_match_serverowners(struct nfs_client *a, struct nfs_client *b) 568 { 569 struct nfs41_server_owner *o1 = a->cl_serverowner; 570 struct nfs41_server_owner *o2 = b->cl_serverowner; 571 572 if (o1->minor_id != o2->minor_id) { 573 dprintk("NFS: --> %s server owner minor IDs do not match\n", 574 __func__); 575 return false; 576 } 577 578 if (o1->major_id_sz != o2->major_id_sz) 579 goto out_major_mismatch; 580 if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0) 581 goto out_major_mismatch; 582 583 dprintk("NFS: --> %s server owners match\n", __func__); 584 return true; 585 586 out_major_mismatch: 587 dprintk("NFS: --> %s server owner major IDs do not match\n", 588 __func__); 589 return false; 590 } 591 592 /** 593 * nfs41_walk_client_list - Find nfs_client that matches a client/server owner 594 * 595 * @new: nfs_client with client ID to test 596 * @result: OUT: found nfs_client, or new 597 * @cred: credential to use for trunking test 598 * 599 * Returns zero, a negative errno, or a negative NFS4ERR status. 600 * If zero is returned, an nfs_client pointer is planted in "result." 601 * 602 * NB: nfs41_walk_client_list() relies on the new nfs_client being 603 * the last nfs_client on the list. 604 */ 605 int nfs41_walk_client_list(struct nfs_client *new, 606 struct nfs_client **result, 607 struct rpc_cred *cred) 608 { 609 struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id); 610 struct nfs_client *pos, *prev = NULL; 611 int status = -NFS4ERR_STALE_CLIENTID; 612 613 spin_lock(&nn->nfs_client_lock); 614 list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) { 615 /* If "pos" isn't marked ready, we can't trust the 616 * remaining fields in "pos", especially the client 617 * ID and serverowner fields. Wait for CREATE_SESSION 618 * to finish. */ 619 if (pos->cl_cons_state > NFS_CS_READY) { 620 atomic_inc(&pos->cl_count); 621 spin_unlock(&nn->nfs_client_lock); 622 623 if (prev) 624 nfs_put_client(prev); 625 prev = pos; 626 627 status = nfs_wait_client_init_complete(pos); 628 if (status == 0) { 629 nfs4_schedule_lease_recovery(pos); 630 status = nfs4_wait_clnt_recover(pos); 631 } 632 spin_lock(&nn->nfs_client_lock); 633 if (status < 0) 634 continue; 635 } 636 if (pos->cl_cons_state != NFS_CS_READY) 637 continue; 638 639 if (pos->rpc_ops != new->rpc_ops) 640 continue; 641 642 if (pos->cl_proto != new->cl_proto) 643 continue; 644 645 if (pos->cl_minorversion != new->cl_minorversion) 646 continue; 647 648 if (!nfs4_match_clientids(pos, new)) 649 continue; 650 651 if (!nfs4_match_serverowners(pos, new)) 652 continue; 653 654 atomic_inc(&pos->cl_count); 655 *result = pos; 656 status = 0; 657 dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n", 658 __func__, pos, atomic_read(&pos->cl_count)); 659 break; 660 } 661 662 /* No matching nfs_client found. */ 663 spin_unlock(&nn->nfs_client_lock); 664 dprintk("NFS: <-- %s status = %d\n", __func__, status); 665 if (prev) 666 nfs_put_client(prev); 667 return status; 668 } 669 #endif /* CONFIG_NFS_V4_1 */ 670 671 static void nfs4_destroy_server(struct nfs_server *server) 672 { 673 nfs_server_return_all_delegations(server); 674 unset_pnfs_layoutdriver(server); 675 nfs4_purge_state_owners(server); 676 } 677 678 /* 679 * NFSv4.0 callback thread helper 680 * 681 * Find a client by callback identifier 682 */ 683 struct nfs_client * 684 nfs4_find_client_ident(struct net *net, int cb_ident) 685 { 686 struct nfs_client *clp; 687 struct nfs_net *nn = net_generic(net, nfs_net_id); 688 689 spin_lock(&nn->nfs_client_lock); 690 clp = idr_find(&nn->cb_ident_idr, cb_ident); 691 if (clp) 692 atomic_inc(&clp->cl_count); 693 spin_unlock(&nn->nfs_client_lock); 694 return clp; 695 } 696 697 #if defined(CONFIG_NFS_V4_1) 698 /* Common match routine for v4.0 and v4.1 callback services */ 699 static bool nfs4_cb_match_client(const struct sockaddr *addr, 700 struct nfs_client *clp, u32 minorversion) 701 { 702 struct sockaddr *clap = (struct sockaddr *)&clp->cl_addr; 703 704 /* Don't match clients that failed to initialise */ 705 if (!(clp->cl_cons_state == NFS_CS_READY || 706 clp->cl_cons_state == NFS_CS_SESSION_INITING)) 707 return false; 708 709 smp_rmb(); 710 711 /* Match the version and minorversion */ 712 if (clp->rpc_ops->version != 4 || 713 clp->cl_minorversion != minorversion) 714 return false; 715 716 /* Match only the IP address, not the port number */ 717 if (!nfs_sockaddr_match_ipaddr(addr, clap)) 718 return false; 719 720 return true; 721 } 722 723 /* 724 * NFSv4.1 callback thread helper 725 * For CB_COMPOUND calls, find a client by IP address, protocol version, 726 * minorversion, and sessionID 727 * 728 * Returns NULL if no such client 729 */ 730 struct nfs_client * 731 nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, 732 struct nfs4_sessionid *sid, u32 minorversion) 733 { 734 struct nfs_client *clp; 735 struct nfs_net *nn = net_generic(net, nfs_net_id); 736 737 spin_lock(&nn->nfs_client_lock); 738 list_for_each_entry(clp, &nn->nfs_client_list, cl_share_link) { 739 if (nfs4_cb_match_client(addr, clp, minorversion) == false) 740 continue; 741 742 if (!nfs4_has_session(clp)) 743 continue; 744 745 /* Match sessionid*/ 746 if (memcmp(clp->cl_session->sess_id.data, 747 sid->data, NFS4_MAX_SESSIONID_LEN) != 0) 748 continue; 749 750 atomic_inc(&clp->cl_count); 751 spin_unlock(&nn->nfs_client_lock); 752 return clp; 753 } 754 spin_unlock(&nn->nfs_client_lock); 755 return NULL; 756 } 757 758 #else /* CONFIG_NFS_V4_1 */ 759 760 struct nfs_client * 761 nfs4_find_client_sessionid(struct net *net, const struct sockaddr *addr, 762 struct nfs4_sessionid *sid, u32 minorversion) 763 { 764 return NULL; 765 } 766 #endif /* CONFIG_NFS_V4_1 */ 767 768 /* 769 * Set up an NFS4 client 770 */ 771 static int nfs4_set_client(struct nfs_server *server, 772 const char *hostname, 773 const struct sockaddr *addr, 774 const size_t addrlen, 775 const char *ip_addr, 776 rpc_authflavor_t authflavour, 777 int proto, const struct rpc_timeout *timeparms, 778 u32 minorversion, struct net *net) 779 { 780 struct nfs_client_initdata cl_init = { 781 .hostname = hostname, 782 .addr = addr, 783 .addrlen = addrlen, 784 .nfs_mod = &nfs_v4, 785 .proto = proto, 786 .minorversion = minorversion, 787 .net = net, 788 }; 789 struct nfs_client *clp; 790 int error; 791 792 dprintk("--> nfs4_set_client()\n"); 793 794 if (server->flags & NFS_MOUNT_NORESVPORT) 795 set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); 796 if (server->options & NFS_OPTION_MIGRATION) 797 set_bit(NFS_CS_MIGRATION, &cl_init.init_flags); 798 799 /* Allocate or find a client reference we can use */ 800 clp = nfs_get_client(&cl_init, timeparms, ip_addr, authflavour); 801 if (IS_ERR(clp)) { 802 error = PTR_ERR(clp); 803 goto error; 804 } 805 806 /* 807 * Query for the lease time on clientid setup or renewal 808 * 809 * Note that this will be set on nfs_clients that were created 810 * only for the DS role and did not set this bit, but now will 811 * serve a dual role. 812 */ 813 set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state); 814 815 server->nfs_client = clp; 816 dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp); 817 return 0; 818 error: 819 dprintk("<-- nfs4_set_client() = xerror %d\n", error); 820 return error; 821 } 822 823 /* 824 * Set up a pNFS Data Server client. 825 * 826 * Return any existing nfs_client that matches server address,port,version 827 * and minorversion. 828 * 829 * For a new nfs_client, use a soft mount (default), a low retrans and a 830 * low timeout interval so that if a connection is lost, we retry through 831 * the MDS. 832 */ 833 struct nfs_client *nfs4_set_ds_client(struct nfs_client* mds_clp, 834 const struct sockaddr *ds_addr, int ds_addrlen, 835 int ds_proto, unsigned int ds_timeo, unsigned int ds_retrans) 836 { 837 struct nfs_client_initdata cl_init = { 838 .addr = ds_addr, 839 .addrlen = ds_addrlen, 840 .nfs_mod = &nfs_v4, 841 .proto = ds_proto, 842 .minorversion = mds_clp->cl_minorversion, 843 .net = mds_clp->cl_net, 844 }; 845 struct rpc_timeout ds_timeout; 846 struct nfs_client *clp; 847 848 /* 849 * Set an authflavor equual to the MDS value. Use the MDS nfs_client 850 * cl_ipaddr so as to use the same EXCHANGE_ID co_ownerid as the MDS 851 * (section 13.1 RFC 5661). 852 */ 853 nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans); 854 clp = nfs_get_client(&cl_init, &ds_timeout, mds_clp->cl_ipaddr, 855 mds_clp->cl_rpcclient->cl_auth->au_flavor); 856 857 dprintk("<-- %s %p\n", __func__, clp); 858 return clp; 859 } 860 EXPORT_SYMBOL_GPL(nfs4_set_ds_client); 861 862 /* 863 * Session has been established, and the client marked ready. 864 * Set the mount rsize and wsize with negotiated fore channel 865 * attributes which will be bound checked in nfs_server_set_fsinfo. 866 */ 867 static void nfs4_session_set_rwsize(struct nfs_server *server) 868 { 869 #ifdef CONFIG_NFS_V4_1 870 struct nfs4_session *sess; 871 u32 server_resp_sz; 872 u32 server_rqst_sz; 873 874 if (!nfs4_has_session(server->nfs_client)) 875 return; 876 sess = server->nfs_client->cl_session; 877 server_resp_sz = sess->fc_attrs.max_resp_sz - nfs41_maxread_overhead; 878 server_rqst_sz = sess->fc_attrs.max_rqst_sz - nfs41_maxwrite_overhead; 879 880 if (server->rsize > server_resp_sz) 881 server->rsize = server_resp_sz; 882 if (server->wsize > server_rqst_sz) 883 server->wsize = server_rqst_sz; 884 #endif /* CONFIG_NFS_V4_1 */ 885 } 886 887 static int nfs4_server_common_setup(struct nfs_server *server, 888 struct nfs_fh *mntfh, bool auth_probe) 889 { 890 struct nfs_fattr *fattr; 891 int error; 892 893 /* data servers support only a subset of NFSv4.1 */ 894 if (is_ds_only_client(server->nfs_client)) 895 return -EPROTONOSUPPORT; 896 897 fattr = nfs_alloc_fattr(); 898 if (fattr == NULL) 899 return -ENOMEM; 900 901 /* We must ensure the session is initialised first */ 902 error = nfs4_init_session(server->nfs_client); 903 if (error < 0) 904 goto out; 905 906 /* Set the basic capabilities */ 907 server->caps |= server->nfs_client->cl_mvops->init_caps; 908 if (server->flags & NFS_MOUNT_NORDIRPLUS) 909 server->caps &= ~NFS_CAP_READDIRPLUS; 910 /* 911 * Don't use NFS uid/gid mapping if we're using AUTH_SYS or lower 912 * authentication. 913 */ 914 if (nfs4_disable_idmapping && 915 server->client->cl_auth->au_flavor == RPC_AUTH_UNIX) 916 server->caps |= NFS_CAP_UIDGID_NOMAP; 917 918 919 /* Probe the root fh to retrieve its FSID and filehandle */ 920 error = nfs4_get_rootfh(server, mntfh, auth_probe); 921 if (error < 0) 922 goto out; 923 924 dprintk("Server FSID: %llx:%llx\n", 925 (unsigned long long) server->fsid.major, 926 (unsigned long long) server->fsid.minor); 927 dprintk("Mount FH: %d\n", mntfh->size); 928 929 nfs4_session_set_rwsize(server); 930 931 error = nfs_probe_fsinfo(server, mntfh, fattr); 932 if (error < 0) 933 goto out; 934 935 if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN) 936 server->namelen = NFS4_MAXNAMLEN; 937 938 nfs_server_insert_lists(server); 939 server->mount_time = jiffies; 940 server->destroy = nfs4_destroy_server; 941 out: 942 nfs_free_fattr(fattr); 943 return error; 944 } 945 946 /* 947 * Create a version 4 volume record 948 */ 949 static int nfs4_init_server(struct nfs_server *server, 950 const struct nfs_parsed_mount_data *data) 951 { 952 rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX; 953 struct rpc_timeout timeparms; 954 int error; 955 956 dprintk("--> nfs4_init_server()\n"); 957 958 nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, 959 data->timeo, data->retrans); 960 961 /* Initialise the client representation from the mount data */ 962 server->flags = data->flags; 963 server->options = data->options; 964 965 if (data->auth_flavor_len >= 1) 966 pseudoflavor = data->auth_flavors[0]; 967 968 /* Get a client record */ 969 error = nfs4_set_client(server, 970 data->nfs_server.hostname, 971 (const struct sockaddr *)&data->nfs_server.address, 972 data->nfs_server.addrlen, 973 data->client_address, 974 pseudoflavor, 975 data->nfs_server.protocol, 976 &timeparms, 977 data->minorversion, 978 data->net); 979 if (error < 0) 980 goto error; 981 982 if (data->rsize) 983 server->rsize = nfs_block_size(data->rsize, NULL); 984 if (data->wsize) 985 server->wsize = nfs_block_size(data->wsize, NULL); 986 987 server->acregmin = data->acregmin * HZ; 988 server->acregmax = data->acregmax * HZ; 989 server->acdirmin = data->acdirmin * HZ; 990 server->acdirmax = data->acdirmax * HZ; 991 992 server->port = data->nfs_server.port; 993 994 error = nfs_init_server_rpcclient(server, &timeparms, pseudoflavor); 995 996 error: 997 /* Done */ 998 dprintk("<-- nfs4_init_server() = %d\n", error); 999 return error; 1000 } 1001 1002 /* 1003 * Create a version 4 volume record 1004 * - keyed on server and FSID 1005 */ 1006 /*struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, 1007 struct nfs_fh *mntfh)*/ 1008 struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info, 1009 struct nfs_subversion *nfs_mod) 1010 { 1011 struct nfs_server *server; 1012 bool auth_probe; 1013 int error; 1014 1015 dprintk("--> nfs4_create_server()\n"); 1016 1017 server = nfs_alloc_server(); 1018 if (!server) 1019 return ERR_PTR(-ENOMEM); 1020 1021 auth_probe = mount_info->parsed->auth_flavor_len < 1; 1022 1023 /* set up the general RPC client */ 1024 error = nfs4_init_server(server, mount_info->parsed); 1025 if (error < 0) 1026 goto error; 1027 1028 error = nfs4_server_common_setup(server, mount_info->mntfh, auth_probe); 1029 if (error < 0) 1030 goto error; 1031 1032 dprintk("<-- nfs4_create_server() = %p\n", server); 1033 return server; 1034 1035 error: 1036 nfs_free_server(server); 1037 dprintk("<-- nfs4_create_server() = error %d\n", error); 1038 return ERR_PTR(error); 1039 } 1040 1041 /* 1042 * Create an NFS4 referral server record 1043 */ 1044 struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, 1045 struct nfs_fh *mntfh) 1046 { 1047 struct nfs_client *parent_client; 1048 struct nfs_server *server, *parent_server; 1049 int error; 1050 1051 dprintk("--> nfs4_create_referral_server()\n"); 1052 1053 server = nfs_alloc_server(); 1054 if (!server) 1055 return ERR_PTR(-ENOMEM); 1056 1057 parent_server = NFS_SB(data->sb); 1058 parent_client = parent_server->nfs_client; 1059 1060 /* Initialise the client representation from the parent server */ 1061 nfs_server_copy_userdata(server, parent_server); 1062 1063 /* Get a client representation. 1064 * Note: NFSv4 always uses TCP, */ 1065 error = nfs4_set_client(server, data->hostname, 1066 data->addr, 1067 data->addrlen, 1068 parent_client->cl_ipaddr, 1069 data->authflavor, 1070 rpc_protocol(parent_server->client), 1071 parent_server->client->cl_timeout, 1072 parent_client->cl_mvops->minor_version, 1073 parent_client->cl_net); 1074 if (error < 0) 1075 goto error; 1076 1077 error = nfs_init_server_rpcclient(server, parent_server->client->cl_timeout, data->authflavor); 1078 if (error < 0) 1079 goto error; 1080 1081 error = nfs4_server_common_setup(server, mntfh, 1082 !(parent_server->flags & NFS_MOUNT_SECFLAVOUR)); 1083 if (error < 0) 1084 goto error; 1085 1086 dprintk("<-- nfs_create_referral_server() = %p\n", server); 1087 return server; 1088 1089 error: 1090 nfs_free_server(server); 1091 dprintk("<-- nfs4_create_referral_server() = error %d\n", error); 1092 return ERR_PTR(error); 1093 } 1094