X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;ds=sidebyside;f=utils%2Fmount%2Fstropts.c;h=a8b22ce9a0d14bcd89012360cfac52e7f72913bc;hb=911630538580cdaaee1c37cdf1a8b35b8ed6b23f;hp=4ffee485f0d0c29f42ffd9eddd1f689d0cba3725;hpb=25dd860f13b93109dfd54ef8be0bfd91e4353af1;p=nfs-utils.git diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index 4ffee48..a8b22ce 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -302,11 +302,6 @@ static int nfs_set_version(struct nfsmount_info *mi) if (strncmp(mi->type, "nfs4", 4) == 0) mi->version = 4; - else { - char *option = po_get(mi->options, "proto"); - if (option && strcmp(option, "rdma") == 0) - mi->version = 3; - } /* * If we still don't know, check for version-specific @@ -490,14 +485,19 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options) union nfs_sockaddr mnt_address; struct sockaddr *mnt_saddr = &mnt_address.sa; socklen_t mnt_salen = sizeof(mnt_address); + unsigned long protocol; struct pmap mnt_pmap; char *option; /* - * Skip option negotiation for proto=rdma mounts. + * Version and transport negotiation is not required + * and does not work for RDMA mounts. */ - option = po_get(options, "proto"); - if (option && strcmp(option, "rdma") == 0) + if (!nfs_nfs_protocol(options, &protocol)) { + errno = EINVAL; + return 0; + } + if (protocol == NFSPROTO_RDMA) goto out; /* @@ -538,7 +538,10 @@ nfs_rewrite_pmap_mount_options(struct mount_options *options) if (!nfs_construct_new_options(options, nfs_saddr, &nfs_pmap, mnt_saddr, &mnt_pmap)) { - errno = EINVAL; + if (rpc_createerr.cf_stat == RPC_UNKNOWNPROTO) + errno = EPROTONOSUPPORT; + else + errno = EINVAL; return 0; } @@ -563,10 +566,6 @@ static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts) return 0; } - if (verbose) - printf(_("%s: trying text-based options '%s'\n"), - progname, options); - if (mi->fake) return 1; @@ -580,10 +579,8 @@ static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts) return !result; } -/* - * For "-t nfs vers=2" or "-t nfs vers=3" mounts. - */ -static int nfs_try_mount_v3v2(struct nfsmount_info *mi) +static int nfs_do_mount_v3v2(struct nfsmount_info *mi, + struct sockaddr *sap, socklen_t salen) { struct mount_options *options = po_dup(mi->options); int result = 0; @@ -592,13 +589,21 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi) errno = ENOMEM; return result; } + errno = 0; + if (!nfs_append_addr_option(sap, salen, options)) { + if (errno == 0) + errno = EINVAL; + goto out_fail; + } if (!nfs_fix_mounthost_option(options, mi->hostname)) { - errno = EINVAL; + if (errno == 0) + errno = EINVAL; goto out_fail; } if (!mi->fake && !nfs_verify_lock_option(options)) { - errno = EINVAL; + if (errno == 0) + errno = EINVAL; goto out_fail; } @@ -613,6 +618,10 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi) goto out_fail; } + if (verbose) + printf(_("%s: trying text-based options '%s'\n"), + progname, *mi->extra_opts); + if (!nfs_rewrite_pmap_mount_options(options)) goto out_fail; @@ -624,11 +633,36 @@ out_fail: } /* - * For "-t nfs -o vers=4" or "-t nfs4" mounts. + * Attempt a "-t nfs vers=2" or "-t nfs vers=3" mount. + * + * Returns TRUE if successful, otherwise FALSE. + * "errno" is set to reflect the individual error. */ -static int nfs_try_mount_v4(struct nfsmount_info *mi) +static int nfs_try_mount_v3v2(struct nfsmount_info *mi) +{ + struct addrinfo *ai; + int ret; + + for (ai = mi->address; ai != NULL; ai = ai->ai_next) { + ret = nfs_do_mount_v3v2(mi, ai->ai_addr, ai->ai_addrlen); + if (ret != 0) + return ret; + + switch (errno) { + case ECONNREFUSED: + case EOPNOTSUPP: + case EHOSTUNREACH: + continue; + default: + break; + } + } + return ret; +} + +static int nfs_do_mount_v4(struct nfsmount_info *mi, + struct sockaddr *sap, socklen_t salen) { - struct addrinfo *ai = mi->address; struct mount_options *options = po_dup(mi->options); int result = 0; @@ -656,7 +690,12 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi) } } - if (!nfs_append_clientaddr_option(ai->ai_addr, ai->ai_addrlen, options)) { + if (!nfs_append_addr_option(sap, salen, options)) { + errno = EINVAL; + goto out_fail; + } + + if (!nfs_append_clientaddr_option(sap, salen, options)) { errno = EINVAL; goto out_fail; } @@ -669,6 +708,10 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi) goto out_fail; } + if (verbose) + printf(_("%s: trying text-based options '%s'\n"), + progname, *mi->extra_opts); + result = nfs_sys_mount(mi, options); out_fail: @@ -676,6 +719,33 @@ out_fail: return result; } +/* + * Attempt a "-t nfs -o vers=4" or "-t nfs4" mount. + * + * Returns TRUE if successful, otherwise FALSE. + * "errno" is set to reflect the individual error. + */ +static int nfs_try_mount_v4(struct nfsmount_info *mi) +{ + struct addrinfo *ai; + int ret; + + for (ai = mi->address; ai != NULL; ai = ai->ai_next) { + ret = nfs_do_mount_v4(mi, ai->ai_addr, ai->ai_addrlen); + if (ret != 0) + return ret; + + switch (errno) { + case ECONNREFUSED: + case EHOSTUNREACH: + continue; + default: + break; + } + } + return ret; +} + /* * This is a single pass through the fg/bg loop. * @@ -735,6 +805,7 @@ static int nfs_is_permanent_error(int error) case ESTALE: case ETIMEDOUT: case ECONNREFUSED: + case EHOSTUNREACH: return 0; /* temporary */ default: return 1; /* permanent */