diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-03 21:27:36 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-03 21:27:36 -0500 |
commit | 7285f2d2ffd4b7ab4ffb70a47759ee209c30017b (patch) | |
tree | 255cdddc72429f013b3bcf5c51d1818cb3e3bd51 | |
parent | 0b08b07507d5ae733408fd4ebda1cd89d3a840ef (diff) | |
parent | 44ed3556bad809797f7b06a4a88918fd8a23d6fe (diff) |
Merge branch 'devel' into linux-next
-rw-r--r-- | fs/nfs/callback.c | 12 | ||||
-rw-r--r-- | fs/nfs/dir.c | 67 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 7 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 8 | ||||
-rw-r--r-- | fs/nfs/super.c | 104 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/sched.h | 2 | ||||
-rw-r--r-- | net/sunrpc/addr.c | 10 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 54 | ||||
-rw-r--r-- | net/sunrpc/rpcb_clnt.c | 104 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 3 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 2 |
12 files changed, 261 insertions, 114 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 293fa0528a6e..e66ec5d169f7 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -78,11 +78,6 @@ nfs4_callback_svc(void *vrqstp) | |||
78 | 78 | ||
79 | set_freezable(); | 79 | set_freezable(); |
80 | 80 | ||
81 | /* | ||
82 | * FIXME: do we really need to run this under the BKL? If so, please | ||
83 | * add a comment about what it's intended to protect. | ||
84 | */ | ||
85 | lock_kernel(); | ||
86 | while (!kthread_should_stop()) { | 81 | while (!kthread_should_stop()) { |
87 | /* | 82 | /* |
88 | * Listen for a request on the socket | 83 | * Listen for a request on the socket |
@@ -104,7 +99,6 @@ nfs4_callback_svc(void *vrqstp) | |||
104 | preverr = err; | 99 | preverr = err; |
105 | svc_process(rqstp); | 100 | svc_process(rqstp); |
106 | } | 101 | } |
107 | unlock_kernel(); | ||
108 | return 0; | 102 | return 0; |
109 | } | 103 | } |
110 | 104 | ||
@@ -160,11 +154,6 @@ nfs41_callback_svc(void *vrqstp) | |||
160 | 154 | ||
161 | set_freezable(); | 155 | set_freezable(); |
162 | 156 | ||
163 | /* | ||
164 | * FIXME: do we really need to run this under the BKL? If so, please | ||
165 | * add a comment about what it's intended to protect. | ||
166 | */ | ||
167 | lock_kernel(); | ||
168 | while (!kthread_should_stop()) { | 157 | while (!kthread_should_stop()) { |
169 | prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); | 158 | prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); |
170 | spin_lock_bh(&serv->sv_cb_lock); | 159 | spin_lock_bh(&serv->sv_cb_lock); |
@@ -183,7 +172,6 @@ nfs41_callback_svc(void *vrqstp) | |||
183 | } | 172 | } |
184 | finish_wait(&serv->sv_cb_waitq, &wq); | 173 | finish_wait(&serv->sv_cb_waitq, &wq); |
185 | } | 174 | } |
186 | unlock_kernel(); | ||
187 | return 0; | 175 | return 0; |
188 | } | 176 | } |
189 | 177 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7cb298525eef..2c5ace4f00a7 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1579,55 +1579,46 @@ static int nfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1579 | struct dentry *dentry = NULL, *rehash = NULL; | 1579 | struct dentry *dentry = NULL, *rehash = NULL; |
1580 | int error = -EBUSY; | 1580 | int error = -EBUSY; |
1581 | 1581 | ||
1582 | /* | ||
1583 | * To prevent any new references to the target during the rename, | ||
1584 | * we unhash the dentry and free the inode in advance. | ||
1585 | */ | ||
1586 | if (!d_unhashed(new_dentry)) { | ||
1587 | d_drop(new_dentry); | ||
1588 | rehash = new_dentry; | ||
1589 | } | ||
1590 | |||
1591 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", | 1582 | dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n", |
1592 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, | 1583 | old_dentry->d_parent->d_name.name, old_dentry->d_name.name, |
1593 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, | 1584 | new_dentry->d_parent->d_name.name, new_dentry->d_name.name, |
1594 | atomic_read(&new_dentry->d_count)); | 1585 | atomic_read(&new_dentry->d_count)); |
1595 | 1586 | ||
1596 | /* | 1587 | /* |
1597 | * First check whether the target is busy ... we can't | 1588 | * For non-directories, check whether the target is busy and if so, |
1598 | * safely do _any_ rename if the target is in use. | 1589 | * make a copy of the dentry and then do a silly-rename. If the |
1599 | * | 1590 | * silly-rename succeeds, the copied dentry is hashed and becomes |
1600 | * For files, make a copy of the dentry and then do a | 1591 | * the new target. |
1601 | * silly-rename. If the silly-rename succeeds, the | ||
1602 | * copied dentry is hashed and becomes the new target. | ||
1603 | */ | 1592 | */ |
1604 | if (!new_inode) | 1593 | if (new_inode && !S_ISDIR(new_inode->i_mode)) { |
1605 | goto go_ahead; | 1594 | /* |
1606 | if (S_ISDIR(new_inode->i_mode)) { | 1595 | * To prevent any new references to the target during the |
1607 | error = -EISDIR; | 1596 | * rename, we unhash the dentry in advance. |
1608 | if (!S_ISDIR(old_inode->i_mode)) | 1597 | */ |
1609 | goto out; | 1598 | if (!d_unhashed(new_dentry)) { |
1610 | } else if (atomic_read(&new_dentry->d_count) > 2) { | 1599 | d_drop(new_dentry); |
1611 | int err; | 1600 | rehash = new_dentry; |
1612 | /* copy the target dentry's name */ | 1601 | } |
1613 | dentry = d_alloc(new_dentry->d_parent, | 1602 | |
1614 | &new_dentry->d_name); | 1603 | if (atomic_read(&new_dentry->d_count) > 2) { |
1615 | if (!dentry) | 1604 | int err; |
1616 | goto out; | 1605 | |
1606 | /* copy the target dentry's name */ | ||
1607 | dentry = d_alloc(new_dentry->d_parent, | ||
1608 | &new_dentry->d_name); | ||
1609 | if (!dentry) | ||
1610 | goto out; | ||
1617 | 1611 | ||
1618 | /* silly-rename the existing target ... */ | 1612 | /* silly-rename the existing target ... */ |
1619 | err = nfs_sillyrename(new_dir, new_dentry); | 1613 | err = nfs_sillyrename(new_dir, new_dentry); |
1620 | if (!err) { | 1614 | if (err) |
1621 | new_dentry = rehash = dentry; | 1615 | goto out; |
1616 | |||
1617 | new_dentry = dentry; | ||
1622 | new_inode = NULL; | 1618 | new_inode = NULL; |
1623 | /* instantiate the replacement target */ | 1619 | } |
1624 | d_instantiate(new_dentry, NULL); | ||
1625 | } else if (atomic_read(&new_dentry->d_count) > 1) | ||
1626 | /* dentry still busy? */ | ||
1627 | goto out; | ||
1628 | } | 1620 | } |
1629 | 1621 | ||
1630 | go_ahead: | ||
1631 | /* | 1622 | /* |
1632 | * ... prune child dentries and writebacks if needed. | 1623 | * ... prune child dentries and writebacks if needed. |
1633 | */ | 1624 | */ |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index df8a734f1c05..0f9b7541e049 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -275,6 +275,13 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode, | |||
275 | /* FALLTHROUGH */ | 275 | /* FALLTHROUGH */ |
276 | #endif /* !defined(CONFIG_NFS_V4_1) */ | 276 | #endif /* !defined(CONFIG_NFS_V4_1) */ |
277 | case -NFS4ERR_FILE_OPEN: | 277 | case -NFS4ERR_FILE_OPEN: |
278 | if (exception->timeout > HZ) { | ||
279 | /* We have retried a decent amount, time to | ||
280 | * fail | ||
281 | */ | ||
282 | ret = -EBUSY; | ||
283 | break; | ||
284 | } | ||
278 | case -NFS4ERR_GRACE: | 285 | case -NFS4ERR_GRACE: |
279 | case -NFS4ERR_DELAY: | 286 | case -NFS4ERR_DELAY: |
280 | ret = nfs4_delay(server->client, &exception->timeout); | 287 | ret = nfs4_delay(server->client, &exception->timeout); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 62927879572f..2eb0059bd693 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -877,6 +877,10 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ | |||
877 | case -NFS4ERR_EXPIRED: | 877 | case -NFS4ERR_EXPIRED: |
878 | case -NFS4ERR_NO_GRACE: | 878 | case -NFS4ERR_NO_GRACE: |
879 | case -NFS4ERR_STALE_CLIENTID: | 879 | case -NFS4ERR_STALE_CLIENTID: |
880 | case -NFS4ERR_BADSESSION: | ||
881 | case -NFS4ERR_BADSLOT: | ||
882 | case -NFS4ERR_BAD_HIGH_SLOT: | ||
883 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
880 | goto out; | 884 | goto out; |
881 | default: | 885 | default: |
882 | printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", | 886 | printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n", |
@@ -959,6 +963,10 @@ restart: | |||
959 | case -NFS4ERR_NO_GRACE: | 963 | case -NFS4ERR_NO_GRACE: |
960 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); | 964 | nfs4_state_mark_reclaim_nograce(sp->so_client, state); |
961 | case -NFS4ERR_STALE_CLIENTID: | 965 | case -NFS4ERR_STALE_CLIENTID: |
966 | case -NFS4ERR_BADSESSION: | ||
967 | case -NFS4ERR_BADSLOT: | ||
968 | case -NFS4ERR_BAD_HIGH_SLOT: | ||
969 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | ||
962 | goto out_err; | 970 | goto out_err; |
963 | } | 971 | } |
964 | nfs4_put_open_state(state); | 972 | nfs4_put_open_state(state); |
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 | ||
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 62f63fb0c4c8..8c880372536e 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -170,8 +170,8 @@ struct nfs4_sequence_args { | |||
170 | struct nfs4_sequence_res { | 170 | struct nfs4_sequence_res { |
171 | struct nfs4_session *sr_session; | 171 | struct nfs4_session *sr_session; |
172 | u8 sr_slotid; /* slot used to send request */ | 172 | u8 sr_slotid; /* slot used to send request */ |
173 | unsigned long sr_renewal_time; | ||
174 | int sr_status; /* sequence operation status */ | 173 | int sr_status; /* sequence operation status */ |
174 | unsigned long sr_renewal_time; | ||
175 | }; | 175 | }; |
176 | 176 | ||
177 | struct nfs4_get_lease_time_args { | 177 | struct nfs4_get_lease_time_args { |
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h index 401097781fc0..1906782ec86b 100644 --- a/include/linux/sunrpc/sched.h +++ b/include/linux/sunrpc/sched.h | |||
@@ -130,12 +130,14 @@ struct rpc_task_setup { | |||
130 | #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ | 130 | #define RPC_TASK_DYNAMIC 0x0080 /* task was kmalloc'ed */ |
131 | #define RPC_TASK_KILLED 0x0100 /* task was killed */ | 131 | #define RPC_TASK_KILLED 0x0100 /* task was killed */ |
132 | #define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */ | 132 | #define RPC_TASK_SOFT 0x0200 /* Use soft timeouts */ |
133 | #define RPC_TASK_SOFTCONN 0x0400 /* Fail if can't connect */ | ||
133 | 134 | ||
134 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) | 135 | #define RPC_IS_ASYNC(t) ((t)->tk_flags & RPC_TASK_ASYNC) |
135 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) | 136 | #define RPC_IS_SWAPPER(t) ((t)->tk_flags & RPC_TASK_SWAPPER) |
136 | #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) | 137 | #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS) |
137 | #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) | 138 | #define RPC_ASSASSINATED(t) ((t)->tk_flags & RPC_TASK_KILLED) |
138 | #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) | 139 | #define RPC_IS_SOFT(t) ((t)->tk_flags & RPC_TASK_SOFT) |
140 | #define RPC_IS_SOFTCONN(t) ((t)->tk_flags & RPC_TASK_SOFTCONN) | ||
139 | 141 | ||
140 | #define RPC_TASK_RUNNING 0 | 142 | #define RPC_TASK_RUNNING 0 |
141 | #define RPC_TASK_QUEUED 1 | 143 | #define RPC_TASK_QUEUED 1 |
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index c7450c8f0a7c..6dcdd2517819 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
@@ -55,16 +55,8 @@ static size_t rpc_ntop6_noscopeid(const struct sockaddr *sap, | |||
55 | 55 | ||
56 | /* | 56 | /* |
57 | * RFC 4291, Section 2.2.1 | 57 | * RFC 4291, Section 2.2.1 |
58 | * | ||
59 | * To keep the result as short as possible, especially | ||
60 | * since we don't shorthand, we don't want leading zeros | ||
61 | * in each halfword, so avoid %pI6. | ||
62 | */ | 58 | */ |
63 | return snprintf(buf, buflen, "%x:%x:%x:%x:%x:%x:%x:%x", | 59 | return snprintf(buf, buflen, "%pI6c", addr); |
64 | ntohs(addr->s6_addr16[0]), ntohs(addr->s6_addr16[1]), | ||
65 | ntohs(addr->s6_addr16[2]), ntohs(addr->s6_addr16[3]), | ||
66 | ntohs(addr->s6_addr16[4]), ntohs(addr->s6_addr16[5]), | ||
67 | ntohs(addr->s6_addr16[6]), ntohs(addr->s6_addr16[7])); | ||
68 | } | 60 | } |
69 | 61 | ||
70 | static size_t rpc_ntop6(const struct sockaddr *sap, | 62 | static size_t rpc_ntop6(const struct sockaddr *sap, |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 38829e20500b..154034b675bd 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -79,7 +79,7 @@ static void call_connect_status(struct rpc_task *task); | |||
79 | 79 | ||
80 | static __be32 *rpc_encode_header(struct rpc_task *task); | 80 | static __be32 *rpc_encode_header(struct rpc_task *task); |
81 | static __be32 *rpc_verify_header(struct rpc_task *task); | 81 | static __be32 *rpc_verify_header(struct rpc_task *task); |
82 | static int rpc_ping(struct rpc_clnt *clnt, int flags); | 82 | static int rpc_ping(struct rpc_clnt *clnt); |
83 | 83 | ||
84 | static void rpc_register_client(struct rpc_clnt *clnt) | 84 | static void rpc_register_client(struct rpc_clnt *clnt) |
85 | { | 85 | { |
@@ -340,7 +340,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
340 | return clnt; | 340 | return clnt; |
341 | 341 | ||
342 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { | 342 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { |
343 | int err = rpc_ping(clnt, RPC_TASK_SOFT); | 343 | int err = rpc_ping(clnt); |
344 | if (err != 0) { | 344 | if (err != 0) { |
345 | rpc_shutdown_client(clnt); | 345 | rpc_shutdown_client(clnt); |
346 | return ERR_PTR(err); | 346 | return ERR_PTR(err); |
@@ -528,7 +528,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old, | |||
528 | clnt->cl_prog = program->number; | 528 | clnt->cl_prog = program->number; |
529 | clnt->cl_vers = version->number; | 529 | clnt->cl_vers = version->number; |
530 | clnt->cl_stats = program->stats; | 530 | clnt->cl_stats = program->stats; |
531 | err = rpc_ping(clnt, RPC_TASK_SOFT); | 531 | err = rpc_ping(clnt); |
532 | if (err != 0) { | 532 | if (err != 0) { |
533 | rpc_shutdown_client(clnt); | 533 | rpc_shutdown_client(clnt); |
534 | clnt = ERR_PTR(err); | 534 | clnt = ERR_PTR(err); |
@@ -1060,7 +1060,7 @@ call_bind_status(struct rpc_task *task) | |||
1060 | goto retry_timeout; | 1060 | goto retry_timeout; |
1061 | case -EPFNOSUPPORT: | 1061 | case -EPFNOSUPPORT: |
1062 | /* server doesn't support any rpcbind version we know of */ | 1062 | /* server doesn't support any rpcbind version we know of */ |
1063 | dprintk("RPC: %5u remote rpcbind service unavailable\n", | 1063 | dprintk("RPC: %5u unrecognized remote rpcbind service\n", |
1064 | task->tk_pid); | 1064 | task->tk_pid); |
1065 | break; | 1065 | break; |
1066 | case -EPROTONOSUPPORT: | 1066 | case -EPROTONOSUPPORT: |
@@ -1069,6 +1069,21 @@ call_bind_status(struct rpc_task *task) | |||
1069 | task->tk_status = 0; | 1069 | task->tk_status = 0; |
1070 | task->tk_action = call_bind; | 1070 | task->tk_action = call_bind; |
1071 | return; | 1071 | return; |
1072 | case -ECONNREFUSED: /* connection problems */ | ||
1073 | case -ECONNRESET: | ||
1074 | case -ENOTCONN: | ||
1075 | case -EHOSTDOWN: | ||
1076 | case -EHOSTUNREACH: | ||
1077 | case -ENETUNREACH: | ||
1078 | case -EPIPE: | ||
1079 | dprintk("RPC: %5u remote rpcbind unreachable: %d\n", | ||
1080 | task->tk_pid, task->tk_status); | ||
1081 | if (!RPC_IS_SOFTCONN(task)) { | ||
1082 | rpc_delay(task, 5*HZ); | ||
1083 | goto retry_timeout; | ||
1084 | } | ||
1085 | status = task->tk_status; | ||
1086 | break; | ||
1072 | default: | 1087 | default: |
1073 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", | 1088 | dprintk("RPC: %5u unrecognized rpcbind error (%d)\n", |
1074 | task->tk_pid, -task->tk_status); | 1089 | task->tk_pid, -task->tk_status); |
@@ -1180,11 +1195,25 @@ static void | |||
1180 | call_transmit_status(struct rpc_task *task) | 1195 | call_transmit_status(struct rpc_task *task) |
1181 | { | 1196 | { |
1182 | task->tk_action = call_status; | 1197 | task->tk_action = call_status; |
1198 | |||
1199 | /* | ||
1200 | * Common case: success. Force the compiler to put this | ||
1201 | * test first. | ||
1202 | */ | ||
1203 | if (task->tk_status == 0) { | ||
1204 | xprt_end_transmit(task); | ||
1205 | rpc_task_force_reencode(task); | ||
1206 | return; | ||
1207 | } | ||
1208 | |||
1183 | switch (task->tk_status) { | 1209 | switch (task->tk_status) { |
1184 | case -EAGAIN: | 1210 | case -EAGAIN: |
1185 | break; | 1211 | break; |
1186 | default: | 1212 | default: |
1213 | dprint_status(task); | ||
1187 | xprt_end_transmit(task); | 1214 | xprt_end_transmit(task); |
1215 | rpc_task_force_reencode(task); | ||
1216 | break; | ||
1188 | /* | 1217 | /* |
1189 | * Special cases: if we've been waiting on the | 1218 | * Special cases: if we've been waiting on the |
1190 | * socket's write_space() callback, or if the | 1219 | * socket's write_space() callback, or if the |
@@ -1192,11 +1221,16 @@ call_transmit_status(struct rpc_task *task) | |||
1192 | * then hold onto the transport lock. | 1221 | * then hold onto the transport lock. |
1193 | */ | 1222 | */ |
1194 | case -ECONNREFUSED: | 1223 | case -ECONNREFUSED: |
1195 | case -ECONNRESET: | ||
1196 | case -ENOTCONN: | ||
1197 | case -EHOSTDOWN: | 1224 | case -EHOSTDOWN: |
1198 | case -EHOSTUNREACH: | 1225 | case -EHOSTUNREACH: |
1199 | case -ENETUNREACH: | 1226 | case -ENETUNREACH: |
1227 | if (RPC_IS_SOFTCONN(task)) { | ||
1228 | xprt_end_transmit(task); | ||
1229 | rpc_exit(task, task->tk_status); | ||
1230 | break; | ||
1231 | } | ||
1232 | case -ECONNRESET: | ||
1233 | case -ENOTCONN: | ||
1200 | case -EPIPE: | 1234 | case -EPIPE: |
1201 | rpc_task_force_reencode(task); | 1235 | rpc_task_force_reencode(task); |
1202 | } | 1236 | } |
@@ -1346,6 +1380,10 @@ call_timeout(struct rpc_task *task) | |||
1346 | dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); | 1380 | dprintk("RPC: %5u call_timeout (major)\n", task->tk_pid); |
1347 | task->tk_timeouts++; | 1381 | task->tk_timeouts++; |
1348 | 1382 | ||
1383 | if (RPC_IS_SOFTCONN(task)) { | ||
1384 | rpc_exit(task, -ETIMEDOUT); | ||
1385 | return; | ||
1386 | } | ||
1349 | if (RPC_IS_SOFT(task)) { | 1387 | if (RPC_IS_SOFT(task)) { |
1350 | if (clnt->cl_chatty) | 1388 | if (clnt->cl_chatty) |
1351 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | 1389 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
@@ -1675,14 +1713,14 @@ static struct rpc_procinfo rpcproc_null = { | |||
1675 | .p_decode = rpcproc_decode_null, | 1713 | .p_decode = rpcproc_decode_null, |
1676 | }; | 1714 | }; |
1677 | 1715 | ||
1678 | static int rpc_ping(struct rpc_clnt *clnt, int flags) | 1716 | static int rpc_ping(struct rpc_clnt *clnt) |
1679 | { | 1717 | { |
1680 | struct rpc_message msg = { | 1718 | struct rpc_message msg = { |
1681 | .rpc_proc = &rpcproc_null, | 1719 | .rpc_proc = &rpcproc_null, |
1682 | }; | 1720 | }; |
1683 | int err; | 1721 | int err; |
1684 | msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0); | 1722 | msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0); |
1685 | err = rpc_call_sync(clnt, &msg, flags); | 1723 | err = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN); |
1686 | put_rpccred(msg.rpc_cred); | 1724 | put_rpccred(msg.rpc_cred); |
1687 | return err; | 1725 | return err; |
1688 | } | 1726 | } |
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 830faf4d9997..3e3772d8eb92 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/in6.h> | 20 | #include <linux/in6.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/mutex.h> | ||
23 | #include <net/ipv6.h> | 24 | #include <net/ipv6.h> |
24 | 25 | ||
25 | #include <linux/sunrpc/clnt.h> | 26 | #include <linux/sunrpc/clnt.h> |
@@ -110,6 +111,9 @@ static void rpcb_getport_done(struct rpc_task *, void *); | |||
110 | static void rpcb_map_release(void *data); | 111 | static void rpcb_map_release(void *data); |
111 | static struct rpc_program rpcb_program; | 112 | static struct rpc_program rpcb_program; |
112 | 113 | ||
114 | static struct rpc_clnt * rpcb_local_clnt; | ||
115 | static struct rpc_clnt * rpcb_local_clnt4; | ||
116 | |||
113 | struct rpcbind_args { | 117 | struct rpcbind_args { |
114 | struct rpc_xprt * r_xprt; | 118 | struct rpc_xprt * r_xprt; |
115 | 119 | ||
@@ -163,21 +167,60 @@ static const struct sockaddr_in rpcb_inaddr_loopback = { | |||
163 | .sin_port = htons(RPCBIND_PORT), | 167 | .sin_port = htons(RPCBIND_PORT), |
164 | }; | 168 | }; |
165 | 169 | ||
166 | static struct rpc_clnt *rpcb_create_local(struct sockaddr *addr, | 170 | static DEFINE_MUTEX(rpcb_create_local_mutex); |
167 | size_t addrlen, u32 version) | 171 | |
172 | /* | ||
173 | * Returns zero on success, otherwise a negative errno value | ||
174 | * is returned. | ||
175 | */ | ||
176 | static int rpcb_create_local(void) | ||
168 | { | 177 | { |
169 | struct rpc_create_args args = { | 178 | struct rpc_create_args args = { |
170 | .protocol = XPRT_TRANSPORT_UDP, | 179 | .protocol = XPRT_TRANSPORT_TCP, |
171 | .address = addr, | 180 | .address = (struct sockaddr *)&rpcb_inaddr_loopback, |
172 | .addrsize = addrlen, | 181 | .addrsize = sizeof(rpcb_inaddr_loopback), |
173 | .servername = "localhost", | 182 | .servername = "localhost", |
174 | .program = &rpcb_program, | 183 | .program = &rpcb_program, |
175 | .version = version, | 184 | .version = RPCBVERS_2, |
176 | .authflavor = RPC_AUTH_UNIX, | 185 | .authflavor = RPC_AUTH_UNIX, |
177 | .flags = RPC_CLNT_CREATE_NOPING, | 186 | .flags = RPC_CLNT_CREATE_NOPING, |
178 | }; | 187 | }; |
188 | struct rpc_clnt *clnt, *clnt4; | ||
189 | int result = 0; | ||
190 | |||
191 | if (rpcb_local_clnt) | ||
192 | return result; | ||
193 | |||
194 | mutex_lock(&rpcb_create_local_mutex); | ||
195 | if (rpcb_local_clnt) | ||
196 | goto out; | ||
197 | |||
198 | clnt = rpc_create(&args); | ||
199 | if (IS_ERR(clnt)) { | ||
200 | dprintk("RPC: failed to create local rpcbind " | ||
201 | "client (errno %ld).\n", PTR_ERR(clnt)); | ||
202 | result = -PTR_ERR(clnt); | ||
203 | goto out; | ||
204 | } | ||
179 | 205 | ||
180 | return rpc_create(&args); | 206 | /* |
207 | * This results in an RPC ping. On systems running portmapper, | ||
208 | * the v4 ping will fail. Proceed anyway, but disallow rpcb | ||
209 | * v4 upcalls. | ||
210 | */ | ||
211 | clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4); | ||
212 | if (IS_ERR(clnt4)) { | ||
213 | dprintk("RPC: failed to create local rpcbind v4 " | ||
214 | "cleint (errno %ld).\n", PTR_ERR(clnt4)); | ||
215 | clnt4 = NULL; | ||
216 | } | ||
217 | |||
218 | rpcb_local_clnt = clnt; | ||
219 | rpcb_local_clnt4 = clnt4; | ||
220 | |||
221 | out: | ||
222 | mutex_unlock(&rpcb_create_local_mutex); | ||
223 | return result; | ||
181 | } | 224 | } |
182 | 225 | ||
183 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | 226 | static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, |
@@ -209,22 +252,13 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr, | |||
209 | return rpc_create(&args); | 252 | return rpc_create(&args); |
210 | } | 253 | } |
211 | 254 | ||
212 | static int rpcb_register_call(const u32 version, struct rpc_message *msg) | 255 | static int rpcb_register_call(struct rpc_clnt *clnt, struct rpc_message *msg) |
213 | { | 256 | { |
214 | struct sockaddr *addr = (struct sockaddr *)&rpcb_inaddr_loopback; | ||
215 | size_t addrlen = sizeof(rpcb_inaddr_loopback); | ||
216 | struct rpc_clnt *rpcb_clnt; | ||
217 | int result, error = 0; | 257 | int result, error = 0; |
218 | 258 | ||
219 | msg->rpc_resp = &result; | 259 | msg->rpc_resp = &result; |
220 | 260 | ||
221 | rpcb_clnt = rpcb_create_local(addr, addrlen, version); | 261 | error = rpc_call_sync(clnt, msg, RPC_TASK_SOFTCONN); |
222 | if (!IS_ERR(rpcb_clnt)) { | ||
223 | error = rpc_call_sync(rpcb_clnt, msg, 0); | ||
224 | rpc_shutdown_client(rpcb_clnt); | ||
225 | } else | ||
226 | error = PTR_ERR(rpcb_clnt); | ||
227 | |||
228 | if (error < 0) { | 262 | if (error < 0) { |
229 | dprintk("RPC: failed to contact local rpcbind " | 263 | dprintk("RPC: failed to contact local rpcbind " |
230 | "server (errno %d).\n", -error); | 264 | "server (errno %d).\n", -error); |
@@ -279,6 +313,11 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
279 | struct rpc_message msg = { | 313 | struct rpc_message msg = { |
280 | .rpc_argp = &map, | 314 | .rpc_argp = &map, |
281 | }; | 315 | }; |
316 | int error; | ||
317 | |||
318 | error = rpcb_create_local(); | ||
319 | if (error) | ||
320 | return error; | ||
282 | 321 | ||
283 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " | 322 | dprintk("RPC: %sregistering (%u, %u, %d, %u) with local " |
284 | "rpcbind\n", (port ? "" : "un"), | 323 | "rpcbind\n", (port ? "" : "un"), |
@@ -288,7 +327,7 @@ int rpcb_register(u32 prog, u32 vers, int prot, unsigned short port) | |||
288 | if (port) | 327 | if (port) |
289 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; | 328 | msg.rpc_proc = &rpcb_procedures2[RPCBPROC_SET]; |
290 | 329 | ||
291 | return rpcb_register_call(RPCBVERS_2, &msg); | 330 | return rpcb_register_call(rpcb_local_clnt, &msg); |
292 | } | 331 | } |
293 | 332 | ||
294 | /* | 333 | /* |
@@ -313,7 +352,7 @@ static int rpcb_register_inet4(const struct sockaddr *sap, | |||
313 | if (port) | 352 | if (port) |
314 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 353 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
315 | 354 | ||
316 | result = rpcb_register_call(RPCBVERS_4, msg); | 355 | result = rpcb_register_call(rpcb_local_clnt4, msg); |
317 | kfree(map->r_addr); | 356 | kfree(map->r_addr); |
318 | return result; | 357 | return result; |
319 | } | 358 | } |
@@ -340,7 +379,7 @@ static int rpcb_register_inet6(const struct sockaddr *sap, | |||
340 | if (port) | 379 | if (port) |
341 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; | 380 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_SET]; |
342 | 381 | ||
343 | result = rpcb_register_call(RPCBVERS_4, msg); | 382 | result = rpcb_register_call(rpcb_local_clnt4, msg); |
344 | kfree(map->r_addr); | 383 | kfree(map->r_addr); |
345 | return result; | 384 | return result; |
346 | } | 385 | } |
@@ -356,7 +395,7 @@ static int rpcb_unregister_all_protofamilies(struct rpc_message *msg) | |||
356 | map->r_addr = ""; | 395 | map->r_addr = ""; |
357 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; | 396 | msg->rpc_proc = &rpcb_procedures4[RPCBPROC_UNSET]; |
358 | 397 | ||
359 | return rpcb_register_call(RPCBVERS_4, msg); | 398 | return rpcb_register_call(rpcb_local_clnt4, msg); |
360 | } | 399 | } |
361 | 400 | ||
362 | /** | 401 | /** |
@@ -414,6 +453,13 @@ int rpcb_v4_register(const u32 program, const u32 version, | |||
414 | struct rpc_message msg = { | 453 | struct rpc_message msg = { |
415 | .rpc_argp = &map, | 454 | .rpc_argp = &map, |
416 | }; | 455 | }; |
456 | int error; | ||
457 | |||
458 | error = rpcb_create_local(); | ||
459 | if (error) | ||
460 | return error; | ||
461 | if (rpcb_local_clnt4 == NULL) | ||
462 | return -EPROTONOSUPPORT; | ||
417 | 463 | ||
418 | if (address == NULL) | 464 | if (address == NULL) |
419 | return rpcb_unregister_all_protofamilies(&msg); | 465 | return rpcb_unregister_all_protofamilies(&msg); |
@@ -491,7 +537,7 @@ static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbi | |||
491 | .rpc_message = &msg, | 537 | .rpc_message = &msg, |
492 | .callback_ops = &rpcb_getport_ops, | 538 | .callback_ops = &rpcb_getport_ops, |
493 | .callback_data = map, | 539 | .callback_data = map, |
494 | .flags = RPC_TASK_ASYNC, | 540 | .flags = RPC_TASK_ASYNC | RPC_TASK_SOFTCONN, |
495 | }; | 541 | }; |
496 | 542 | ||
497 | return rpc_run_task(&task_setup_data); | 543 | return rpc_run_task(&task_setup_data); |
@@ -1027,3 +1073,15 @@ static struct rpc_program rpcb_program = { | |||
1027 | .version = rpcb_version, | 1073 | .version = rpcb_version, |
1028 | .stats = &rpcb_stats, | 1074 | .stats = &rpcb_stats, |
1029 | }; | 1075 | }; |
1076 | |||
1077 | /** | ||
1078 | * cleanup_rpcb_clnt - remove xprtsock's sysctls, unregister | ||
1079 | * | ||
1080 | */ | ||
1081 | void cleanup_rpcb_clnt(void) | ||
1082 | { | ||
1083 | if (rpcb_local_clnt4) | ||
1084 | rpc_shutdown_client(rpcb_local_clnt4); | ||
1085 | if (rpcb_local_clnt) | ||
1086 | rpc_shutdown_client(rpcb_local_clnt); | ||
1087 | } | ||
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 8cce92189019..f438347d817b 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | extern struct cache_detail ip_map_cache, unix_gid_cache; | 25 | extern struct cache_detail ip_map_cache, unix_gid_cache; |
26 | 26 | ||
27 | extern void cleanup_rpcb_clnt(void); | ||
28 | |||
27 | static int __init | 29 | static int __init |
28 | init_sunrpc(void) | 30 | init_sunrpc(void) |
29 | { | 31 | { |
@@ -53,6 +55,7 @@ out: | |||
53 | static void __exit | 55 | static void __exit |
54 | cleanup_sunrpc(void) | 56 | cleanup_sunrpc(void) |
55 | { | 57 | { |
58 | cleanup_rpcb_clnt(); | ||
56 | rpcauth_remove_module(); | 59 | rpcauth_remove_module(); |
57 | cleanup_socket_xprt(); | 60 | cleanup_socket_xprt(); |
58 | svc_cleanup_xprt_sock(); | 61 | svc_cleanup_xprt_sock(); |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 37c5475ba258..ff312f8b018d 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -2033,7 +2033,7 @@ static void xs_connect(struct rpc_task *task) | |||
2033 | if (xprt_test_and_set_connecting(xprt)) | 2033 | if (xprt_test_and_set_connecting(xprt)) |
2034 | return; | 2034 | return; |
2035 | 2035 | ||
2036 | if (transport->sock != NULL) { | 2036 | if (transport->sock != NULL && !RPC_IS_SOFTCONN(task)) { |
2037 | dprintk("RPC: xs_connect delayed xprt %p for %lu " | 2037 | dprintk("RPC: xs_connect delayed xprt %p for %lu " |
2038 | "seconds\n", | 2038 | "seconds\n", |
2039 | xprt, xprt->reestablish_timeout / HZ); | 2039 | xprt, xprt->reestablish_timeout / HZ); |