diff options
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 393 |
1 files changed, 172 insertions, 221 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b878528b64c1..fa517ae9207f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/sunrpc/clnt.h> | 33 | #include <linux/sunrpc/clnt.h> |
34 | #include <linux/sunrpc/stats.h> | 34 | #include <linux/sunrpc/stats.h> |
35 | #include <linux/sunrpc/metrics.h> | 35 | #include <linux/sunrpc/metrics.h> |
36 | #include <linux/sunrpc/xprtsock.h> | ||
37 | #include <linux/sunrpc/xprtrdma.h> | ||
36 | #include <linux/nfs_fs.h> | 38 | #include <linux/nfs_fs.h> |
37 | #include <linux/nfs_mount.h> | 39 | #include <linux/nfs_mount.h> |
38 | #include <linux/nfs4_mount.h> | 40 | #include <linux/nfs4_mount.h> |
@@ -58,36 +60,6 @@ | |||
58 | 60 | ||
59 | #define NFSDBG_FACILITY NFSDBG_VFS | 61 | #define NFSDBG_FACILITY NFSDBG_VFS |
60 | 62 | ||
61 | |||
62 | struct nfs_parsed_mount_data { | ||
63 | int flags; | ||
64 | int rsize, wsize; | ||
65 | int timeo, retrans; | ||
66 | int acregmin, acregmax, | ||
67 | acdirmin, acdirmax; | ||
68 | int namlen; | ||
69 | unsigned int bsize; | ||
70 | unsigned int auth_flavor_len; | ||
71 | rpc_authflavor_t auth_flavors[1]; | ||
72 | char *client_address; | ||
73 | |||
74 | struct { | ||
75 | struct sockaddr_in address; | ||
76 | unsigned int program; | ||
77 | unsigned int version; | ||
78 | unsigned short port; | ||
79 | int protocol; | ||
80 | } mount_server; | ||
81 | |||
82 | struct { | ||
83 | struct sockaddr_in address; | ||
84 | char *hostname; | ||
85 | char *export_path; | ||
86 | unsigned int program; | ||
87 | int protocol; | ||
88 | } nfs_server; | ||
89 | }; | ||
90 | |||
91 | enum { | 63 | enum { |
92 | /* Mount options that take no arguments */ | 64 | /* Mount options that take no arguments */ |
93 | Opt_soft, Opt_hard, | 65 | Opt_soft, Opt_hard, |
@@ -97,7 +69,7 @@ enum { | |||
97 | Opt_ac, Opt_noac, | 69 | Opt_ac, Opt_noac, |
98 | Opt_lock, Opt_nolock, | 70 | Opt_lock, Opt_nolock, |
99 | Opt_v2, Opt_v3, | 71 | Opt_v2, Opt_v3, |
100 | Opt_udp, Opt_tcp, | 72 | Opt_udp, Opt_tcp, Opt_rdma, |
101 | Opt_acl, Opt_noacl, | 73 | Opt_acl, Opt_noacl, |
102 | Opt_rdirplus, Opt_nordirplus, | 74 | Opt_rdirplus, Opt_nordirplus, |
103 | Opt_sharecache, Opt_nosharecache, | 75 | Opt_sharecache, Opt_nosharecache, |
@@ -116,7 +88,7 @@ enum { | |||
116 | 88 | ||
117 | /* Mount options that take string arguments */ | 89 | /* Mount options that take string arguments */ |
118 | Opt_sec, Opt_proto, Opt_mountproto, | 90 | Opt_sec, Opt_proto, Opt_mountproto, |
119 | Opt_addr, Opt_mounthost, Opt_clientaddr, | 91 | Opt_addr, Opt_mountaddr, Opt_clientaddr, |
120 | 92 | ||
121 | /* Mount options that are ignored */ | 93 | /* Mount options that are ignored */ |
122 | Opt_userspace, Opt_deprecated, | 94 | Opt_userspace, Opt_deprecated, |
@@ -143,6 +115,7 @@ static match_table_t nfs_mount_option_tokens = { | |||
143 | { Opt_v3, "v3" }, | 115 | { Opt_v3, "v3" }, |
144 | { Opt_udp, "udp" }, | 116 | { Opt_udp, "udp" }, |
145 | { Opt_tcp, "tcp" }, | 117 | { Opt_tcp, "tcp" }, |
118 | { Opt_rdma, "rdma" }, | ||
146 | { Opt_acl, "acl" }, | 119 | { Opt_acl, "acl" }, |
147 | { Opt_noacl, "noacl" }, | 120 | { Opt_noacl, "noacl" }, |
148 | { Opt_rdirplus, "rdirplus" }, | 121 | { Opt_rdirplus, "rdirplus" }, |
@@ -175,13 +148,14 @@ static match_table_t nfs_mount_option_tokens = { | |||
175 | { Opt_mountproto, "mountproto=%s" }, | 148 | { Opt_mountproto, "mountproto=%s" }, |
176 | { Opt_addr, "addr=%s" }, | 149 | { Opt_addr, "addr=%s" }, |
177 | { Opt_clientaddr, "clientaddr=%s" }, | 150 | { Opt_clientaddr, "clientaddr=%s" }, |
178 | { Opt_mounthost, "mounthost=%s" }, | 151 | { Opt_userspace, "mounthost=%s" }, |
152 | { Opt_mountaddr, "mountaddr=%s" }, | ||
179 | 153 | ||
180 | { Opt_err, NULL } | 154 | { Opt_err, NULL } |
181 | }; | 155 | }; |
182 | 156 | ||
183 | enum { | 157 | enum { |
184 | Opt_xprt_udp, Opt_xprt_tcp, | 158 | Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma, |
185 | 159 | ||
186 | Opt_xprt_err | 160 | Opt_xprt_err |
187 | }; | 161 | }; |
@@ -189,6 +163,7 @@ enum { | |||
189 | static match_table_t nfs_xprt_protocol_tokens = { | 163 | static match_table_t nfs_xprt_protocol_tokens = { |
190 | { Opt_xprt_udp, "udp" }, | 164 | { Opt_xprt_udp, "udp" }, |
191 | { Opt_xprt_tcp, "tcp" }, | 165 | { Opt_xprt_tcp, "tcp" }, |
166 | { Opt_xprt_rdma, "rdma" }, | ||
192 | 167 | ||
193 | { Opt_xprt_err, NULL } | 168 | { Opt_xprt_err, NULL } |
194 | }; | 169 | }; |
@@ -449,7 +424,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
449 | const char *nostr; | 424 | const char *nostr; |
450 | } nfs_info[] = { | 425 | } nfs_info[] = { |
451 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, | 426 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
452 | { NFS_MOUNT_INTR, ",intr", "" }, | 427 | { NFS_MOUNT_INTR, ",intr", ",nointr" }, |
453 | { NFS_MOUNT_NOCTO, ",nocto", "" }, | 428 | { NFS_MOUNT_NOCTO, ",nocto", "" }, |
454 | { NFS_MOUNT_NOAC, ",noac", "" }, | 429 | { NFS_MOUNT_NOAC, ",noac", "" }, |
455 | { NFS_MOUNT_NONLM, ",nolock", "" }, | 430 | { NFS_MOUNT_NONLM, ",nolock", "" }, |
@@ -460,8 +435,6 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
460 | }; | 435 | }; |
461 | const struct proc_nfs_info *nfs_infop; | 436 | const struct proc_nfs_info *nfs_infop; |
462 | struct nfs_client *clp = nfss->nfs_client; | 437 | struct nfs_client *clp = nfss->nfs_client; |
463 | char buf[12]; | ||
464 | const char *proto; | ||
465 | 438 | ||
466 | seq_printf(m, ",vers=%d", clp->rpc_ops->version); | 439 | seq_printf(m, ",vers=%d", clp->rpc_ops->version); |
467 | seq_printf(m, ",rsize=%d", nfss->rsize); | 440 | seq_printf(m, ",rsize=%d", nfss->rsize); |
@@ -480,18 +453,8 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
480 | else | 453 | else |
481 | seq_puts(m, nfs_infop->nostr); | 454 | seq_puts(m, nfs_infop->nostr); |
482 | } | 455 | } |
483 | switch (nfss->client->cl_xprt->prot) { | 456 | seq_printf(m, ",proto=%s", |
484 | case IPPROTO_TCP: | 457 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); |
485 | proto = "tcp"; | ||
486 | break; | ||
487 | case IPPROTO_UDP: | ||
488 | proto = "udp"; | ||
489 | break; | ||
490 | default: | ||
491 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); | ||
492 | proto = buf; | ||
493 | } | ||
494 | seq_printf(m, ",proto=%s", proto); | ||
495 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); | 458 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); |
496 | seq_printf(m, ",retrans=%u", clp->retrans_count); | 459 | seq_printf(m, ",retrans=%u", clp->retrans_count); |
497 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); | 460 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); |
@@ -506,8 +469,8 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
506 | 469 | ||
507 | nfs_show_mount_options(m, nfss, 0); | 470 | nfs_show_mount_options(m, nfss, 0); |
508 | 471 | ||
509 | seq_puts(m, ",addr="); | 472 | seq_printf(m, ",addr="NIPQUAD_FMT, |
510 | seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\"); | 473 | NIPQUAD(nfss->nfs_client->cl_addr.sin_addr)); |
511 | 474 | ||
512 | return 0; | 475 | return 0; |
513 | } | 476 | } |
@@ -698,13 +661,19 @@ static int nfs_parse_mount_options(char *raw, | |||
698 | break; | 661 | break; |
699 | case Opt_udp: | 662 | case Opt_udp: |
700 | mnt->flags &= ~NFS_MOUNT_TCP; | 663 | mnt->flags &= ~NFS_MOUNT_TCP; |
701 | mnt->nfs_server.protocol = IPPROTO_UDP; | 664 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
702 | mnt->timeo = 7; | 665 | mnt->timeo = 7; |
703 | mnt->retrans = 5; | 666 | mnt->retrans = 5; |
704 | break; | 667 | break; |
705 | case Opt_tcp: | 668 | case Opt_tcp: |
706 | mnt->flags |= NFS_MOUNT_TCP; | 669 | mnt->flags |= NFS_MOUNT_TCP; |
707 | mnt->nfs_server.protocol = IPPROTO_TCP; | 670 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
671 | mnt->timeo = 600; | ||
672 | mnt->retrans = 2; | ||
673 | break; | ||
674 | case Opt_rdma: | ||
675 | mnt->flags |= NFS_MOUNT_TCP; /* for side protocols */ | ||
676 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | ||
708 | mnt->timeo = 600; | 677 | mnt->timeo = 600; |
709 | mnt->retrans = 2; | 678 | mnt->retrans = 2; |
710 | break; | 679 | break; |
@@ -913,13 +882,20 @@ static int nfs_parse_mount_options(char *raw, | |||
913 | switch (token) { | 882 | switch (token) { |
914 | case Opt_xprt_udp: | 883 | case Opt_xprt_udp: |
915 | mnt->flags &= ~NFS_MOUNT_TCP; | 884 | mnt->flags &= ~NFS_MOUNT_TCP; |
916 | mnt->nfs_server.protocol = IPPROTO_UDP; | 885 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
917 | mnt->timeo = 7; | 886 | mnt->timeo = 7; |
918 | mnt->retrans = 5; | 887 | mnt->retrans = 5; |
919 | break; | 888 | break; |
920 | case Opt_xprt_tcp: | 889 | case Opt_xprt_tcp: |
921 | mnt->flags |= NFS_MOUNT_TCP; | 890 | mnt->flags |= NFS_MOUNT_TCP; |
922 | mnt->nfs_server.protocol = IPPROTO_TCP; | 891 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
892 | mnt->timeo = 600; | ||
893 | mnt->retrans = 2; | ||
894 | break; | ||
895 | case Opt_xprt_rdma: | ||
896 | /* vector side protocols to TCP */ | ||
897 | mnt->flags |= NFS_MOUNT_TCP; | ||
898 | mnt->nfs_server.protocol = XPRT_TRANSPORT_RDMA; | ||
923 | mnt->timeo = 600; | 899 | mnt->timeo = 600; |
924 | mnt->retrans = 2; | 900 | mnt->retrans = 2; |
925 | break; | 901 | break; |
@@ -937,11 +913,12 @@ static int nfs_parse_mount_options(char *raw, | |||
937 | 913 | ||
938 | switch (token) { | 914 | switch (token) { |
939 | case Opt_xprt_udp: | 915 | case Opt_xprt_udp: |
940 | mnt->mount_server.protocol = IPPROTO_UDP; | 916 | mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; |
941 | break; | 917 | break; |
942 | case Opt_xprt_tcp: | 918 | case Opt_xprt_tcp: |
943 | mnt->mount_server.protocol = IPPROTO_TCP; | 919 | mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; |
944 | break; | 920 | break; |
921 | case Opt_xprt_rdma: /* not used for side protocols */ | ||
945 | default: | 922 | default: |
946 | goto out_unrec_xprt; | 923 | goto out_unrec_xprt; |
947 | } | 924 | } |
@@ -961,7 +938,7 @@ static int nfs_parse_mount_options(char *raw, | |||
961 | goto out_nomem; | 938 | goto out_nomem; |
962 | mnt->client_address = string; | 939 | mnt->client_address = string; |
963 | break; | 940 | break; |
964 | case Opt_mounthost: | 941 | case Opt_mountaddr: |
965 | string = match_strdup(args); | 942 | string = match_strdup(args); |
966 | if (string == NULL) | 943 | if (string == NULL) |
967 | goto out_nomem; | 944 | goto out_nomem; |
@@ -1027,16 +1004,10 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1027 | sin = args->mount_server.address; | 1004 | sin = args->mount_server.address; |
1028 | else | 1005 | else |
1029 | sin = args->nfs_server.address; | 1006 | sin = args->nfs_server.address; |
1030 | if (args->mount_server.port == 0) { | 1007 | /* |
1031 | status = rpcb_getport_sync(&sin, | 1008 | * autobind will be used if mount_server.port == 0 |
1032 | args->mount_server.program, | 1009 | */ |
1033 | args->mount_server.version, | 1010 | sin.sin_port = htons(args->mount_server.port); |
1034 | args->mount_server.protocol); | ||
1035 | if (status < 0) | ||
1036 | goto out_err; | ||
1037 | sin.sin_port = htons(status); | ||
1038 | } else | ||
1039 | sin.sin_port = htons(args->mount_server.port); | ||
1040 | 1011 | ||
1041 | /* | 1012 | /* |
1042 | * Now ask the mount server to map our export path | 1013 | * Now ask the mount server to map our export path |
@@ -1049,14 +1020,11 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args, | |||
1049 | args->mount_server.version, | 1020 | args->mount_server.version, |
1050 | args->mount_server.protocol, | 1021 | args->mount_server.protocol, |
1051 | root_fh); | 1022 | root_fh); |
1052 | if (status < 0) | 1023 | if (status == 0) |
1053 | goto out_err; | 1024 | return 0; |
1054 | |||
1055 | return status; | ||
1056 | 1025 | ||
1057 | out_err: | 1026 | dfprintk(MOUNT, "NFS: unable to mount server " NIPQUAD_FMT |
1058 | dfprintk(MOUNT, "NFS: unable to contact server on host " | 1027 | ", error %d\n", NIPQUAD(sin.sin_addr.s_addr), status); |
1059 | NIPQUAD_FMT "\n", NIPQUAD(sin.sin_addr.s_addr)); | ||
1060 | return status; | 1028 | return status; |
1061 | } | 1029 | } |
1062 | 1030 | ||
@@ -1079,15 +1047,31 @@ out_err: | |||
1079 | * XXX: as far as I can tell, changing the NFS program number is not | 1047 | * XXX: as far as I can tell, changing the NFS program number is not |
1080 | * supported in the NFS client. | 1048 | * supported in the NFS client. |
1081 | */ | 1049 | */ |
1082 | static int nfs_validate_mount_data(struct nfs_mount_data **options, | 1050 | static int nfs_validate_mount_data(void *options, |
1051 | struct nfs_parsed_mount_data *args, | ||
1083 | struct nfs_fh *mntfh, | 1052 | struct nfs_fh *mntfh, |
1084 | const char *dev_name) | 1053 | const char *dev_name) |
1085 | { | 1054 | { |
1086 | struct nfs_mount_data *data = *options; | 1055 | struct nfs_mount_data *data = (struct nfs_mount_data *)options; |
1087 | 1056 | ||
1088 | if (data == NULL) | 1057 | if (data == NULL) |
1089 | goto out_no_data; | 1058 | goto out_no_data; |
1090 | 1059 | ||
1060 | memset(args, 0, sizeof(*args)); | ||
1061 | args->flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP); | ||
1062 | args->rsize = NFS_MAX_FILE_IO_SIZE; | ||
1063 | args->wsize = NFS_MAX_FILE_IO_SIZE; | ||
1064 | args->timeo = 600; | ||
1065 | args->retrans = 2; | ||
1066 | args->acregmin = 3; | ||
1067 | args->acregmax = 60; | ||
1068 | args->acdirmin = 30; | ||
1069 | args->acdirmax = 60; | ||
1070 | args->mount_server.protocol = XPRT_TRANSPORT_UDP; | ||
1071 | args->mount_server.program = NFS_MNT_PROGRAM; | ||
1072 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; | ||
1073 | args->nfs_server.program = NFS_PROGRAM; | ||
1074 | |||
1091 | switch (data->version) { | 1075 | switch (data->version) { |
1092 | case 1: | 1076 | case 1: |
1093 | data->namlen = 0; | 1077 | data->namlen = 0; |
@@ -1116,92 +1100,73 @@ static int nfs_validate_mount_data(struct nfs_mount_data **options, | |||
1116 | if (mntfh->size < sizeof(mntfh->data)) | 1100 | if (mntfh->size < sizeof(mntfh->data)) |
1117 | memset(mntfh->data + mntfh->size, 0, | 1101 | memset(mntfh->data + mntfh->size, 0, |
1118 | sizeof(mntfh->data) - mntfh->size); | 1102 | sizeof(mntfh->data) - mntfh->size); |
1103 | |||
1104 | if (!nfs_verify_server_address((struct sockaddr *) &data->addr)) | ||
1105 | goto out_no_address; | ||
1106 | |||
1107 | /* | ||
1108 | * Translate to nfs_parsed_mount_data, which nfs_fill_super | ||
1109 | * can deal with. | ||
1110 | */ | ||
1111 | args->flags = data->flags; | ||
1112 | args->rsize = data->rsize; | ||
1113 | args->wsize = data->wsize; | ||
1114 | args->flags = data->flags; | ||
1115 | args->timeo = data->timeo; | ||
1116 | args->retrans = data->retrans; | ||
1117 | args->acregmin = data->acregmin; | ||
1118 | args->acregmax = data->acregmax; | ||
1119 | args->acdirmin = data->acdirmin; | ||
1120 | args->acdirmax = data->acdirmax; | ||
1121 | args->nfs_server.address = data->addr; | ||
1122 | if (!(data->flags & NFS_MOUNT_TCP)) | ||
1123 | args->nfs_server.protocol = XPRT_TRANSPORT_UDP; | ||
1124 | /* N.B. caller will free nfs_server.hostname in all cases */ | ||
1125 | args->nfs_server.hostname = kstrdup(data->hostname, GFP_KERNEL); | ||
1126 | args->namlen = data->namlen; | ||
1127 | args->bsize = data->bsize; | ||
1128 | args->auth_flavors[0] = data->pseudoflavor; | ||
1119 | break; | 1129 | break; |
1120 | default: { | 1130 | default: { |
1121 | unsigned int len; | 1131 | unsigned int len; |
1122 | char *c; | 1132 | char *c; |
1123 | int status; | 1133 | int status; |
1124 | struct nfs_parsed_mount_data args = { | ||
1125 | .flags = (NFS_MOUNT_VER3 | NFS_MOUNT_TCP), | ||
1126 | .rsize = NFS_MAX_FILE_IO_SIZE, | ||
1127 | .wsize = NFS_MAX_FILE_IO_SIZE, | ||
1128 | .timeo = 600, | ||
1129 | .retrans = 2, | ||
1130 | .acregmin = 3, | ||
1131 | .acregmax = 60, | ||
1132 | .acdirmin = 30, | ||
1133 | .acdirmax = 60, | ||
1134 | .mount_server.protocol = IPPROTO_UDP, | ||
1135 | .mount_server.program = NFS_MNT_PROGRAM, | ||
1136 | .nfs_server.protocol = IPPROTO_TCP, | ||
1137 | .nfs_server.program = NFS_PROGRAM, | ||
1138 | }; | ||
1139 | |||
1140 | if (nfs_parse_mount_options((char *) *options, &args) == 0) | ||
1141 | return -EINVAL; | ||
1142 | 1134 | ||
1143 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 1135 | if (nfs_parse_mount_options((char *)options, args) == 0) |
1144 | if (data == NULL) | 1136 | return -EINVAL; |
1145 | return -ENOMEM; | ||
1146 | 1137 | ||
1147 | /* | 1138 | if (!nfs_verify_server_address((struct sockaddr *) |
1148 | * NB: after this point, caller will free "data" | 1139 | &args->nfs_server.address)) |
1149 | * if we return an error | 1140 | goto out_no_address; |
1150 | */ | ||
1151 | *options = data; | ||
1152 | 1141 | ||
1153 | c = strchr(dev_name, ':'); | 1142 | c = strchr(dev_name, ':'); |
1154 | if (c == NULL) | 1143 | if (c == NULL) |
1155 | return -EINVAL; | 1144 | return -EINVAL; |
1156 | len = c - dev_name; | 1145 | len = c - dev_name; |
1157 | if (len > sizeof(data->hostname)) | 1146 | /* N.B. caller will free nfs_server.hostname in all cases */ |
1158 | return -ENAMETOOLONG; | 1147 | args->nfs_server.hostname = kstrndup(dev_name, len, GFP_KERNEL); |
1159 | strncpy(data->hostname, dev_name, len); | ||
1160 | args.nfs_server.hostname = data->hostname; | ||
1161 | 1148 | ||
1162 | c++; | 1149 | c++; |
1163 | if (strlen(c) > NFS_MAXPATHLEN) | 1150 | if (strlen(c) > NFS_MAXPATHLEN) |
1164 | return -ENAMETOOLONG; | 1151 | return -ENAMETOOLONG; |
1165 | args.nfs_server.export_path = c; | 1152 | args->nfs_server.export_path = c; |
1166 | 1153 | ||
1167 | status = nfs_try_mount(&args, mntfh); | 1154 | status = nfs_try_mount(args, mntfh); |
1168 | if (status) | 1155 | if (status) |
1169 | return status; | 1156 | return status; |
1170 | 1157 | ||
1171 | /* | ||
1172 | * Translate to nfs_mount_data, which nfs_fill_super | ||
1173 | * can deal with. | ||
1174 | */ | ||
1175 | data->version = 6; | ||
1176 | data->flags = args.flags; | ||
1177 | data->rsize = args.rsize; | ||
1178 | data->wsize = args.wsize; | ||
1179 | data->timeo = args.timeo; | ||
1180 | data->retrans = args.retrans; | ||
1181 | data->acregmin = args.acregmin; | ||
1182 | data->acregmax = args.acregmax; | ||
1183 | data->acdirmin = args.acdirmin; | ||
1184 | data->acdirmax = args.acdirmax; | ||
1185 | data->addr = args.nfs_server.address; | ||
1186 | data->namlen = args.namlen; | ||
1187 | data->bsize = args.bsize; | ||
1188 | data->pseudoflavor = args.auth_flavors[0]; | ||
1189 | |||
1190 | break; | 1158 | break; |
1191 | } | 1159 | } |
1192 | } | 1160 | } |
1193 | 1161 | ||
1194 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | 1162 | if (!(args->flags & NFS_MOUNT_SECFLAVOUR)) |
1195 | data->pseudoflavor = RPC_AUTH_UNIX; | 1163 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
1196 | 1164 | ||
1197 | #ifndef CONFIG_NFS_V3 | 1165 | #ifndef CONFIG_NFS_V3 |
1198 | if (data->flags & NFS_MOUNT_VER3) | 1166 | if (args->flags & NFS_MOUNT_VER3) |
1199 | goto out_v3_not_compiled; | 1167 | goto out_v3_not_compiled; |
1200 | #endif /* !CONFIG_NFS_V3 */ | 1168 | #endif /* !CONFIG_NFS_V3 */ |
1201 | 1169 | ||
1202 | if (!nfs_verify_server_address((struct sockaddr *) &data->addr)) | ||
1203 | goto out_no_address; | ||
1204 | |||
1205 | return 0; | 1170 | return 0; |
1206 | 1171 | ||
1207 | out_no_data: | 1172 | out_no_data: |
@@ -1258,7 +1223,8 @@ static inline void nfs_initialise_sb(struct super_block *sb) | |||
1258 | /* | 1223 | /* |
1259 | * Finish setting up an NFS2/3 superblock | 1224 | * Finish setting up an NFS2/3 superblock |
1260 | */ | 1225 | */ |
1261 | static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) | 1226 | static void nfs_fill_super(struct super_block *sb, |
1227 | struct nfs_parsed_mount_data *data) | ||
1262 | { | 1228 | { |
1263 | struct nfs_server *server = NFS_SB(sb); | 1229 | struct nfs_server *server = NFS_SB(sb); |
1264 | 1230 | ||
@@ -1379,7 +1345,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1379 | struct nfs_server *server = NULL; | 1345 | struct nfs_server *server = NULL; |
1380 | struct super_block *s; | 1346 | struct super_block *s; |
1381 | struct nfs_fh mntfh; | 1347 | struct nfs_fh mntfh; |
1382 | struct nfs_mount_data *data = raw_data; | 1348 | struct nfs_parsed_mount_data data; |
1383 | struct dentry *mntroot; | 1349 | struct dentry *mntroot; |
1384 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 1350 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
1385 | struct nfs_sb_mountdata sb_mntdata = { | 1351 | struct nfs_sb_mountdata sb_mntdata = { |
@@ -1388,12 +1354,12 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1388 | int error; | 1354 | int error; |
1389 | 1355 | ||
1390 | /* Validate the mount data */ | 1356 | /* Validate the mount data */ |
1391 | error = nfs_validate_mount_data(&data, &mntfh, dev_name); | 1357 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); |
1392 | if (error < 0) | 1358 | if (error < 0) |
1393 | goto out; | 1359 | goto out; |
1394 | 1360 | ||
1395 | /* Get a volume representation */ | 1361 | /* Get a volume representation */ |
1396 | server = nfs_create_server(data, &mntfh); | 1362 | server = nfs_create_server(&data, &mntfh); |
1397 | if (IS_ERR(server)) { | 1363 | if (IS_ERR(server)) { |
1398 | error = PTR_ERR(server); | 1364 | error = PTR_ERR(server); |
1399 | goto out; | 1365 | goto out; |
@@ -1417,7 +1383,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1417 | 1383 | ||
1418 | if (!s->s_root) { | 1384 | if (!s->s_root) { |
1419 | /* initial superblock/root creation */ | 1385 | /* initial superblock/root creation */ |
1420 | nfs_fill_super(s, data); | 1386 | nfs_fill_super(s, &data); |
1421 | } | 1387 | } |
1422 | 1388 | ||
1423 | mntroot = nfs_get_root(s, &mntfh); | 1389 | mntroot = nfs_get_root(s, &mntfh); |
@@ -1432,8 +1398,7 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1432 | error = 0; | 1398 | error = 0; |
1433 | 1399 | ||
1434 | out: | 1400 | out: |
1435 | if (data != raw_data) | 1401 | kfree(data.nfs_server.hostname); |
1436 | kfree(data); | ||
1437 | return error; | 1402 | return error; |
1438 | 1403 | ||
1439 | out_err_nosb: | 1404 | out_err_nosb: |
@@ -1559,38 +1524,49 @@ static void nfs4_fill_super(struct super_block *sb) | |||
1559 | /* | 1524 | /* |
1560 | * Validate NFSv4 mount options | 1525 | * Validate NFSv4 mount options |
1561 | */ | 1526 | */ |
1562 | static int nfs4_validate_mount_data(struct nfs4_mount_data **options, | 1527 | static int nfs4_validate_mount_data(void *options, |
1563 | const char *dev_name, | 1528 | struct nfs_parsed_mount_data *args, |
1564 | struct sockaddr_in *addr, | 1529 | const char *dev_name) |
1565 | rpc_authflavor_t *authflavour, | ||
1566 | char **hostname, | ||
1567 | char **mntpath, | ||
1568 | char **ip_addr) | ||
1569 | { | 1530 | { |
1570 | struct nfs4_mount_data *data = *options; | 1531 | struct nfs4_mount_data *data = (struct nfs4_mount_data *)options; |
1571 | char *c; | 1532 | char *c; |
1572 | 1533 | ||
1573 | if (data == NULL) | 1534 | if (data == NULL) |
1574 | goto out_no_data; | 1535 | goto out_no_data; |
1575 | 1536 | ||
1537 | memset(args, 0, sizeof(*args)); | ||
1538 | args->rsize = NFS_MAX_FILE_IO_SIZE; | ||
1539 | args->wsize = NFS_MAX_FILE_IO_SIZE; | ||
1540 | args->timeo = 600; | ||
1541 | args->retrans = 2; | ||
1542 | args->acregmin = 3; | ||
1543 | args->acregmax = 60; | ||
1544 | args->acdirmin = 30; | ||
1545 | args->acdirmax = 60; | ||
1546 | args->nfs_server.protocol = XPRT_TRANSPORT_TCP; | ||
1547 | |||
1576 | switch (data->version) { | 1548 | switch (data->version) { |
1577 | case 1: | 1549 | case 1: |
1578 | if (data->host_addrlen != sizeof(*addr)) | 1550 | if (data->host_addrlen != sizeof(args->nfs_server.address)) |
1579 | goto out_no_address; | 1551 | goto out_no_address; |
1580 | if (copy_from_user(addr, data->host_addr, sizeof(*addr))) | 1552 | if (copy_from_user(&args->nfs_server.address, |
1553 | data->host_addr, | ||
1554 | sizeof(args->nfs_server.address))) | ||
1581 | return -EFAULT; | 1555 | return -EFAULT; |
1582 | if (addr->sin_port == 0) | 1556 | if (args->nfs_server.address.sin_port == 0) |
1583 | addr->sin_port = htons(NFS_PORT); | 1557 | args->nfs_server.address.sin_port = htons(NFS_PORT); |
1584 | if (!nfs_verify_server_address((struct sockaddr *) addr)) | 1558 | if (!nfs_verify_server_address((struct sockaddr *) |
1559 | &args->nfs_server.address)) | ||
1585 | goto out_no_address; | 1560 | goto out_no_address; |
1586 | 1561 | ||
1587 | switch (data->auth_flavourlen) { | 1562 | switch (data->auth_flavourlen) { |
1588 | case 0: | 1563 | case 0: |
1589 | *authflavour = RPC_AUTH_UNIX; | 1564 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
1590 | break; | 1565 | break; |
1591 | case 1: | 1566 | case 1: |
1592 | if (copy_from_user(authflavour, data->auth_flavours, | 1567 | if (copy_from_user(&args->auth_flavors[0], |
1593 | sizeof(*authflavour))) | 1568 | data->auth_flavours, |
1569 | sizeof(args->auth_flavors[0]))) | ||
1594 | return -EFAULT; | 1570 | return -EFAULT; |
1595 | break; | 1571 | break; |
1596 | default: | 1572 | default: |
@@ -1600,75 +1576,57 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options, | |||
1600 | c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); | 1576 | c = strndup_user(data->hostname.data, NFS4_MAXNAMLEN); |
1601 | if (IS_ERR(c)) | 1577 | if (IS_ERR(c)) |
1602 | return PTR_ERR(c); | 1578 | return PTR_ERR(c); |
1603 | *hostname = c; | 1579 | args->nfs_server.hostname = c; |
1604 | 1580 | ||
1605 | c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN); | 1581 | c = strndup_user(data->mnt_path.data, NFS4_MAXPATHLEN); |
1606 | if (IS_ERR(c)) | 1582 | if (IS_ERR(c)) |
1607 | return PTR_ERR(c); | 1583 | return PTR_ERR(c); |
1608 | *mntpath = c; | 1584 | args->nfs_server.export_path = c; |
1609 | dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", *mntpath); | 1585 | dfprintk(MOUNT, "NFS: MNTPATH: '%s'\n", c); |
1610 | 1586 | ||
1611 | c = strndup_user(data->client_addr.data, 16); | 1587 | c = strndup_user(data->client_addr.data, 16); |
1612 | if (IS_ERR(c)) | 1588 | if (IS_ERR(c)) |
1613 | return PTR_ERR(c); | 1589 | return PTR_ERR(c); |
1614 | *ip_addr = c; | 1590 | args->client_address = c; |
1591 | |||
1592 | /* | ||
1593 | * Translate to nfs_parsed_mount_data, which nfs4_fill_super | ||
1594 | * can deal with. | ||
1595 | */ | ||
1596 | |||
1597 | args->flags = data->flags & NFS4_MOUNT_FLAGMASK; | ||
1598 | args->rsize = data->rsize; | ||
1599 | args->wsize = data->wsize; | ||
1600 | args->timeo = data->timeo; | ||
1601 | args->retrans = data->retrans; | ||
1602 | args->acregmin = data->acregmin; | ||
1603 | args->acregmax = data->acregmax; | ||
1604 | args->acdirmin = data->acdirmin; | ||
1605 | args->acdirmax = data->acdirmax; | ||
1606 | args->nfs_server.protocol = data->proto; | ||
1615 | 1607 | ||
1616 | break; | 1608 | break; |
1617 | default: { | 1609 | default: { |
1618 | unsigned int len; | 1610 | unsigned int len; |
1619 | struct nfs_parsed_mount_data args = { | 1611 | |
1620 | .rsize = NFS_MAX_FILE_IO_SIZE, | 1612 | if (nfs_parse_mount_options((char *)options, args) == 0) |
1621 | .wsize = NFS_MAX_FILE_IO_SIZE, | ||
1622 | .timeo = 600, | ||
1623 | .retrans = 2, | ||
1624 | .acregmin = 3, | ||
1625 | .acregmax = 60, | ||
1626 | .acdirmin = 30, | ||
1627 | .acdirmax = 60, | ||
1628 | .nfs_server.protocol = IPPROTO_TCP, | ||
1629 | }; | ||
1630 | |||
1631 | if (nfs_parse_mount_options((char *) *options, &args) == 0) | ||
1632 | return -EINVAL; | 1613 | return -EINVAL; |
1633 | 1614 | ||
1634 | if (!nfs_verify_server_address((struct sockaddr *) | 1615 | if (!nfs_verify_server_address((struct sockaddr *) |
1635 | &args.nfs_server.address)) | 1616 | &args->nfs_server.address)) |
1636 | return -EINVAL; | 1617 | return -EINVAL; |
1637 | *addr = args.nfs_server.address; | ||
1638 | 1618 | ||
1639 | switch (args.auth_flavor_len) { | 1619 | switch (args->auth_flavor_len) { |
1640 | case 0: | 1620 | case 0: |
1641 | *authflavour = RPC_AUTH_UNIX; | 1621 | args->auth_flavors[0] = RPC_AUTH_UNIX; |
1642 | break; | 1622 | break; |
1643 | case 1: | 1623 | case 1: |
1644 | *authflavour = (rpc_authflavor_t) args.auth_flavors[0]; | ||
1645 | break; | 1624 | break; |
1646 | default: | 1625 | default: |
1647 | goto out_inval_auth; | 1626 | goto out_inval_auth; |
1648 | } | 1627 | } |
1649 | 1628 | ||
1650 | /* | 1629 | /* |
1651 | * Translate to nfs4_mount_data, which nfs4_fill_super | ||
1652 | * can deal with. | ||
1653 | */ | ||
1654 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
1655 | if (data == NULL) | ||
1656 | return -ENOMEM; | ||
1657 | *options = data; | ||
1658 | |||
1659 | data->version = 1; | ||
1660 | data->flags = args.flags & NFS4_MOUNT_FLAGMASK; | ||
1661 | data->rsize = args.rsize; | ||
1662 | data->wsize = args.wsize; | ||
1663 | data->timeo = args.timeo; | ||
1664 | data->retrans = args.retrans; | ||
1665 | data->acregmin = args.acregmin; | ||
1666 | data->acregmax = args.acregmax; | ||
1667 | data->acdirmin = args.acdirmin; | ||
1668 | data->acdirmax = args.acdirmax; | ||
1669 | data->proto = args.nfs_server.protocol; | ||
1670 | |||
1671 | /* | ||
1672 | * Split "dev_name" into "hostname:mntpath". | 1630 | * Split "dev_name" into "hostname:mntpath". |
1673 | */ | 1631 | */ |
1674 | c = strchr(dev_name, ':'); | 1632 | c = strchr(dev_name, ':'); |
@@ -1678,27 +1636,25 @@ static int nfs4_validate_mount_data(struct nfs4_mount_data **options, | |||
1678 | len = c - dev_name; | 1636 | len = c - dev_name; |
1679 | if (len > NFS4_MAXNAMLEN) | 1637 | if (len > NFS4_MAXNAMLEN) |
1680 | return -ENAMETOOLONG; | 1638 | return -ENAMETOOLONG; |
1681 | *hostname = kzalloc(len, GFP_KERNEL); | 1639 | args->nfs_server.hostname = kzalloc(len, GFP_KERNEL); |
1682 | if (*hostname == NULL) | 1640 | if (args->nfs_server.hostname == NULL) |
1683 | return -ENOMEM; | 1641 | return -ENOMEM; |
1684 | strncpy(*hostname, dev_name, len - 1); | 1642 | strncpy(args->nfs_server.hostname, dev_name, len - 1); |
1685 | 1643 | ||
1686 | c++; /* step over the ':' */ | 1644 | c++; /* step over the ':' */ |
1687 | len = strlen(c); | 1645 | len = strlen(c); |
1688 | if (len > NFS4_MAXPATHLEN) | 1646 | if (len > NFS4_MAXPATHLEN) |
1689 | return -ENAMETOOLONG; | 1647 | return -ENAMETOOLONG; |
1690 | *mntpath = kzalloc(len + 1, GFP_KERNEL); | 1648 | args->nfs_server.export_path = kzalloc(len + 1, GFP_KERNEL); |
1691 | if (*mntpath == NULL) | 1649 | if (args->nfs_server.export_path == NULL) |
1692 | return -ENOMEM; | 1650 | return -ENOMEM; |
1693 | strncpy(*mntpath, c, len); | 1651 | strncpy(args->nfs_server.export_path, c, len); |
1694 | 1652 | ||
1695 | dprintk("MNTPATH: %s\n", *mntpath); | 1653 | dprintk("MNTPATH: %s\n", args->nfs_server.export_path); |
1696 | 1654 | ||
1697 | if (args.client_address == NULL) | 1655 | if (args->client_address == NULL) |
1698 | goto out_no_client_address; | 1656 | goto out_no_client_address; |
1699 | 1657 | ||
1700 | *ip_addr = args.client_address; | ||
1701 | |||
1702 | break; | 1658 | break; |
1703 | } | 1659 | } |
1704 | } | 1660 | } |
@@ -1729,14 +1685,11 @@ out_no_client_address: | |||
1729 | static int nfs4_get_sb(struct file_system_type *fs_type, | 1685 | static int nfs4_get_sb(struct file_system_type *fs_type, |
1730 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 1686 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
1731 | { | 1687 | { |
1732 | struct nfs4_mount_data *data = raw_data; | 1688 | struct nfs_parsed_mount_data data; |
1733 | struct super_block *s; | 1689 | struct super_block *s; |
1734 | struct nfs_server *server; | 1690 | struct nfs_server *server; |
1735 | struct sockaddr_in addr; | ||
1736 | rpc_authflavor_t authflavour; | ||
1737 | struct nfs_fh mntfh; | 1691 | struct nfs_fh mntfh; |
1738 | struct dentry *mntroot; | 1692 | struct dentry *mntroot; |
1739 | char *mntpath = NULL, *hostname = NULL, *ip_addr = NULL; | ||
1740 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; | 1693 | int (*compare_super)(struct super_block *, void *) = nfs_compare_super; |
1741 | struct nfs_sb_mountdata sb_mntdata = { | 1694 | struct nfs_sb_mountdata sb_mntdata = { |
1742 | .mntflags = flags, | 1695 | .mntflags = flags, |
@@ -1744,14 +1697,12 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
1744 | int error; | 1697 | int error; |
1745 | 1698 | ||
1746 | /* Validate the mount data */ | 1699 | /* Validate the mount data */ |
1747 | error = nfs4_validate_mount_data(&data, dev_name, &addr, &authflavour, | 1700 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); |
1748 | &hostname, &mntpath, &ip_addr); | ||
1749 | if (error < 0) | 1701 | if (error < 0) |
1750 | goto out; | 1702 | goto out; |
1751 | 1703 | ||
1752 | /* Get a volume representation */ | 1704 | /* Get a volume representation */ |
1753 | server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, | 1705 | server = nfs4_create_server(&data, &mntfh); |
1754 | authflavour, &mntfh); | ||
1755 | if (IS_ERR(server)) { | 1706 | if (IS_ERR(server)) { |
1756 | error = PTR_ERR(server); | 1707 | error = PTR_ERR(server); |
1757 | goto out; | 1708 | goto out; |
@@ -1790,9 +1741,9 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
1790 | error = 0; | 1741 | error = 0; |
1791 | 1742 | ||
1792 | out: | 1743 | out: |
1793 | kfree(ip_addr); | 1744 | kfree(data.client_address); |
1794 | kfree(mntpath); | 1745 | kfree(data.nfs_server.export_path); |
1795 | kfree(hostname); | 1746 | kfree(data.nfs_server.hostname); |
1796 | return error; | 1747 | return error; |
1797 | 1748 | ||
1798 | out_free: | 1749 | out_free: |