229 lines
7.6 KiB
Diff
229 lines
7.6 KiB
Diff
From 852424a9a02dbe1a7c3b75a014bc71cad2ab6d5e Mon Sep 17 00:00:00 2001
|
|
From: Neil Brown <neilb@suse.de>
|
|
Date: Mon, 21 Jul 2008 12:45:50 +1000
|
|
References: bnc#404170
|
|
Subject: [PATCH] Check nfs options (vers/protocol) before trying mount.
|
|
|
|
As the kernels nfs-mount client does not have heuristics to pick the
|
|
best protocol/version, also check with portmap to find what is
|
|
available before requesting a mount.
|
|
|
|
However don't try to 'ping' the services. For NFS, this ping would
|
|
need to come from a reserved port, and these are a scarce resource.
|
|
|
|
If the mount found, retry the probe doing any ping that might be
|
|
needed in the hope of finding the problem.
|
|
|
|
Note: this patch also removes the (recently added) setting of
|
|
mountport= in the mount arguments. This is because:
|
|
1/ the kernel can find it easily itself
|
|
2/ it could confuse unmount which may be run much later
|
|
when mountd is running on a different port.
|
|
|
|
|
|
Signed-off-by: Neil Brown <neilb@suse.de>
|
|
---
|
|
utils/mount/network.c | 35 +++++++++++++++++++++--------------
|
|
utils/mount/network.h | 2 +-
|
|
utils/mount/nfsmount.c | 2 +-
|
|
utils/mount/stropts.c | 18 +++++++-----------
|
|
4 files changed, 30 insertions(+), 27 deletions(-)
|
|
|
|
--- nfs-utils-1.1.3.orig/utils/mount/network.c
|
|
+++ nfs-utils-1.1.3/utils/mount/network.c
|
|
@@ -500,9 +500,11 @@ static unsigned short getport(struct soc
|
|
* Use the portmapper to discover whether or not the service we want is
|
|
* available. The lists 'versions' and 'protos' define ordered sequences
|
|
* of service versions and udp/tcp protocols to probe for.
|
|
+ * If 'ping' is set, set an RPC NULL request to make sure the service
|
|
+ * is there. Else just assume that it is.
|
|
*/
|
|
static int probe_port(clnt_addr_t *server, const unsigned long *versions,
|
|
- const unsigned int *protos)
|
|
+ const unsigned int *protos, int ping)
|
|
{
|
|
struct sockaddr_in *saddr = &server->saddr;
|
|
struct pmap *pmap = &server->pmap;
|
|
@@ -530,7 +532,8 @@ static int probe_port(clnt_addr_t *serve
|
|
_("UDP") : _("TCP"),
|
|
p_port);
|
|
}
|
|
- if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL))
|
|
+ if (!ping ||
|
|
+ clnt_ping(saddr, prog, *p_vers, *p_prot, NULL))
|
|
goto out_ok;
|
|
}
|
|
}
|
|
@@ -565,7 +568,7 @@ out_ok:
|
|
return 1;
|
|
}
|
|
|
|
-static int probe_nfsport(clnt_addr_t *nfs_server)
|
|
+static int probe_nfsport(clnt_addr_t *nfs_server, int ping)
|
|
{
|
|
struct pmap *pmap = &nfs_server->pmap;
|
|
|
|
@@ -573,12 +576,14 @@ static int probe_nfsport(clnt_addr_t *nf
|
|
return 1;
|
|
|
|
if (nfs_mount_data_version >= 4)
|
|
- return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first);
|
|
+ return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first,
|
|
+ ping);
|
|
else
|
|
- return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
|
|
+ return probe_port(nfs_server, probe_nfs2_only, probe_udp_only,
|
|
+ ping);
|
|
}
|
|
|
|
-static int probe_mntport(clnt_addr_t *mnt_server)
|
|
+static int probe_mntport(clnt_addr_t *mnt_server, int ping)
|
|
{
|
|
struct pmap *pmap = &mnt_server->pmap;
|
|
|
|
@@ -586,9 +591,11 @@ static int probe_mntport(clnt_addr_t *mn
|
|
return 1;
|
|
|
|
if (nfs_mount_data_version >= 4)
|
|
- return probe_port(mnt_server, probe_mnt3_first, probe_udp_first);
|
|
+ return probe_port(mnt_server, probe_mnt3_first, probe_udp_first,
|
|
+ ping);
|
|
else
|
|
- return probe_port(mnt_server, probe_mnt1_first, probe_udp_only);
|
|
+ return probe_port(mnt_server, probe_mnt1_first, probe_udp_only,
|
|
+ ping);
|
|
}
|
|
|
|
/**
|
|
@@ -601,7 +608,7 @@ static int probe_mntport(clnt_addr_t *mn
|
|
*
|
|
* A side effect of calling this function is that rpccreateerr is set.
|
|
*/
|
|
-int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
|
+int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server, int ping)
|
|
{
|
|
struct pmap *nfs_pmap = &nfs_server->pmap;
|
|
struct pmap *mnt_pmap = &mnt_server->pmap;
|
|
@@ -623,9 +630,9 @@ int probe_bothports(clnt_addr_t *mnt_ser
|
|
|
|
for (; *probe_vers; probe_vers++) {
|
|
nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
|
|
- if ((res = probe_nfsport(nfs_server) != 0)) {
|
|
+ if ((res = probe_nfsport(nfs_server, ping) != 0)) {
|
|
mnt_pmap->pm_vers = *probe_vers;
|
|
- if ((res = probe_mntport(mnt_server)) != 0)
|
|
+ if ((res = probe_mntport(mnt_server, ping)) != 0)
|
|
return 1;
|
|
memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
|
|
}
|
|
@@ -643,9 +650,9 @@ out_bad:
|
|
return 0;
|
|
|
|
version_fixed:
|
|
- if (!probe_nfsport(nfs_server))
|
|
+ if (!probe_nfsport(nfs_server, ping))
|
|
goto out_bad;
|
|
- return probe_mntport(mnt_server);
|
|
+ return probe_mntport(mnt_server, ping);
|
|
}
|
|
|
|
static int probe_statd(void)
|
|
@@ -712,7 +719,7 @@ int nfs_call_umount(clnt_addr_t *mnt_ser
|
|
enum clnt_stat res = 0;
|
|
int msock;
|
|
|
|
- if (!probe_mntport(mnt_server))
|
|
+ if (!probe_mntport(mnt_server, 0))
|
|
return 0;
|
|
clnt = mnt_openclnt(mnt_server, &msock);
|
|
if (!clnt)
|
|
--- nfs-utils-1.1.3.orig/utils/mount/network.h
|
|
+++ nfs-utils-1.1.3/utils/mount/network.h
|
|
@@ -39,7 +39,7 @@ typedef struct {
|
|
static const struct timeval TIMEOUT = { 20, 0 };
|
|
static const struct timeval RETRY_TIMEOUT = { 3, 0 };
|
|
|
|
-int probe_bothports(clnt_addr_t *, clnt_addr_t *);
|
|
+int probe_bothports(clnt_addr_t *, clnt_addr_t *, int);
|
|
int nfs_gethostbyname(const char *, struct sockaddr_in *);
|
|
int nfs_name_to_address(const char *, const sa_family_t,
|
|
struct sockaddr *, socklen_t *);
|
|
--- nfs-utils-1.1.3.orig/utils/mount/nfsmount.c
|
|
+++ nfs-utils-1.1.3/utils/mount/nfsmount.c
|
|
@@ -129,7 +129,7 @@ nfs_call_mount(clnt_addr_t *mnt_server,
|
|
enum clnt_stat stat;
|
|
int msock;
|
|
|
|
- if (!probe_bothports(mnt_server, nfs_server))
|
|
+ if (!probe_bothports(mnt_server, nfs_server, 1))
|
|
goto out_bad;
|
|
|
|
clnt = mnt_openclnt(mnt_server, &msock);
|
|
--- nfs-utils-1.1.3.orig/utils/mount/stropts.c
|
|
+++ nfs-utils-1.1.3/utils/mount/stropts.c
|
|
@@ -314,7 +314,7 @@ static int nfs_is_permanent_error(int er
|
|
* Returns a new group of mount options if successful; otherwise
|
|
* NULL is returned if some failure occurred.
|
|
*/
|
|
-static struct mount_options *nfs_rewrite_mount_options(char *str)
|
|
+static struct mount_options *nfs_rewrite_mount_options(char *str, int ping)
|
|
{
|
|
struct mount_options *options;
|
|
char *option, new_option[64];
|
|
@@ -405,7 +405,7 @@ static struct mount_options *nfs_rewrite
|
|
po_remove_all(options, "tcp");
|
|
po_remove_all(options, "udp");
|
|
|
|
- if (!probe_bothports(&mnt_server, &nfs_server)) {
|
|
+ if (!probe_bothports(&mnt_server, &nfs_server, ping)) {
|
|
errno = ESPIPE;
|
|
goto err;
|
|
}
|
|
@@ -441,11 +441,6 @@ static struct mount_options *nfs_rewrite
|
|
if (po_append(options, new_option) == PO_FAILED)
|
|
goto err;
|
|
|
|
- snprintf(new_option, sizeof(new_option) - 1,
|
|
- "mountport=%lu", mnt_server.pmap.pm_port);
|
|
- if (po_append(options, new_option) == PO_FAILED)
|
|
- goto err;
|
|
-
|
|
errno = 0;
|
|
return options;
|
|
|
|
@@ -486,13 +481,13 @@ static int nfs_sys_mount(const struct nf
|
|
* 'extra_opts' are updated to reflect the mount options that worked.
|
|
* If the retry fails, 'options' and 'extra_opts' are left unchanged.
|
|
*/
|
|
-static int nfs_retry_nfs23mount(struct nfsmount_info *mi)
|
|
+static int nfs_try_nfs23mount_probe(struct nfsmount_info *mi, int ping)
|
|
{
|
|
struct mount_options *retry_options;
|
|
char *retry_str = NULL;
|
|
char **extra_opts = mi->extra_opts;
|
|
|
|
- retry_options = nfs_rewrite_mount_options(*extra_opts);
|
|
+ retry_options = nfs_rewrite_mount_options(*extra_opts, ping);
|
|
if (!retry_options)
|
|
return 0;
|
|
|
|
@@ -547,7 +542,7 @@ static int nfs_try_nfs23mount(struct nfs
|
|
if (mi->fake)
|
|
return 1;
|
|
|
|
- if (nfs_sys_mount(mi, "nfs", *extra_opts))
|
|
+ if (nfs_try_nfs23mount_probe(mi, 0))
|
|
return 1;
|
|
|
|
/*
|
|
@@ -557,7 +552,8 @@ static int nfs_try_nfs23mount(struct nfs
|
|
if (errno != EOPNOTSUPP && errno != EPROTONOSUPPORT)
|
|
return 0;
|
|
|
|
- return nfs_retry_nfs23mount(mi);
|
|
+ /* Probe harder */
|
|
+ return nfs_try_nfs23mount_probe(mi, 1);
|
|
}
|
|
|
|
/*
|