.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* client.c: NFS client sharing and management code |
---|
2 | 3 | * |
---|
3 | 4 | * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved. |
---|
4 | 5 | * 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 | 6 | */ |
---|
11 | 7 | |
---|
12 | 8 | |
---|
.. | .. |
---|
53 | 49 | #include "pnfs.h" |
---|
54 | 50 | #include "nfs.h" |
---|
55 | 51 | #include "netns.h" |
---|
| 52 | +#include "sysfs.h" |
---|
| 53 | +#include "nfs42.h" |
---|
56 | 54 | |
---|
57 | 55 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
---|
58 | 56 | |
---|
.. | .. |
---|
151 | 149 | struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init) |
---|
152 | 150 | { |
---|
153 | 151 | struct nfs_client *clp; |
---|
154 | | - struct rpc_cred *cred; |
---|
155 | 152 | int err = -ENOMEM; |
---|
156 | 153 | |
---|
157 | 154 | if ((clp = kzalloc(sizeof(*clp), GFP_KERNEL)) == NULL) |
---|
.. | .. |
---|
182 | 179 | |
---|
183 | 180 | clp->cl_flags = cl_init->init_flags; |
---|
184 | 181 | clp->cl_proto = cl_init->proto; |
---|
| 182 | + clp->cl_nconnect = cl_init->nconnect; |
---|
185 | 183 | clp->cl_net = get_net(cl_init->net); |
---|
186 | 184 | |
---|
187 | | - cred = rpc_lookup_machine_cred("*"); |
---|
188 | | - if (!IS_ERR(cred)) |
---|
189 | | - clp->cl_machine_cred = cred; |
---|
| 185 | + clp->cl_principal = "*"; |
---|
190 | 186 | nfs_fscache_get_client_cookie(clp); |
---|
191 | 187 | |
---|
192 | 188 | return clp; |
---|
.. | .. |
---|
201 | 197 | EXPORT_SYMBOL_GPL(nfs_alloc_client); |
---|
202 | 198 | |
---|
203 | 199 | #if IS_ENABLED(CONFIG_NFS_V4) |
---|
204 | | -void nfs_cleanup_cb_ident_idr(struct net *net) |
---|
| 200 | +static void nfs_cleanup_cb_ident_idr(struct net *net) |
---|
205 | 201 | { |
---|
206 | 202 | struct nfs_net *nn = net_generic(net, nfs_net_id); |
---|
207 | 203 | |
---|
.. | .. |
---|
223 | 219 | } |
---|
224 | 220 | |
---|
225 | 221 | #else |
---|
226 | | -void nfs_cleanup_cb_ident_idr(struct net *net) |
---|
| 222 | +static void nfs_cleanup_cb_ident_idr(struct net *net) |
---|
227 | 223 | { |
---|
228 | 224 | } |
---|
229 | 225 | |
---|
.. | .. |
---|
247 | 243 | /* -EIO all pending I/O */ |
---|
248 | 244 | if (!IS_ERR(clp->cl_rpcclient)) |
---|
249 | 245 | rpc_shutdown_client(clp->cl_rpcclient); |
---|
250 | | - |
---|
251 | | - if (clp->cl_machine_cred != NULL) |
---|
252 | | - put_rpccred(clp->cl_machine_cred); |
---|
253 | 246 | |
---|
254 | 247 | put_net(clp->cl_net); |
---|
255 | 248 | put_nfs_version(clp->cl_nfs_mod); |
---|
.. | .. |
---|
322 | 315 | /* Match nfsv4 minorversion */ |
---|
323 | 316 | if (clp->cl_minorversion != data->minorversion) |
---|
324 | 317 | continue; |
---|
| 318 | + |
---|
| 319 | + /* Match request for a dedicated DS */ |
---|
| 320 | + if (test_bit(NFS_CS_DS, &data->init_flags) != |
---|
| 321 | + test_bit(NFS_CS_DS, &clp->cl_flags)) |
---|
| 322 | + continue; |
---|
| 323 | + |
---|
325 | 324 | /* Match the full socket address */ |
---|
326 | 325 | if (!rpc_cmp_addr_port(sap, clap)) |
---|
327 | 326 | /* Match all xprt_switch full socket addresses */ |
---|
.. | .. |
---|
477 | 476 | to->to_maxval = to->to_initval; |
---|
478 | 477 | to->to_exponential = 0; |
---|
479 | 478 | break; |
---|
| 479 | +#ifndef CONFIG_NFS_DISABLE_UDP_SUPPORT |
---|
480 | 480 | case XPRT_TRANSPORT_UDP: |
---|
481 | 481 | if (retrans == NFS_UNSPEC_RETRANS) |
---|
482 | 482 | to->to_retries = NFS_DEF_UDP_RETRANS; |
---|
.. | .. |
---|
487 | 487 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; |
---|
488 | 488 | to->to_exponential = 1; |
---|
489 | 489 | break; |
---|
| 490 | +#endif |
---|
490 | 491 | default: |
---|
491 | 492 | BUG(); |
---|
492 | 493 | } |
---|
.. | .. |
---|
504 | 505 | struct rpc_create_args args = { |
---|
505 | 506 | .net = clp->cl_net, |
---|
506 | 507 | .protocol = clp->cl_proto, |
---|
| 508 | + .nconnect = clp->cl_nconnect, |
---|
507 | 509 | .address = (struct sockaddr *)&clp->cl_addr, |
---|
508 | 510 | .addrsize = clp->cl_addrlen, |
---|
509 | 511 | .timeout = cl_init->timeparms, |
---|
.. | .. |
---|
512 | 514 | .program = &nfs_program, |
---|
513 | 515 | .version = clp->rpc_ops->version, |
---|
514 | 516 | .authflavor = flavor, |
---|
| 517 | + .cred = cl_init->cred, |
---|
515 | 518 | }; |
---|
516 | 519 | |
---|
517 | 520 | if (test_bit(NFS_CS_DISCRTRY, &clp->cl_flags)) |
---|
.. | .. |
---|
522 | 525 | args.flags |= RPC_CLNT_CREATE_NONPRIVPORT; |
---|
523 | 526 | if (test_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags)) |
---|
524 | 527 | args.flags |= RPC_CLNT_CREATE_INFINITE_SLOTS; |
---|
| 528 | + if (test_bit(NFS_CS_NOPING, &clp->cl_flags)) |
---|
| 529 | + args.flags |= RPC_CLNT_CREATE_NOPING; |
---|
| 530 | + if (test_bit(NFS_CS_REUSEPORT, &clp->cl_flags)) |
---|
| 531 | + args.flags |= RPC_CLNT_CREATE_REUSEPORT; |
---|
525 | 532 | |
---|
526 | 533 | if (!IS_ERR(clp->cl_rpcclient)) |
---|
527 | 534 | return 0; |
---|
.. | .. |
---|
533 | 540 | return PTR_ERR(clnt); |
---|
534 | 541 | } |
---|
535 | 542 | |
---|
| 543 | + clnt->cl_principal = clp->cl_principal; |
---|
536 | 544 | clp->cl_rpcclient = clnt; |
---|
537 | 545 | return 0; |
---|
538 | 546 | } |
---|
.. | .. |
---|
563 | 571 | 1 : 0, |
---|
564 | 572 | .net = clp->cl_net, |
---|
565 | 573 | .nlmclnt_ops = clp->cl_nfs_mod->rpc_ops->nlmclnt_ops, |
---|
| 574 | + .cred = current_cred(), |
---|
566 | 575 | }; |
---|
567 | 576 | |
---|
568 | 577 | if (nlm_init.nfs_version > 3) |
---|
.. | .. |
---|
575 | 584 | default: |
---|
576 | 585 | nlm_init.protocol = IPPROTO_TCP; |
---|
577 | 586 | break; |
---|
| 587 | +#ifndef CONFIG_NFS_DISABLE_UDP_SUPPORT |
---|
578 | 588 | case XPRT_TRANSPORT_UDP: |
---|
579 | 589 | nlm_init.protocol = IPPROTO_UDP; |
---|
| 590 | +#endif |
---|
580 | 591 | } |
---|
581 | 592 | |
---|
582 | 593 | host = nlmclnt_init(&nlm_init); |
---|
.. | .. |
---|
609 | 620 | sizeof(server->client->cl_timeout_default)); |
---|
610 | 621 | server->client->cl_timeout = &server->client->cl_timeout_default; |
---|
611 | 622 | server->client->cl_softrtry = 0; |
---|
| 623 | + if (server->flags & NFS_MOUNT_SOFTERR) |
---|
| 624 | + server->client->cl_softerr = 1; |
---|
612 | 625 | if (server->flags & NFS_MOUNT_SOFT) |
---|
613 | 626 | server->client->cl_softrtry = 1; |
---|
614 | 627 | |
---|
.. | .. |
---|
651 | 664 | * Create a version 2 or 3 client |
---|
652 | 665 | */ |
---|
653 | 666 | static int nfs_init_server(struct nfs_server *server, |
---|
654 | | - const struct nfs_parsed_mount_data *data, |
---|
655 | | - struct nfs_subversion *nfs_mod) |
---|
| 667 | + const struct fs_context *fc) |
---|
656 | 668 | { |
---|
| 669 | + const struct nfs_fs_context *ctx = nfs_fc2context(fc); |
---|
657 | 670 | struct rpc_timeout timeparms; |
---|
658 | 671 | struct nfs_client_initdata cl_init = { |
---|
659 | | - .hostname = data->nfs_server.hostname, |
---|
660 | | - .addr = (const struct sockaddr *)&data->nfs_server.address, |
---|
661 | | - .addrlen = data->nfs_server.addrlen, |
---|
662 | | - .nfs_mod = nfs_mod, |
---|
663 | | - .proto = data->nfs_server.protocol, |
---|
664 | | - .net = data->net, |
---|
| 672 | + .hostname = ctx->nfs_server.hostname, |
---|
| 673 | + .addr = (const struct sockaddr *)&ctx->nfs_server.address, |
---|
| 674 | + .addrlen = ctx->nfs_server.addrlen, |
---|
| 675 | + .nfs_mod = ctx->nfs_mod, |
---|
| 676 | + .proto = ctx->nfs_server.protocol, |
---|
| 677 | + .net = fc->net_ns, |
---|
665 | 678 | .timeparms = &timeparms, |
---|
| 679 | + .cred = server->cred, |
---|
| 680 | + .nconnect = ctx->nfs_server.nconnect, |
---|
| 681 | + .init_flags = (1UL << NFS_CS_REUSEPORT), |
---|
666 | 682 | }; |
---|
667 | 683 | struct nfs_client *clp; |
---|
668 | 684 | int error; |
---|
669 | 685 | |
---|
670 | | - nfs_init_timeout_values(&timeparms, data->nfs_server.protocol, |
---|
671 | | - data->timeo, data->retrans); |
---|
672 | | - if (data->flags & NFS_MOUNT_NORESVPORT) |
---|
| 686 | + nfs_init_timeout_values(&timeparms, ctx->nfs_server.protocol, |
---|
| 687 | + ctx->timeo, ctx->retrans); |
---|
| 688 | + if (ctx->flags & NFS_MOUNT_NORESVPORT) |
---|
673 | 689 | set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags); |
---|
674 | 690 | |
---|
675 | 691 | /* Allocate or find a client reference we can use */ |
---|
.. | .. |
---|
680 | 696 | server->nfs_client = clp; |
---|
681 | 697 | |
---|
682 | 698 | /* Initialise the client representation from the mount data */ |
---|
683 | | - server->flags = data->flags; |
---|
684 | | - server->options = data->options; |
---|
| 699 | + server->flags = ctx->flags; |
---|
| 700 | + server->options = ctx->options; |
---|
685 | 701 | server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID| |
---|
686 | 702 | NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP| |
---|
687 | 703 | NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME; |
---|
688 | 704 | |
---|
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); |
---|
| 705 | + if (ctx->rsize) |
---|
| 706 | + server->rsize = nfs_block_size(ctx->rsize, NULL); |
---|
| 707 | + if (ctx->wsize) |
---|
| 708 | + server->wsize = nfs_block_size(ctx->wsize, NULL); |
---|
693 | 709 | |
---|
694 | | - server->acregmin = data->acregmin * HZ; |
---|
695 | | - server->acregmax = data->acregmax * HZ; |
---|
696 | | - server->acdirmin = data->acdirmin * HZ; |
---|
697 | | - server->acdirmax = data->acdirmax * HZ; |
---|
| 710 | + server->acregmin = ctx->acregmin * HZ; |
---|
| 711 | + server->acregmax = ctx->acregmax * HZ; |
---|
| 712 | + server->acdirmin = ctx->acdirmin * HZ; |
---|
| 713 | + server->acdirmax = ctx->acdirmax * HZ; |
---|
698 | 714 | |
---|
699 | 715 | /* Start lockd here, before we might error out */ |
---|
700 | 716 | error = nfs_start_lockd(server); |
---|
701 | 717 | if (error < 0) |
---|
702 | 718 | goto error; |
---|
703 | 719 | |
---|
704 | | - server->port = data->nfs_server.port; |
---|
705 | | - server->auth_info = data->auth_info; |
---|
| 720 | + server->port = ctx->nfs_server.port; |
---|
| 721 | + server->auth_info = ctx->auth_info; |
---|
706 | 722 | |
---|
707 | 723 | error = nfs_init_server_rpcclient(server, &timeparms, |
---|
708 | | - data->selected_flavor); |
---|
| 724 | + ctx->selected_flavor); |
---|
709 | 725 | if (error < 0) |
---|
710 | 726 | goto error; |
---|
711 | 727 | |
---|
712 | 728 | /* 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; |
---|
| 729 | + if (ctx->mount_server.addrlen) { |
---|
| 730 | + memcpy(&server->mountd_address, &ctx->mount_server.address, |
---|
| 731 | + ctx->mount_server.addrlen); |
---|
| 732 | + server->mountd_addrlen = ctx->mount_server.addrlen; |
---|
717 | 733 | } |
---|
718 | | - server->mountd_version = data->mount_server.version; |
---|
719 | | - server->mountd_port = data->mount_server.port; |
---|
720 | | - server->mountd_protocol = data->mount_server.protocol; |
---|
| 734 | + server->mountd_version = ctx->mount_server.version; |
---|
| 735 | + server->mountd_port = ctx->mount_server.port; |
---|
| 736 | + server->mountd_protocol = ctx->mount_server.protocol; |
---|
721 | 737 | |
---|
722 | | - server->namelen = data->namlen; |
---|
| 738 | + server->namelen = ctx->namlen; |
---|
723 | 739 | return 0; |
---|
724 | 740 | |
---|
725 | 741 | error: |
---|
.. | .. |
---|
734 | 750 | static void nfs_server_set_fsinfo(struct nfs_server *server, |
---|
735 | 751 | struct nfs_fsinfo *fsinfo) |
---|
736 | 752 | { |
---|
737 | | - unsigned long max_rpc_payload; |
---|
| 753 | + unsigned long max_rpc_payload, raw_max_rpc_payload; |
---|
738 | 754 | |
---|
739 | 755 | /* Work out a lot of parameters */ |
---|
740 | 756 | if (server->rsize == 0) |
---|
.. | .. |
---|
747 | 763 | if (fsinfo->wtmax >= 512 && server->wsize > fsinfo->wtmax) |
---|
748 | 764 | server->wsize = nfs_block_size(fsinfo->wtmax, NULL); |
---|
749 | 765 | |
---|
750 | | - max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); |
---|
| 766 | + raw_max_rpc_payload = rpc_max_payload(server->client); |
---|
| 767 | + max_rpc_payload = nfs_block_size(raw_max_rpc_payload, NULL); |
---|
| 768 | + |
---|
751 | 769 | if (server->rsize > max_rpc_payload) |
---|
752 | 770 | server->rsize = max_rpc_payload; |
---|
753 | 771 | if (server->rsize > NFS_MAX_FILE_IO_SIZE) |
---|
.. | .. |
---|
780 | 798 | server->clone_blksize = fsinfo->clone_blksize; |
---|
781 | 799 | /* We're airborne Set socket buffersize */ |
---|
782 | 800 | rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); |
---|
| 801 | + |
---|
| 802 | +#ifdef CONFIG_NFS_V4_2 |
---|
| 803 | + /* |
---|
| 804 | + * Defaults until limited by the session parameters. |
---|
| 805 | + */ |
---|
| 806 | + server->gxasize = min_t(unsigned int, raw_max_rpc_payload, |
---|
| 807 | + XATTR_SIZE_MAX); |
---|
| 808 | + server->sxasize = min_t(unsigned int, raw_max_rpc_payload, |
---|
| 809 | + XATTR_SIZE_MAX); |
---|
| 810 | + server->lxasize = min_t(unsigned int, raw_max_rpc_payload, |
---|
| 811 | + nfs42_listxattr_xdrsize(XATTR_LIST_MAX)); |
---|
| 812 | + |
---|
| 813 | + if (fsinfo->xattr_support) |
---|
| 814 | + server->caps |= NFS_CAP_XATTR; |
---|
| 815 | +#endif |
---|
783 | 816 | } |
---|
784 | 817 | |
---|
785 | 818 | /* |
---|
.. | .. |
---|
931 | 964 | ida_destroy(&server->lockowner_id); |
---|
932 | 965 | ida_destroy(&server->openowner_id); |
---|
933 | 966 | nfs_free_iostats(server->io_stats); |
---|
| 967 | + put_cred(server->cred); |
---|
934 | 968 | kfree(server); |
---|
935 | 969 | nfs_release_automount_timer(); |
---|
936 | 970 | } |
---|
.. | .. |
---|
940 | 974 | * Create a version 2 or 3 volume record |
---|
941 | 975 | * - keyed on server and FSID |
---|
942 | 976 | */ |
---|
943 | | -struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info, |
---|
944 | | - struct nfs_subversion *nfs_mod) |
---|
| 977 | +struct nfs_server *nfs_create_server(struct fs_context *fc) |
---|
945 | 978 | { |
---|
| 979 | + struct nfs_fs_context *ctx = nfs_fc2context(fc); |
---|
946 | 980 | struct nfs_server *server; |
---|
947 | 981 | struct nfs_fattr *fattr; |
---|
948 | 982 | int error; |
---|
.. | .. |
---|
951 | 985 | if (!server) |
---|
952 | 986 | return ERR_PTR(-ENOMEM); |
---|
953 | 987 | |
---|
| 988 | + server->cred = get_cred(current_cred()); |
---|
| 989 | + |
---|
954 | 990 | error = -ENOMEM; |
---|
955 | 991 | fattr = nfs_alloc_fattr(); |
---|
956 | 992 | if (fattr == NULL) |
---|
957 | 993 | goto error; |
---|
958 | 994 | |
---|
959 | 995 | /* Get a client representation */ |
---|
960 | | - error = nfs_init_server(server, mount_info->parsed, nfs_mod); |
---|
| 996 | + error = nfs_init_server(server, fc); |
---|
961 | 997 | if (error < 0) |
---|
962 | 998 | goto error; |
---|
963 | 999 | |
---|
964 | 1000 | /* Probe the root fh to retrieve its FSID */ |
---|
965 | | - error = nfs_probe_fsinfo(server, mount_info->mntfh, fattr); |
---|
| 1001 | + error = nfs_probe_fsinfo(server, ctx->mntfh, fattr); |
---|
966 | 1002 | if (error < 0) |
---|
967 | 1003 | goto error; |
---|
968 | 1004 | if (server->nfs_client->rpc_ops->version == 3) { |
---|
969 | 1005 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) |
---|
970 | 1006 | server->namelen = NFS3_MAXNAMLEN; |
---|
971 | | - if (!(mount_info->parsed->flags & NFS_MOUNT_NORDIRPLUS)) |
---|
| 1007 | + if (!(ctx->flags & NFS_MOUNT_NORDIRPLUS)) |
---|
972 | 1008 | server->caps |= NFS_CAP_READDIRPLUS; |
---|
973 | 1009 | } else { |
---|
974 | 1010 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) |
---|
.. | .. |
---|
976 | 1012 | } |
---|
977 | 1013 | |
---|
978 | 1014 | if (!(fattr->valid & NFS_ATTR_FATTR)) { |
---|
979 | | - error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, |
---|
980 | | - fattr, NULL, NULL); |
---|
| 1015 | + error = ctx->nfs_mod->rpc_ops->getattr(server, ctx->mntfh, |
---|
| 1016 | + fattr, NULL, NULL); |
---|
981 | 1017 | if (error < 0) { |
---|
982 | 1018 | dprintk("nfs_create_server: getattr error = %d\n", -error); |
---|
983 | 1019 | goto error; |
---|
.. | .. |
---|
1016 | 1052 | server = nfs_alloc_server(); |
---|
1017 | 1053 | if (!server) |
---|
1018 | 1054 | return ERR_PTR(-ENOMEM); |
---|
| 1055 | + |
---|
| 1056 | + server->cred = get_cred(source->cred); |
---|
1019 | 1057 | |
---|
1020 | 1058 | error = -ENOMEM; |
---|
1021 | 1059 | fattr_fsinfo = nfs_alloc_fattr(); |
---|
.. | .. |
---|
1072 | 1110 | #endif |
---|
1073 | 1111 | spin_lock_init(&nn->nfs_client_lock); |
---|
1074 | 1112 | nn->boot_time = ktime_get_real(); |
---|
| 1113 | + |
---|
| 1114 | + nfs_netns_sysfs_setup(nn, net); |
---|
| 1115 | +} |
---|
| 1116 | + |
---|
| 1117 | +void nfs_clients_exit(struct net *net) |
---|
| 1118 | +{ |
---|
| 1119 | + struct nfs_net *nn = net_generic(net, nfs_net_id); |
---|
| 1120 | + |
---|
| 1121 | + nfs_netns_sysfs_destroy(nn); |
---|
| 1122 | + nfs_cleanup_cb_ident_idr(net); |
---|
| 1123 | + WARN_ON_ONCE(!list_empty(&nn->nfs_client_list)); |
---|
| 1124 | + WARN_ON_ONCE(!list_empty(&nn->nfs_volume_list)); |
---|
1075 | 1125 | } |
---|
1076 | 1126 | |
---|
1077 | 1127 | #ifdef CONFIG_PROC_FS |
---|