Skip to content

Commit

Permalink
NLM: Always start both UDP and TCP listeners
Browse files Browse the repository at this point in the history
Commit 24e3666, which first appeared in 2.6.19, changed lockd so that
the client side starts a UDP listener only if there is a UDP NFSv2/v3
mount.  Its description notes:

    This... means that lockd will *not* listen on UDP if the only
    mounts are TCP mount (and nfsd hasn't started).

    The latter is the only one that concerns me at all - I don't know
    if this might be a problem with some servers.

Unfortunately it is a problem for Linux itself.  The rpc.statd daemon
on Linux uses UDP for contacting the local lockd, no matter which
protocol is used for NFS mounts.  Without a local lockd UDP listener,
NFSv2/v3 lock recovery from Linux NFS clients always fails.

Revert parts of commit 24e3666 so lockd_up() always starts both
listeners.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Cc: Neil Brown <neilb@suse.de>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
  • Loading branch information
Chuck Lever authored and J. Bruce Fields committed Oct 4, 2008
1 parent 9a38a83 commit 8c3916f
Showing 1 changed file with 19 additions and 18 deletions.
37 changes: 19 additions & 18 deletions fs/lockd/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,25 +189,28 @@ lockd(void *vrqstp)
}

/*
* Make any sockets that are needed but not present.
* If nlm_udpport or nlm_tcpport were set as module
* options, make those sockets unconditionally
* Ensure there are active UDP and TCP listeners for lockd.
*
* Even if we have only TCP NFS mounts and/or TCP NFSDs, some
* local services (such as rpc.statd) still require UDP, and
* some NFS servers do not yet support NLM over TCP.
*
* Returns zero if all listeners are available; otherwise a
* negative errno value is returned.
*/
static int make_socks(struct svc_serv *serv, int proto)
static int make_socks(struct svc_serv *serv)
{
static int warned;
struct svc_xprt *xprt;
int err = 0;

if (proto == IPPROTO_UDP || nlm_udpport) {
xprt = svc_find_xprt(serv, "udp", 0, 0);
if (!xprt)
err = svc_create_xprt(serv, "udp", nlm_udpport,
SVC_SOCK_DEFAULTS);
else
svc_xprt_put(xprt);
}
if (err >= 0 && (proto == IPPROTO_TCP || nlm_tcpport)) {
xprt = svc_find_xprt(serv, "udp", 0, 0);
if (!xprt)
err = svc_create_xprt(serv, "udp", nlm_udpport,
SVC_SOCK_DEFAULTS);
else
svc_xprt_put(xprt);
if (err >= 0) {
xprt = svc_find_xprt(serv, "tcp", 0, 0);
if (!xprt)
err = svc_create_xprt(serv, "tcp", nlm_tcpport,
Expand Down Expand Up @@ -237,11 +240,8 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
/*
* Check whether we're already up and running.
*/
if (nlmsvc_rqst) {
if (proto)
error = make_socks(nlmsvc_rqst->rq_server, proto);
if (nlmsvc_rqst)
goto out;
}

/*
* Sanity check: if there's no pid,
Expand All @@ -258,7 +258,8 @@ lockd_up(int proto) /* Maybe add a 'family' option when IPv6 is supported ?? */
goto out;
}

if ((error = make_socks(serv, proto)) < 0)
error = make_socks(serv);
if (error < 0)
goto destroy_and_out;

/*
Expand Down

0 comments on commit 8c3916f

Please sign in to comment.