Text-based mounts try a mount operation first with default settings,
then negotiate via rpcbind queries and retry the mount, if the default
settings don't work. This method introduces long delays in certain
common scenarios, and makes it difficult to tell when it is
appropriate to fail immediately or negotiate and retry.
To address these behavioral regressions, make text-based mounts
operate the same way that legacy mounts work. Perform rpcbind queries
with short timeouts first, then use the results to determine
transport, version, and port number settings for the mount.
This allows the mount.nfs command to detect server settings, or
whether negotiation is even possible, quickly. It also makes it
simple to determine when to fail vs. when to retry.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_address;
socklen_t mnt_salen;
struct pmap mnt_pmap;
struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_address;
socklen_t mnt_salen;
struct pmap mnt_pmap;
options = po_split(str);
if (!options) {
options = po_split(str);
if (!options) {
+ /*
+ * Skip option negotiation for proto=rdma mounts.
+ */
+ option = po_get(options, "proto");
+ if (option && strcmp(option, "rdma") == 0)
+ goto out;
+
+ /*
+ * Extract just the options needed to contact server.
+ * Bail now if any of these have bad values.
+ */
if (!nfs_extract_server_addresses(options, nfs_saddr, &nfs_salen,
mnt_saddr, &mnt_salen)) {
errno = EINVAL;
goto err;
}
if (!nfs_extract_server_addresses(options, nfs_saddr, &nfs_salen,
mnt_saddr, &mnt_salen)) {
errno = EINVAL;
goto err;
}
if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap)) {
errno = EINVAL;
goto err;
}
if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap)) {
errno = EINVAL;
goto err;
}
- /* The kernel NFS client doesn't support changing the RPC program
- * number for these services, so reset these fields before probing
- * the server's ports. */
+ /*
+ * The kernel NFS client doesn't support changing the RPC
+ * program number for these services, so force the value of
+ * these fields before probing the server's ports.
+ */
nfs_pmap.pm_prog = NFS_PROGRAM;
mnt_pmap.pm_prog = MOUNTPROG;
nfs_pmap.pm_prog = NFS_PROGRAM;
mnt_pmap.pm_prog = MOUNTPROG;
+ /*
+ * If the server's rpcbind service isn't available, we can't
+ * negotiate. Bail now if we can't contact it.
+ */
if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
nfs_saddr, nfs_salen, &nfs_pmap)) {
errno = ESPIPE;
if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
nfs_saddr, nfs_salen, &nfs_pmap)) {
errno = ESPIPE;
errno = 0;
return options;
errno = 0;
return options;
printf(_("%s: text-based options (retry): '%s'\n"),
progname, retry_str);
printf(_("%s: text-based options (retry): '%s'\n"),
progname, retry_str);
+ if (mi->fake)
+ return 1;
+
if (!nfs_sys_mount(mi, "nfs", retry_str)) {
po_destroy(retry_options);
free(retry_str);
if (!nfs_sys_mount(mi, "nfs", retry_str)) {
po_destroy(retry_options);
free(retry_str);
printf(_("%s: text-based options: '%s'\n"),
progname, *extra_opts);
printf(_("%s: text-based options: '%s'\n"),
progname, *extra_opts);
- if (mi->fake)
- return 1;
-
- if (nfs_sys_mount(mi, "nfs", *extra_opts))
- return 1;
-
- /*
- * The kernel returns EOPNOTSUPP if the RPC bind failed,
- * and EPROTONOSUPPORT if the version isn't supported.
- */
- if (errno != EOPNOTSUPP && errno != EPROTONOSUPPORT)
- return 0;
-
return nfs_retry_nfs23mount(mi);
}
return nfs_retry_nfs23mount(mi);
}