* [PATCH 0/5] struct pmap stuffing
@ 2009-01-08 17:32 Chuck Lever
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
0 siblings, 1 reply; 7+ messages in thread
From: Chuck Lever @ 2009-01-08 17:32 UTC (permalink / raw)
To: steved; +Cc: linux-nfs
Hi Steve-
Happy New Year. Continuing with the IPv6 patch series for the NFS
mount command, I bring you five more patches.
These introduce a new facility for converting a set of NFS mount
options into a properly filled-in struct pmap, ripe for passing into
everyday existing functions like nfs_getport().
The final patches in today's set use this new facility to correct a
number of problems with the text-based mount command's NFS version
detection and fallback logic.
The next set of patches will use this new facility to bring IPv6
support to umount.nfs.
If you have some unit tests for mount.nfs handling version fallback
and/or operating in an environment that does not have an accessible
portmapper on the server, please try them with this series applied.
---
Chuck Lever (5):
text-based mount command: support AF_INET6 in rewrite_mount_options()
text-based mount command: fix mount option rewriting logic
text-based mount options: Use new pmap stuffer when rewriting mount options
text-based mount command: Function to stuff "struct pmap" from mount options
text-based mount command: make po_rightmost() work for N options
utils/mount/network.c | 214 ++++++++++++++++++++++++++++++++++++++++
utils/mount/network.h | 5 +
utils/mount/parse_opt.c | 28 +++--
utils/mount/parse_opt.h | 9 --
utils/mount/stropts.c | 253 ++++++++++++++++++++++++++---------------------
5 files changed, 378 insertions(+), 131 deletions(-)
--
Chuck Lever <chuck.lever@oracle.com>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/5] text-based mount command: make po_rightmost() work for N options
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
@ 2009-01-08 17:32 ` Chuck Lever
2009-01-08 17:32 ` [PATCH 2/5] text-based mount command: Function to stuff "struct pmap" from mount options Chuck Lever
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chuck Lever @ 2009-01-08 17:32 UTC (permalink / raw)
To: steved; +Cc: linux-nfs
Sometimes we need to choose the rightmost option among multiple
different mount options. For example, we want to find the rightmost
of "proto," "tcp," and "udp". Or, the rightmost of "vers," "nfsvers,"
"v2," and "v3".
Update po_rightmost() to choose among N options instead of just two.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
utils/mount/parse_opt.c | 28 ++++++++++++++++------------
utils/mount/parse_opt.h | 9 ++-------
utils/mount/stropts.c | 28 +++++++++++++++++++++++-----
3 files changed, 41 insertions(+), 24 deletions(-)
diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
index f61d0dd..4934508 100644
--- a/utils/mount/parse_opt.c
+++ b/utils/mount/parse_opt.c
@@ -421,34 +421,38 @@ po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *va
#endif /* HAVE_STRTOL */
/**
- * po_rightmost - determine the relative position of two options
+ * po_rightmost - determine the relative position of several options
* @options: pointer to mount options
- * @key1: pointer to a C string containing an option keyword
- * @key2: pointer to a C string containing another option keyword
+ * @keys: pointer to an array of C strings containing option keywords
+ *
+ * This function can be used to determine which of several similar
+ * options will be the one to take effect.
*
* The kernel parses the mount option string from left to right.
* If an option is specified more than once (for example, "intr"
* and "nointr", the rightmost option is the last to be parsed,
* and it therefore takes precedence over previous similar options.
*
- * This function can be used to determine which of two similar
- * options will be the one to take effect.
+ * This can also distinguish among multiple synonymous options, such
+ * as "proto=," "udp" and "tcp."
+ *
+ * Returns the index into @keys of the option that is rightmost.
+ * If none of the options are present, returns zero.
*/
-po_rightmost_t po_rightmost(struct mount_options *options,
- char *key1, char *key2)
+unsigned int po_rightmost(struct mount_options *options, const char *keys[])
{
struct mount_option *option;
+ unsigned int i;
if (options) {
for (option = options->tail; option; option = option->prev) {
- if (key2 && strcmp(option->keyword, key2) == 0)
- return PO_KEY2_RIGHTMOST;
- if (key1 && strcmp(option->keyword, key1) == 0)
- return PO_KEY1_RIGHTMOST;
+ for (i = 0; keys[i] != NULL; i++)
+ if (strcmp(option->keyword, keys[i]) == 0)
+ return i;
}
}
- return PO_NEITHER_FOUND;
+ return 0;
}
/**
diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
index 199630f..e132b1c 100644
--- a/utils/mount/parse_opt.h
+++ b/utils/mount/parse_opt.h
@@ -35,12 +35,6 @@ typedef enum {
PO_BAD_VALUE = 2,
} po_found_t;
-typedef enum {
- PO_KEY1_RIGHTMOST = -1,
- PO_NEITHER_FOUND = 0,
- PO_KEY2_RIGHTMOST = 1,
-} po_rightmost_t;
-
struct mount_options;
struct mount_options * po_split(char *);
@@ -53,7 +47,8 @@ po_found_t po_contains(struct mount_options *, char *);
char * po_get(struct mount_options *, char *);
po_found_t po_get_numeric(struct mount_options *,
char *, long *);
-po_rightmost_t po_rightmost(struct mount_options *, char *, char *);
+unsigned int po_rightmost(struct mount_options *,
+ const char *keys[]);
po_found_t po_remove_all(struct mount_options *, char *);
void po_destroy(struct mount_options *);
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 43791e6..bd127ab 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -224,9 +224,15 @@ static int nfs_fix_mounthost_option(const sa_family_t family,
* Returns zero if the "lock" option is in effect, but statd
* can't be started. Otherwise, returns 1.
*/
+static const char *nfs_lock_opttbl[] = {
+ "nolock",
+ "lock",
+ NULL,
+};
+
static int nfs_verify_lock_option(struct mount_options *options)
{
- if (po_rightmost(options, "nolock", "lock") == PO_KEY1_RIGHTMOST)
+ if (po_rightmost(options, nfs_lock_opttbl) == 1)
return 1;
if (!start_statd()) {
@@ -316,6 +322,12 @@ 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 const char *nfs_transport_opttbl[] = {
+ "udp",
+ "tcp",
+ NULL,
+};
+
static struct mount_options *nfs_rewrite_mount_options(char *str)
{
struct mount_options *options;
@@ -395,12 +407,12 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
po_remove_all(options, "proto");
}
}
- p = po_rightmost(options, "tcp", "udp");
+ p = po_rightmost(options, nfs_transport_opttbl);
switch (p) {
- case PO_KEY2_RIGHTMOST:
+ case 1:
nfs_server.pmap.pm_prot = IPPROTO_UDP;
break;
- case PO_KEY1_RIGHTMOST:
+ case 2:
nfs_server.pmap.pm_prot = IPPROTO_TCP;
break;
}
@@ -722,12 +734,18 @@ static int nfsmount_bg(struct nfsmount_info *mi)
*
* Returns a valid mount command exit code.
*/
+static const char *nfs_background_opttbl[] = {
+ "bg",
+ "fg",
+ NULL,
+};
+
static int nfsmount_start(struct nfsmount_info *mi)
{
if (!nfs_validate_options(mi))
return EX_FAIL;
- if (po_rightmost(mi->options, "bg", "fg") == PO_KEY1_RIGHTMOST)
+ if (po_rightmost(mi->options, nfs_background_opttbl) == 1)
return nfsmount_bg(mi);
else
return nfsmount_fg(mi);
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] text-based mount command: Function to stuff "struct pmap" from mount options
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-01-08 17:32 ` [PATCH 1/5] text-based mount command: make po_rightmost() work for N options Chuck Lever
@ 2009-01-08 17:32 ` Chuck Lever
2009-01-08 17:32 ` [PATCH 3/5] text-based mount options: Use new pmap stuffer when rewriting " Chuck Lever
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chuck Lever @ 2009-01-08 17:32 UTC (permalink / raw)
To: steved; +Cc: linux-nfs
Both the text-based mount.nfs command and the umount.nfs command need
to fill in a pmap structure based on string mount options. Introduce
a shared function that can do this.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
utils/mount/network.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++
utils/mount/network.h | 5 +
2 files changed, 219 insertions(+), 0 deletions(-)
diff --git a/utils/mount/network.c b/utils/mount/network.c
index d262e94..91a005c 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -48,6 +48,7 @@
#include "nfs_mount.h"
#include "mount_constants.h"
#include "nfsrpc.h"
+#include "parse_opt.h"
#include "network.h"
#define PMAP_TIMEOUT (10)
@@ -67,6 +68,33 @@ static const char *nfs_ns_pgmtbl[] = {
NULL,
};
+static const char *nfs_mnt_pgmtbl[] = {
+ "mount",
+ "mountd",
+ NULL,
+};
+
+static const char *nfs_nfs_pgmtbl[] = {
+ "nfs",
+ "nfsprog",
+ NULL,
+};
+
+static const char *nfs_transport_opttbl[] = {
+ "udp",
+ "tcp",
+ "proto",
+ NULL,
+};
+
+static const char *nfs_version_opttbl[] = {
+ "v2",
+ "v3",
+ "vers",
+ "nfsvers",
+ NULL,
+};
+
static const unsigned long nfs_to_mnt[] = {
0,
0,
@@ -1111,3 +1139,189 @@ out_failed:
return 0;
}
+
+/*
+ * "nfsprog" is only supported by the legacy mount command. The
+ * kernel mount client does not support this option.
+ *
+ * Returns the value set by the nfsprog= option, the value of
+ * the RPC NFS program specified in /etc/rpc, or a baked-in
+ * default program number, if all fails.
+ */
+static rpcprog_t nfs_nfs_program(struct mount_options *options)
+{
+ long tmp;
+
+ if (po_get_numeric(options, "nfsprog", &tmp) == PO_FOUND)
+ if (tmp >= 0)
+ return tmp;
+ return nfs_getrpcbyname(NFSPROG, nfs_nfs_pgmtbl);
+}
+
+
+/*
+ * Returns the RPC version number specified by the given mount
+ * options for the NFS service, or zero if all fails.
+ */
+static rpcvers_t nfs_nfs_version(struct mount_options *options)
+{
+ long tmp;
+
+ switch (po_rightmost(options, nfs_version_opttbl)) {
+ case 1: /* v2 */
+ return 2;
+ case 2: /* v3 */
+ return 3;
+ case 3: /* vers */
+ if (po_get_numeric(options, "vers", &tmp) == PO_FOUND)
+ if (tmp >= 2 && tmp <= 3)
+ return tmp;
+ break;
+ case 4: /* nfsvers */
+ if (po_get_numeric(options, "nfsvers", &tmp) == PO_FOUND)
+ if (tmp >= 2 && tmp <= 3)
+ return tmp;
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * Returns the NFS transport protocol specified by the given mount options
+ *
+ * Returns the IPPROTO_ value specified by the given mount options, or
+ * IPPROTO_UDP if all fails.
+ */
+static unsigned short nfs_nfs_protocol(struct mount_options *options)
+{
+ char *option;
+
+ switch (po_rightmost(options, nfs_transport_opttbl)) {
+ case 1: /* udp */
+ return IPPROTO_UDP;
+ case 2: /* tcp */
+ return IPPROTO_TCP;
+ case 3: /* proto */
+ option = po_get(options, "proto");
+ if (option) {
+ if (strcmp(option, "tcp") == 0)
+ return IPPROTO_TCP;
+ if (strcmp(option, "udp") == 0)
+ return IPPROTO_UDP;
+ }
+ }
+ return IPPROTO_UDP;
+}
+
+/*
+ * Returns the NFS server's port number specified by the given
+ * mount options, or zero if all fails. Zero results in a portmap
+ * query to discover the server's mountd service port.
+ *
+ * port=0 will guarantee an rpcbind request precedes the first
+ * NFS RPC so the client can determine the server's port number.
+ */
+static unsigned short nfs_nfs_port(struct mount_options *options)
+{
+ long tmp;
+
+ if (po_get_numeric(options, "port", &tmp) == PO_FOUND)
+ if (tmp >= 0 && tmp <= 65535)
+ return tmp;
+ return 0;
+}
+
+/*
+ * "mountprog" is only supported by the legacy mount command. The
+ * kernel mount client does not support this option.
+ *
+ * Returns the value set by the mountprog= option, the value of
+ * the RPC mount program specified in /etc/rpc, or a baked-in
+ * default program number, if all fails.
+ */
+static rpcprog_t nfs_mount_program(struct mount_options *options)
+{
+ long tmp;
+
+ if (po_get_numeric(options, "mountprog", &tmp) == PO_FOUND)
+ if (tmp >= 0)
+ return tmp;
+ return nfs_getrpcbyname(MOUNTPROG, nfs_mnt_pgmtbl);
+}
+
+/*
+ * Returns the RPC version number specified by the given mount options,
+ * or the version "3" if all fails.
+ */
+static rpcvers_t nfs_mount_version(struct mount_options *options)
+{
+ long tmp;
+
+ if (po_get_numeric(options, "mountvers", &tmp) == PO_FOUND)
+ if (tmp >= 1 && tmp <= 4)
+ return tmp;
+
+ return nfsvers_to_mnt(nfs_nfs_version(options));
+}
+
+/*
+ * Returns the transport protocol to use for the mount service
+ *
+ * Returns the IPPROTO_ value specified by the mountproto option, or
+ * if that doesn't exist, the IPPROTO_ value specified for NFS
+ * itself.
+ */
+static unsigned short nfs_mount_protocol(struct mount_options *options)
+{
+ char *option;
+
+ option = po_get(options, "mountproto");
+ if (option) {
+ if (strcmp(option, "tcp") == 0)
+ return IPPROTO_TCP;
+ if (strcmp(option, "udp") == 0)
+ return IPPROTO_UDP;
+ }
+
+ return nfs_nfs_version(options);
+}
+
+/*
+ * Returns the mountd server's port number specified by the given
+ * mount options, or zero if all fails. Zero results in a portmap
+ * query to discover the server's mountd service port.
+ *
+ * port=0 will guarantee an rpcbind request precedes the mount
+ * RPC so the client can determine the server's port number.
+ */
+static unsigned short nfs_mount_port(struct mount_options *options)
+{
+ long tmp;
+
+ if (po_get_numeric(options, "mountport", &tmp) == PO_FOUND)
+ if (tmp >= 0 && tmp <= 65535)
+ return tmp;
+ return 0;
+}
+
+/**
+ * nfs_options2pmap - set up pmap structs based on mount options
+ * @options: pointer to mount options
+ * @nfs_pmap: OUT: pointer to pmap arguments for NFS server
+ * @mnt_pmap: OUT: pointer to pmap arguments for mountd server
+ *
+ */
+void nfs_options2pmap(struct mount_options *options,
+ struct pmap *nfs_pmap, struct pmap *mnt_pmap)
+{
+ nfs_pmap->pm_prog = nfs_nfs_program(options);
+ nfs_pmap->pm_vers = nfs_nfs_version(options);
+ nfs_pmap->pm_prot = nfs_nfs_protocol(options);
+ nfs_pmap->pm_port = nfs_nfs_port(options);
+
+ mnt_pmap->pm_prog = nfs_mount_program(options);
+ mnt_pmap->pm_vers = nfs_mount_version(options);
+ mnt_pmap->pm_prot = nfs_mount_protocol(options);
+ mnt_pmap->pm_port = nfs_mount_port(options);
+}
diff --git a/utils/mount/network.h b/utils/mount/network.h
index 075093d..25060ab 100644
--- a/utils/mount/network.h
+++ b/utils/mount/network.h
@@ -57,6 +57,11 @@ int clnt_ping(struct sockaddr_in *, const unsigned long,
const unsigned long, const unsigned int,
struct sockaddr_in *);
+struct mount_options;
+
+void nfs_options2pmap(struct mount_options *,
+ struct pmap *, struct pmap *);
+
int start_statd(void);
unsigned long nfsvers_to_mnt(const unsigned long);
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] text-based mount options: Use new pmap stuffer when rewriting mount options
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-01-08 17:32 ` [PATCH 1/5] text-based mount command: make po_rightmost() work for N options Chuck Lever
2009-01-08 17:32 ` [PATCH 2/5] text-based mount command: Function to stuff "struct pmap" from mount options Chuck Lever
@ 2009-01-08 17:32 ` Chuck Lever
2009-01-08 17:32 ` [PATCH 4/5] text-based mount command: fix mount option rewriting logic Chuck Lever
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Chuck Lever @ 2009-01-08 17:32 UTC (permalink / raw)
To: steved; +Cc: linux-nfs
Call nfs_options2pmap() in nfs_rewrite_mount_options() instead of
open-coding the logic to convert mount options to a pmap struct.
The new nfs_options2pmap() function is more careful about avoiding
invalid mount option values, and handles multiply-specified transport
protocol options correctly.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
utils/mount/stropts.c | 68 ++++---------------------------------------------
1 files changed, 5 insertions(+), 63 deletions(-)
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index bd127ab..99be0f3 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -322,19 +322,12 @@ 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 const char *nfs_transport_opttbl[] = {
- "udp",
- "tcp",
- NULL,
-};
-
static struct mount_options *nfs_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) {
@@ -360,64 +353,13 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
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, "mountvers");
- if (option)
- mnt_server.pmap.pm_vers = atoi(option);
- option = po_get(options, "mountproto");
- if (option) {
- if (strcmp(option, "tcp") == 0) {
- mnt_server.pmap.pm_prot = IPPROTO_TCP;
- po_remove_all(options, "mountproto");
- }
- if (strcmp(option, "udp") == 0) {
- mnt_server.pmap.pm_prot = IPPROTO_UDP;
- po_remove_all(options, "mountproto");
- }
- }
+ nfs_options2pmap(options, &nfs_server.pmap, &mnt_server.pmap);
- option = po_get(options, "port");
- if (option) {
- nfs_server.pmap.pm_port = atoi(option);
- po_remove_all(options, "port");
- }
+ /* 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. */
nfs_server.pmap.pm_prog = NFS_PROGRAM;
-
- 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, nfs_transport_opttbl);
- switch (p) {
- case 1:
- nfs_server.pmap.pm_prot = IPPROTO_UDP;
- break;
- case 2:
- nfs_server.pmap.pm_prot = IPPROTO_TCP;
- break;
- }
- po_remove_all(options, "tcp");
- po_remove_all(options, "udp");
+ mnt_server.pmap.pm_prog = MOUNTPROG;
if (!probe_bothports(&mnt_server, &nfs_server)) {
errno = ESPIPE;
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] text-based mount command: fix mount option rewriting logic
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (2 preceding siblings ...)
2009-01-08 17:32 ` [PATCH 3/5] text-based mount options: Use new pmap stuffer when rewriting " Chuck Lever
@ 2009-01-08 17:32 ` Chuck Lever
2009-01-08 17:33 ` [PATCH 5/5] text-based mount command: support AF_INET6 in rewrite_mount_options() Chuck Lever
2009-01-27 23:02 ` [PATCH 0/5] struct pmap stuffing Steve Dickson
5 siblings, 0 replies; 7+ messages in thread
From: Chuck Lever @ 2009-01-08 17:32 UTC (permalink / raw)
To: steved; +Cc: linux-nfs
Fix a bunch of corner cases in the text-based mount option rewriting logic.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
utils/mount/stropts.c | 113 ++++++++++++++++++++++++++++++++++---------------
1 files changed, 79 insertions(+), 34 deletions(-)
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 99be0f3..319be71 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -309,6 +309,81 @@ static int nfs_is_permanent_error(int error)
}
}
+static int nfs_construct_new_options(struct mount_options *options,
+ struct pmap *nfs_pmap,
+ struct pmap *mnt_pmap)
+{
+ char new_option[64];
+
+ po_remove_all(options, "nfsprog");
+ po_remove_all(options, "mountprog");
+
+ po_remove_all(options, "v2");
+ po_remove_all(options, "v3");
+ po_remove_all(options, "vers");
+ po_remove_all(options, "nfsvers");
+ snprintf(new_option, sizeof(new_option) - 1,
+ "vers=%lu", nfs_pmap->pm_vers);
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+
+ po_remove_all(options, "proto");
+ po_remove_all(options, "udp");
+ po_remove_all(options, "tcp");
+ switch (nfs_pmap->pm_prot) {
+ case IPPROTO_TCP:
+ snprintf(new_option, sizeof(new_option) - 1,
+ "proto=tcp");
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+ break;
+ case IPPROTO_UDP:
+ snprintf(new_option, sizeof(new_option) - 1,
+ "proto=udp");
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+ break;
+ }
+
+ po_remove_all(options, "port");
+ if (nfs_pmap->pm_port != NFS_PORT) {
+ snprintf(new_option, sizeof(new_option) - 1,
+ "port=%lu", nfs_pmap->pm_port);
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+ }
+
+ po_remove_all(options, "mountvers");
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountvers=%lu", mnt_pmap->pm_vers);
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+
+ po_remove_all(options, "mountproto");
+ switch (mnt_pmap->pm_prot) {
+ case IPPROTO_TCP:
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountproto=tcp");
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+ break;
+ case IPPROTO_UDP:
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountproto=udp");
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+ break;
+ }
+
+ po_remove_all(options, "mountport");
+ snprintf(new_option, sizeof(new_option) - 1,
+ "mountport=%lu", mnt_pmap->pm_port);
+ if (po_append(options, new_option) == PO_FAILED)
+ return 0;
+
+ return 1;
+}
+
/*
* Reconstruct the mount option string based on a portmapper probe
* of the server. Returns one if the server's portmapper returned
@@ -325,7 +400,7 @@ static int nfs_is_permanent_error(int error)
static struct mount_options *nfs_rewrite_mount_options(char *str)
{
struct mount_options *options;
- char *option, new_option[64];
+ char *option;
clnt_addr_t mnt_server = { };
clnt_addr_t nfs_server = { };
@@ -366,42 +441,12 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
goto err;
}
- snprintf(new_option, sizeof(new_option) - 1,
- "nfsvers=%lu", nfs_server.pmap.pm_vers);
- if (po_append(options, new_option) == PO_FAILED)
+ if (!nfs_construct_new_options(options,
+ &nfs_server.pmap, &mnt_server.pmap)) {
+ errno = EINVAL;
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;
-
}
- if (mnt_server.pmap.pm_prot == IPPROTO_TCP)
- snprintf(new_option, sizeof(new_option) - 1,
- "mountproto=tcp");
- else
- snprintf(new_option, sizeof(new_option) - 1,
- "mountproto=udp");
- 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;
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] text-based mount command: support AF_INET6 in rewrite_mount_options()
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (3 preceding siblings ...)
2009-01-08 17:32 ` [PATCH 4/5] text-based mount command: fix mount option rewriting logic Chuck Lever
@ 2009-01-08 17:33 ` Chuck Lever
2009-01-27 23:02 ` [PATCH 0/5] struct pmap stuffing Steve Dickson
5 siblings, 0 replies; 7+ messages in thread
From: Chuck Lever @ 2009-01-08 17:33 UTC (permalink / raw)
To: steved; +Cc: linux-nfs
Now that we have an AF_INET6-capable probe_bothports(), we can support
AF_INET6 when rewriting text-based NFS mount options. This should be
adequate to support NFS transport protocol and version negotiation with
AF_INET6 NFS servers.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
utils/mount/stropts.c | 74 ++++++++++++++++++++++++++++++++-----------------
1 files changed, 49 insertions(+), 25 deletions(-)
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 319be71..6d44bb7 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -309,6 +309,37 @@ static int nfs_is_permanent_error(int error)
}
}
+/*
+ * Get NFS/mnt server addresses from mount options
+ *
+ * Returns 1 and fills in @nfs_saddr, @nfs_salen, @mnt_saddr, and @mnt_salen
+ * if all goes well; otherwise zero.
+ */
+static int nfs_extract_server_addresses(struct mount_options *options,
+ struct sockaddr *nfs_saddr,
+ socklen_t *nfs_salen,
+ struct sockaddr *mnt_saddr,
+ socklen_t *mnt_salen)
+{
+ char *option;
+
+ option = po_get(options, "addr");
+ if (option == NULL)
+ return 0;
+ if (!nfs_string_to_sockaddr(option, strlen(option),
+ nfs_saddr, nfs_salen))
+ return 0;
+
+ option = po_get(options, "mountaddr");
+ if (option == NULL)
+ memcpy(mnt_saddr, nfs_saddr, *nfs_salen);
+ else if (!nfs_string_to_sockaddr(option, strlen(option),
+ mnt_saddr, mnt_salen))
+ return 0;
+
+ return 1;
+}
+
static int nfs_construct_new_options(struct mount_options *options,
struct pmap *nfs_pmap,
struct pmap *mnt_pmap)
@@ -400,9 +431,14 @@ static int nfs_construct_new_options(struct mount_options *options,
static struct mount_options *nfs_rewrite_mount_options(char *str)
{
struct mount_options *options;
- char *option;
- clnt_addr_t mnt_server = { };
- clnt_addr_t nfs_server = { };
+ struct sockaddr_storage nfs_address;
+ struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_address;
+ socklen_t nfs_salen;
+ struct pmap nfs_pmap;
+ struct sockaddr_storage mnt_address;
+ struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_address;
+ socklen_t mnt_salen;
+ struct pmap mnt_pmap;
options = po_split(str);
if (!options) {
@@ -410,39 +446,27 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
return NULL;
}
- errno = EINVAL;
- 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
+ if (!nfs_extract_server_addresses(options, nfs_saddr, &nfs_salen,
+ mnt_saddr, &mnt_salen)) {
+ errno = EINVAL;
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));
-
- nfs_options2pmap(options, &nfs_server.pmap, &mnt_server.pmap);
+ nfs_options2pmap(options, &nfs_pmap, &mnt_pmap);
/* 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. */
- nfs_server.pmap.pm_prog = NFS_PROGRAM;
- mnt_server.pmap.pm_prog = MOUNTPROG;
+ nfs_pmap.pm_prog = NFS_PROGRAM;
+ mnt_pmap.pm_prog = MOUNTPROG;
- if (!probe_bothports(&mnt_server, &nfs_server)) {
+ if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
+ nfs_saddr, nfs_salen, &nfs_pmap)) {
errno = ESPIPE;
goto err;
}
- if (!nfs_construct_new_options(options,
- &nfs_server.pmap, &mnt_server.pmap)) {
+ if (!nfs_construct_new_options(options, &nfs_pmap, &mnt_pmap)) {
errno = EINVAL;
goto err;
}
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 0/5] struct pmap stuffing
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
` (4 preceding siblings ...)
2009-01-08 17:33 ` [PATCH 5/5] text-based mount command: support AF_INET6 in rewrite_mount_options() Chuck Lever
@ 2009-01-27 23:02 ` Steve Dickson
5 siblings, 0 replies; 7+ messages in thread
From: Steve Dickson @ 2009-01-27 23:02 UTC (permalink / raw)
To: Chuck Lever; +Cc: linux-nfs
Chuck Lever wrote:
> Hi Steve-
>
> Happy New Year. Continuing with the IPv6 patch series for the NFS
> mount command, I bring you five more patches.
>
> These introduce a new facility for converting a set of NFS mount
> options into a properly filled-in struct pmap, ripe for passing into
> everyday existing functions like nfs_getport().
>
> The final patches in today's set use this new facility to correct a
> number of problems with the text-based mount command's NFS version
> detection and fallback logic.
>
> The next set of patches will use this new facility to bring IPv6
> support to umount.nfs.
>
> If you have some unit tests for mount.nfs handling version fallback
> and/or operating in an environment that does not have an accessible
> portmapper on the server, please try them with this series applied.
>
> ---
>
Committed and tested...
steved.
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2009-01-27 23:04 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-08 17:32 [PATCH 0/5] struct pmap stuffing Chuck Lever
[not found] ` <20090108172526.19893.91621.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-01-08 17:32 ` [PATCH 1/5] text-based mount command: make po_rightmost() work for N options Chuck Lever
2009-01-08 17:32 ` [PATCH 2/5] text-based mount command: Function to stuff "struct pmap" from mount options Chuck Lever
2009-01-08 17:32 ` [PATCH 3/5] text-based mount options: Use new pmap stuffer when rewriting " Chuck Lever
2009-01-08 17:32 ` [PATCH 4/5] text-based mount command: fix mount option rewriting logic Chuck Lever
2009-01-08 17:33 ` [PATCH 5/5] text-based mount command: support AF_INET6 in rewrite_mount_options() Chuck Lever
2009-01-27 23:02 ` [PATCH 0/5] struct pmap stuffing Steve Dickson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox