nfs-utils/nfs-utils-1.1.2-try-before-mount.patch

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);
}
/*