X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fmount%2Fstropts.c;h=ceefdb0fc24cecb5a5215db809fbe01fece76251;hp=76bbefd3104eaf10f117461ae8e1f4fcfd0cd545;hb=a8b90e8f64a7d53b20c0980f2a6d9a8d5945bcc4;hpb=3faa54e8a17411de28c7b707207d49b4466ae873 diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index 76bbefd..ceefdb0 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -45,6 +45,7 @@ #include "parse_opt.h" #include "version.h" #include "parse_dev.h" +#include "conffile.h" #ifndef NFS_PROGRAM #define NFS_PROGRAM (100003) @@ -259,7 +260,7 @@ static int nfs_append_sloppy_option(struct mount_options *options) } /* - * Set up mandatory NFS mount options. + * Set up mandatory non-version specific NFS mount options. * * Returns 1 if successful; otherwise zero. */ @@ -278,15 +279,18 @@ static int nfs_validate_options(struct nfsmount_info *mi) return 0; if (strncmp(mi->type, "nfs4", 4) == 0) mi->version = 4; - - if (mi->version == 4) { - if (!nfs_append_clientaddr_option(sap, mi->salen, mi->options)) - return 0; - } else { - if (!nfs_fix_mounthost_option(mi->options)) - return 0; - if (!mi->fake && !nfs_verify_lock_option(mi->options)) - return 0; + else { + char *option = po_get(mi->options, "proto"); + if (option && strcmp(option, "rdma") == 0) + mi->version = 3; + } + /* + * Use the default value set in the config file when + * the version has not been explicitly set. + */ + if (mi->version == 0 && config_default_vers) { + if (config_default_vers < 4) + mi->version = config_default_vers; } if (!nfs_append_sloppy_option(mi->options)) @@ -295,12 +299,6 @@ static int nfs_validate_options(struct nfsmount_info *mi) if (!nfs_append_addr_option(sap, mi->salen, mi->options)) return 0; - /* - * Update option string to be recorded in /etc/mnttab - */ - if (po_join(mi->options, mi->extra_opts) == PO_FAILED) - return 0; - return 1; } @@ -490,17 +488,12 @@ out: * Returns TRUE if successful, otherwise FALSE. * "errno" is set to reflect the individual error. */ -static int nfs_try_mount(struct nfsmount_info *mi) +static int nfs_sys_mount(struct nfsmount_info *mi, struct mount_options *opts) { char *options = NULL; int result; - if (mi->version != 4) { - if (!nfs_rewrite_pmap_mount_options(mi->options)) - return 0; - } - - if (po_join(mi->options, &options) == PO_FAILED) { + if (po_join(opts, &options) == PO_FAILED) { errno = EIO; return 0; } @@ -522,6 +515,121 @@ static int nfs_try_mount(struct nfsmount_info *mi) return !result; } +/* + * For "-t nfs vers=2" or "-t nfs vers=3" mounts. + */ +static int nfs_try_mount_v3v2(struct nfsmount_info *mi) +{ + struct mount_options *options = po_dup(mi->options); + int result = 0; + + if (!options) { + errno = ENOMEM; + return result; + } + + if (!nfs_fix_mounthost_option(options)) { + errno = EINVAL; + goto out_fail; + } + if (!mi->fake && !nfs_verify_lock_option(options)) { + errno = EINVAL; + goto out_fail; + } + + /* + * Options we negotiate below may be stale by the time this + * file system is unmounted. In order to force umount.nfs + * to renegotiate with the server, only write the user- + * specified options, and not negotiated options, to /etc/mtab. + */ + if (po_join(options, mi->extra_opts) == PO_FAILED) { + errno = ENOMEM; + goto out_fail; + } + + if (!nfs_rewrite_pmap_mount_options(options)) + goto out_fail; + + result = nfs_sys_mount(mi, options); + +out_fail: + po_destroy(options); + return result; +} + +/* + * For "-t nfs -o vers=4" or "-t nfs4" mounts. + */ +static int nfs_try_mount_v4(struct nfsmount_info *mi) +{ + struct sockaddr *sap = (struct sockaddr *)&mi->address; + struct mount_options *options = po_dup(mi->options); + int result = 0; + + if (!options) { + errno = ENOMEM; + return result; + } + + if (mi->version == 0) { + if (po_append(options, "vers=4") == PO_FAILED) { + errno = EINVAL; + goto out_fail; + } + } + + if (!nfs_append_clientaddr_option(sap, mi->salen, options)) { + errno = EINVAL; + goto out_fail; + } + /* + * Update option string to be recorded in /etc/mtab. + */ + if (po_join(options, mi->extra_opts) == PO_FAILED) { + errno = ENOMEM; + return 0; + } + + result = nfs_sys_mount(mi, options); + +out_fail: + po_destroy(options); + return result; +} + +/* + * This is a single pass through the fg/bg loop. + * + * Returns TRUE if successful, otherwise FALSE. + * "errno" is set to reflect the individual error. + */ +static int nfs_try_mount(struct nfsmount_info *mi) +{ + int result = 0; + + switch (mi->version) { + case 0: + if (linux_version_code() > MAKE_VERSION(2, 6, 31)) { + errno = 0; + result = nfs_try_mount_v4(mi); + if (errno != EPROTONOSUPPORT) + break; + } + case 2: + case 3: + result = nfs_try_mount_v3v2(mi); + break; + case 4: + result = nfs_try_mount_v4(mi); + break; + default: + errno = EIO; + } + + return result; +} + /* * Distinguish between permanent and temporary errors. *