diff options
Diffstat (limited to 'fs/nfs/super.c')
| -rw-r--r-- | fs/nfs/super.c | 104 |
1 files changed, 82 insertions, 22 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 90be551b80c1..ce907efc5508 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -175,14 +175,16 @@ static const match_table_t nfs_mount_option_tokens = { | |||
| 175 | }; | 175 | }; |
| 176 | 176 | ||
| 177 | enum { | 177 | enum { |
| 178 | Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma, | 178 | Opt_xprt_udp, Opt_xprt_udp6, Opt_xprt_tcp, Opt_xprt_tcp6, Opt_xprt_rdma, |
| 179 | 179 | ||
| 180 | Opt_xprt_err | 180 | Opt_xprt_err |
| 181 | }; | 181 | }; |
| 182 | 182 | ||
| 183 | static const match_table_t nfs_xprt_protocol_tokens = { | 183 | static const match_table_t nfs_xprt_protocol_tokens = { |
| 184 | { Opt_xprt_udp, "udp" }, | 184 | { Opt_xprt_udp, "udp" }, |
| 185 | { Opt_xprt_udp6, "udp6" }, | ||
| 185 | { Opt_xprt_tcp, "tcp" }, | 186 | { Opt_xprt_tcp, "tcp" }, |
| 187 | { Opt_xprt_tcp6, "tcp6" }, | ||
| 186 | { Opt_xprt_rdma, "rdma" }, | 188 | { Opt_xprt_rdma, "rdma" }, |
| 187 | 189 | ||
| 188 | { Opt_xprt_err, NULL } | 190 | { Opt_xprt_err, NULL } |
| @@ -492,6 +494,45 @@ static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) | |||
| 492 | return sec_flavours[i].str; | 494 | return sec_flavours[i].str; |
| 493 | } | 495 | } |
| 494 | 496 | ||
| 497 | static void nfs_show_mountd_netid(struct seq_file *m, struct nfs_server *nfss, | ||
| 498 | int showdefaults) | ||
| 499 | { | ||
| 500 | struct sockaddr *sap = (struct sockaddr *) &nfss->mountd_address; | ||
| 501 | |||
| 502 | seq_printf(m, ",mountproto="); | ||
| 503 | switch (sap->sa_family) { | ||
| 504 | case AF_INET: | ||
| 505 | switch (nfss->mountd_protocol) { | ||
| 506 | case IPPROTO_UDP: | ||
| 507 | seq_printf(m, RPCBIND_NETID_UDP); | ||
| 508 | break; | ||
| 509 | case IPPROTO_TCP: | ||
| 510 | seq_printf(m, RPCBIND_NETID_TCP); | ||
| 511 | break; | ||
| 512 | default: | ||
| 513 | if (showdefaults) | ||
| 514 | seq_printf(m, "auto"); | ||
| 515 | } | ||
| 516 | break; | ||
| 517 | case AF_INET6: | ||
| 518 | switch (nfss->mountd_protocol) { | ||
| 519 | case IPPROTO_UDP: | ||
| 520 | seq_printf(m, RPCBIND_NETID_UDP6); | ||
| 521 | break; | ||
| 522 | case IPPROTO_TCP: | ||
| 523 | seq_printf(m, RPCBIND_NETID_TCP6); | ||
| 524 | break; | ||
| 525 | default: | ||
| 526 | if (showdefaults) | ||
| 527 | seq_printf(m, "auto"); | ||
| 528 | } | ||
| 529 | break; | ||
| 530 | default: | ||
| 531 | if (showdefaults) | ||
| 532 | seq_printf(m, "auto"); | ||
| 533 | } | ||
| 534 | } | ||
| 535 | |||
| 495 | static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, | 536 | static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, |
| 496 | int showdefaults) | 537 | int showdefaults) |
| 497 | { | 538 | { |
| @@ -505,7 +546,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, | |||
| 505 | } | 546 | } |
| 506 | case AF_INET6: { | 547 | case AF_INET6: { |
| 507 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; | 548 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; |
| 508 | seq_printf(m, ",mountaddr=%pI6", &sin6->sin6_addr); | 549 | seq_printf(m, ",mountaddr=%pI6c", &sin6->sin6_addr); |
| 509 | break; | 550 | break; |
| 510 | } | 551 | } |
| 511 | default: | 552 | default: |
| @@ -518,17 +559,7 @@ static void nfs_show_mountd_options(struct seq_file *m, struct nfs_server *nfss, | |||
| 518 | if (nfss->mountd_port || showdefaults) | 559 | if (nfss->mountd_port || showdefaults) |
| 519 | seq_printf(m, ",mountport=%u", nfss->mountd_port); | 560 | seq_printf(m, ",mountport=%u", nfss->mountd_port); |
| 520 | 561 | ||
| 521 | switch (nfss->mountd_protocol) { | 562 | nfs_show_mountd_netid(m, nfss, showdefaults); |
| 522 | case IPPROTO_UDP: | ||
| 523 | seq_printf(m, ",mountproto=udp"); | ||
| 524 | break; | ||
| 525 | case IPPROTO_TCP: | ||
| 526 | seq_printf(m, ",mountproto=tcp"); | ||
| 527 | break; | ||
| 528 | default: | ||
| 529 | if (showdefaults) | ||
| 530 | seq_printf(m, ",mountproto=auto"); | ||
| 531 | } | ||
| 532 | } | 563 | } |
| 533 | 564 | ||
| 534 | /* | 565 | /* |
| @@ -578,7 +609,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, | |||
| 578 | seq_puts(m, nfs_infop->nostr); | 609 | seq_puts(m, nfs_infop->nostr); |
| 579 | } | 610 | } |
| 580 | seq_printf(m, ",proto=%s", | 611 | seq_printf(m, ",proto=%s", |
| 581 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO)); | 612 | rpc_peeraddr2str(nfss->client, RPC_DISPLAY_NETID)); |
| 582 | if (version == 4) { | 613 | if (version == 4) { |
| 583 | if (nfss->port != NFS_PORT) | 614 | if (nfss->port != NFS_PORT) |
| 584 | seq_printf(m, ",port=%u", nfss->port); | 615 | seq_printf(m, ",port=%u", nfss->port); |
| @@ -714,8 +745,6 @@ static void nfs_umount_begin(struct super_block *sb) | |||
| 714 | struct nfs_server *server; | 745 | struct nfs_server *server; |
| 715 | struct rpc_clnt *rpc; | 746 | struct rpc_clnt *rpc; |
| 716 | 747 | ||
| 717 | lock_kernel(); | ||
| 718 | |||
| 719 | server = NFS_SB(sb); | 748 | server = NFS_SB(sb); |
| 720 | /* -EIO all pending I/O */ | 749 | /* -EIO all pending I/O */ |
| 721 | rpc = server->client_acl; | 750 | rpc = server->client_acl; |
| @@ -724,8 +753,6 @@ static void nfs_umount_begin(struct super_block *sb) | |||
| 724 | rpc = server->client; | 753 | rpc = server->client; |
| 725 | if (!IS_ERR(rpc)) | 754 | if (!IS_ERR(rpc)) |
| 726 | rpc_killall_tasks(rpc); | 755 | rpc_killall_tasks(rpc); |
| 727 | |||
| 728 | unlock_kernel(); | ||
| 729 | } | 756 | } |
| 730 | 757 | ||
| 731 | static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version) | 758 | static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int version) |
| @@ -734,8 +761,6 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve | |||
| 734 | 761 | ||
| 735 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 762 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
| 736 | if (data) { | 763 | if (data) { |
| 737 | data->rsize = NFS_MAX_FILE_IO_SIZE; | ||
| 738 | data->wsize = NFS_MAX_FILE_IO_SIZE; | ||
| 739 | data->acregmin = NFS_DEF_ACREGMIN; | 764 | data->acregmin = NFS_DEF_ACREGMIN; |
| 740 | data->acregmax = NFS_DEF_ACREGMAX; | 765 | data->acregmax = NFS_DEF_ACREGMAX; |
| 741 | data->acdirmin = NFS_DEF_ACDIRMIN; | 766 | data->acdirmin = NFS_DEF_ACDIRMIN; |
| @@ -887,6 +912,8 @@ static int nfs_parse_mount_options(char *raw, | |||
| 887 | { | 912 | { |
| 888 | char *p, *string, *secdata; | 913 | char *p, *string, *secdata; |
| 889 | int rc, sloppy = 0, invalid_option = 0; | 914 | int rc, sloppy = 0, invalid_option = 0; |
| 915 | unsigned short protofamily = AF_UNSPEC; | ||
| 916 | unsigned short mountfamily = AF_UNSPEC; | ||
| 890 | 917 | ||
| 891 | if (!raw) { | 918 | if (!raw) { |
| 892 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 919 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
| @@ -1232,12 +1259,17 @@ static int nfs_parse_mount_options(char *raw, | |||
| 1232 | token = match_token(string, | 1259 | token = match_token(string, |
| 1233 | nfs_xprt_protocol_tokens, args); | 1260 | nfs_xprt_protocol_tokens, args); |
| 1234 | 1261 | ||
| 1262 | protofamily = AF_INET; | ||
| 1235 | switch (token) { | 1263 | switch (token) { |
| 1264 | case Opt_xprt_udp6: | ||
| 1265 | protofamily = AF_INET6; | ||
| 1236 | case Opt_xprt_udp: | 1266 | case Opt_xprt_udp: |
| 1237 | mnt->flags &= ~NFS_MOUNT_TCP; | 1267 | mnt->flags &= ~NFS_MOUNT_TCP; |
| 1238 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; | 1268 | mnt->nfs_server.protocol = XPRT_TRANSPORT_UDP; |
| 1239 | kfree(string); | 1269 | kfree(string); |
| 1240 | break; | 1270 | break; |
| 1271 | case Opt_xprt_tcp6: | ||
| 1272 | protofamily = AF_INET6; | ||
| 1241 | case Opt_xprt_tcp: | 1273 | case Opt_xprt_tcp: |
| 1242 | mnt->flags |= NFS_MOUNT_TCP; | 1274 | mnt->flags |= NFS_MOUNT_TCP; |
| 1243 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; | 1275 | mnt->nfs_server.protocol = XPRT_TRANSPORT_TCP; |
| @@ -1265,10 +1297,15 @@ static int nfs_parse_mount_options(char *raw, | |||
| 1265 | nfs_xprt_protocol_tokens, args); | 1297 | nfs_xprt_protocol_tokens, args); |
| 1266 | kfree(string); | 1298 | kfree(string); |
| 1267 | 1299 | ||
| 1300 | mountfamily = AF_INET; | ||
| 1268 | switch (token) { | 1301 | switch (token) { |
| 1302 | case Opt_xprt_udp6: | ||
| 1303 | mountfamily = AF_INET6; | ||
| 1269 | case Opt_xprt_udp: | 1304 | case Opt_xprt_udp: |
| 1270 | mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; | 1305 | mnt->mount_server.protocol = XPRT_TRANSPORT_UDP; |
| 1271 | break; | 1306 | break; |
| 1307 | case Opt_xprt_tcp6: | ||
| 1308 | mountfamily = AF_INET6; | ||
| 1272 | case Opt_xprt_tcp: | 1309 | case Opt_xprt_tcp: |
| 1273 | mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; | 1310 | mnt->mount_server.protocol = XPRT_TRANSPORT_TCP; |
| 1274 | break; | 1311 | break; |
| @@ -1367,8 +1404,33 @@ static int nfs_parse_mount_options(char *raw, | |||
| 1367 | if (!sloppy && invalid_option) | 1404 | if (!sloppy && invalid_option) |
| 1368 | return 0; | 1405 | return 0; |
| 1369 | 1406 | ||
| 1407 | /* | ||
| 1408 | * verify that any proto=/mountproto= options match the address | ||
| 1409 | * familiies in the addr=/mountaddr= options. | ||
| 1410 | */ | ||
| 1411 | if (protofamily != AF_UNSPEC && | ||
| 1412 | protofamily != mnt->nfs_server.address.ss_family) | ||
| 1413 | goto out_proto_mismatch; | ||
| 1414 | |||
| 1415 | if (mountfamily != AF_UNSPEC) { | ||
| 1416 | if (mnt->mount_server.addrlen) { | ||
| 1417 | if (mountfamily != mnt->mount_server.address.ss_family) | ||
| 1418 | goto out_mountproto_mismatch; | ||
| 1419 | } else { | ||
| 1420 | if (mountfamily != mnt->nfs_server.address.ss_family) | ||
| 1421 | goto out_mountproto_mismatch; | ||
| 1422 | } | ||
| 1423 | } | ||
| 1424 | |||
| 1370 | return 1; | 1425 | return 1; |
| 1371 | 1426 | ||
| 1427 | out_mountproto_mismatch: | ||
| 1428 | printk(KERN_INFO "NFS: mount server address does not match mountproto= " | ||
| 1429 | "option\n"); | ||
| 1430 | return 0; | ||
| 1431 | out_proto_mismatch: | ||
| 1432 | printk(KERN_INFO "NFS: server address does not match proto= option\n"); | ||
| 1433 | return 0; | ||
| 1372 | out_invalid_address: | 1434 | out_invalid_address: |
| 1373 | printk(KERN_INFO "NFS: bad IP address specified: %s\n", p); | 1435 | printk(KERN_INFO "NFS: bad IP address specified: %s\n", p); |
| 1374 | return 0; | 1436 | return 0; |
| @@ -1881,7 +1943,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) | |||
| 1881 | if (data == NULL) | 1943 | if (data == NULL) |
| 1882 | return -ENOMEM; | 1944 | return -ENOMEM; |
| 1883 | 1945 | ||
| 1884 | lock_kernel(); | ||
| 1885 | /* fill out struct with values from existing mount */ | 1946 | /* fill out struct with values from existing mount */ |
| 1886 | data->flags = nfss->flags; | 1947 | data->flags = nfss->flags; |
| 1887 | data->rsize = nfss->rsize; | 1948 | data->rsize = nfss->rsize; |
| @@ -1907,7 +1968,6 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) | |||
| 1907 | error = nfs_compare_remount_data(nfss, data); | 1968 | error = nfs_compare_remount_data(nfss, data); |
| 1908 | out: | 1969 | out: |
| 1909 | kfree(data); | 1970 | kfree(data); |
| 1910 | unlock_kernel(); | ||
| 1911 | return error; | 1971 | return error; |
| 1912 | } | 1972 | } |
| 1913 | 1973 | ||
