diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2007-10-10 15:06:33 -0400 |
---|---|---|
committer | Neil Brown <neilb@suse.de> | 2007-10-11 11:03:18 +1000 |
commit | 5258d6c1aa4fd319976d1b13e27493adb57a4120 (patch) | |
tree | ac5aa71a154950abfeb78f85b4e1726c737216d2 | |
parent | 36f52a8946387d05f307b5c4c8364d00155ae186 (diff) | |
download | nfs-utils-5258d6c1aa4fd319976d1b13e27493adb57a4120.tar.gz nfs-utils-5258d6c1aa4fd319976d1b13e27493adb57a4120.tar.xz nfs-utils-5258d6c1aa4fd319976d1b13e27493adb57a4120.zip |
text-based mount.nfs: Add rewrite_mount_options() function
Introduce a function for probing the server for what it supports, and then
rewriting the mount options using the probe results.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Neil Brown <neilb@suse.de>
-rw-r--r-- | utils/mount/stropts.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c index c048be0..fcc5b98 100644 --- a/utils/mount/stropts.c +++ b/utils/mount/stropts.c @@ -238,6 +238,136 @@ static int set_mandatory_options(const char *type, } /* + * Reconstruct the mount option string based on a portmapper probe + * of the server. Returns one if the server's portmapper returned + * something we can use, otherwise zero. + * + * To handle version and transport protocol fallback properly, we + * need to parse some of the mount options in order to set up a + * portmap probe. Mount options that rewrite_mount_options() + * doesn't recognize are left alone. + * + * Returns a new group of mount options if successful; otherwise + * NULL is returned if some failure occurred. + */ +static struct mount_options *rewrite_mount_options(char *str) +{ + struct mount_options *options; + char *option, new_option[64]; + clnt_addr_t mnt_server = { }; + clnt_addr_t nfs_server = { }; + int p; + + options = po_split(str); + if (!options) + return NULL; + + option = po_get(options, "addr"); + if (option) { + nfs_server.saddr.sin_family = AF_INET; + if (!inet_aton((const char *)option, &nfs_server.saddr.sin_addr)) + goto err; + } else + goto err; + + option = po_get(options, "mountaddr"); + if (option) { + mnt_server.saddr.sin_family = AF_INET; + if (!inet_aton((const char *)option, &mnt_server.saddr.sin_addr)) + goto err; + } else + memcpy(&mnt_server.saddr, &nfs_server.saddr, + sizeof(mnt_server.saddr)); + + option = po_get(options, "mountport"); + if (option) + mnt_server.pmap.pm_port = atoi(option); + mnt_server.pmap.pm_prog = MOUNTPROG; + option = po_get(options, "mountprog"); + if (option) + mnt_server.pmap.pm_prog = atoi(option); + option = po_get(options, "mountvers"); + if (option) + mnt_server.pmap.pm_vers = atoi(option); + + option = po_get(options, "port"); + if (option) { + nfs_server.pmap.pm_port = atoi(option); + po_remove_all(options, "port"); + } + nfs_server.pmap.pm_prog = NFS_PROGRAM; + option = po_get(options, "nfsprog"); + if (option) + nfs_server.pmap.pm_prog = atoi(option); + + option = po_get(options, "nfsvers"); + if (option) { + nfs_server.pmap.pm_vers = atoi(option); + po_remove_all(options, "nfsvers"); + } + option = po_get(options, "vers"); + if (option) { + nfs_server.pmap.pm_vers = atoi(option); + po_remove_all(options, "vers"); + } + option = po_get(options, "proto"); + if (option) { + if (strcmp(option, "tcp") == 0) { + nfs_server.pmap.pm_prot = IPPROTO_TCP; + po_remove_all(options, "proto"); + } + if (strcmp(option, "udp") == 0) { + nfs_server.pmap.pm_prot = IPPROTO_UDP; + po_remove_all(options, "proto"); + } + } + p = po_rightmost(options, "tcp", "udp"); + switch (p) { + case PO_KEY2_RIGHTMOST: + nfs_server.pmap.pm_prot = IPPROTO_UDP; + break; + case PO_KEY1_RIGHTMOST: + nfs_server.pmap.pm_prot = IPPROTO_TCP; + break; + } + po_remove_all(options, "tcp"); + po_remove_all(options, "udp"); + + if (!probe_bothports(&mnt_server, &nfs_server)) { + rpc_mount_errors("rpcbind", 0, 0); + goto err; + } + + snprintf(new_option, sizeof(new_option) - 1, + "nfsvers=%lu", nfs_server.pmap.pm_vers); + if (po_append(options, new_option) == PO_FAILED) + goto err; + + if (nfs_server.pmap.pm_prot == IPPROTO_TCP) + snprintf(new_option, sizeof(new_option) - 1, + "proto=tcp"); + else + snprintf(new_option, sizeof(new_option) - 1, + "proto=udp"); + if (po_append(options, new_option) == PO_FAILED) + goto err; + + if (nfs_server.pmap.pm_port != NFS_PORT) { + snprintf(new_option, sizeof(new_option) - 1, + "port=%lu", nfs_server.pmap.pm_port); + if (po_append(options, new_option) == PO_FAILED) + goto err; + + } + + return options; + +err: + po_destroy(options); + return NULL; +} + +/* * Attempt an NFSv2/3 mount via a mount(2) system call. * * Returns 1 if successful. Otherwise, returns zero. |