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); |
