]> git.neil.brown.name Git - nfs-utils.git/commitdiff
Check nfs options (vers/protocol) before trying mount. for-steved
authorNeil Brown <neilb@suse.de>
Mon, 21 Jul 2008 02:45:50 +0000 (12:45 +1000)
committerNeil Brown <neilb@suse.de>
Mon, 21 Jul 2008 02:45:50 +0000 (12:45 +1000)
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
utils/mount/network.h
utils/mount/nfsmount.c
utils/mount/stropts.c

index ff5051229a8d934a3e51edda502a3e02e985e883..e53bd535f514c5d2410205f2e0878adce455c49f 100644 (file)
@@ -500,9 +500,11 @@ static unsigned short getport(struct sockaddr_in *saddr,
  * 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 *server, const unsigned long *versions,
                                                        _("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;
                        }
                }
@@ -567,7 +570,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;
 
@@ -575,12 +578,14 @@ static int probe_nfsport(clnt_addr_t *nfs_server)
                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;
 
@@ -588,9 +593,11 @@ static int probe_mntport(clnt_addr_t *mnt_server)
                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);
 }
 
 /**
@@ -603,7 +610,7 @@ static int probe_mntport(clnt_addr_t *mnt_server)
  *
  * 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;
@@ -625,9 +632,9 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
 
        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));
                }
@@ -645,9 +652,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)
@@ -714,7 +721,7 @@ int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
        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)
index a4dba1b69e3a314a4b544b561e0f7b3ad0aeedfd..6c2013f24c2bb8816395d94567411615cbe2ab34 100644 (file)
@@ -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 *);
index 6355681d4b520eeb3bdeacb26ed81cf797ea33cc..905d61d04f9e67c0993b525ce5c13412f33156aa 100644 (file)
@@ -129,7 +129,7 @@ nfs_call_mount(clnt_addr_t *mnt_server, clnt_addr_t *nfs_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);
index 09fca86d1e1705a72e8a6bfb805a9d861f8fdfb8..767d4818dd42aea672ec64cde5ec30ba98ef8e2d 100644 (file)
@@ -314,7 +314,7 @@ static int nfs_is_permanent_error(int error)
  * 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_mount_options(char *str)
        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_mount_options(char *str)
        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 nfsmount_info *mi, const char *type,
  * '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 nfsmount_info *mi)
        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 nfsmount_info *mi)
        if (errno != EOPNOTSUPP && errno != EPROTONOSUPPORT)
                return 0;
 
-       return nfs_retry_nfs23mount(mi);
+       /* Probe harder */
+       return nfs_try_nfs23mount_probe(mi, 1);
 }
 
 /*