- text-based mount command: make po_rightmost() work for N options
- text-based mount command: Function to stuff "struct pmap" from mount options - text-based mount options: Use new pmap stuffer when rewriting mount options - text-based mount command: fix mount option rewriting logic - text-based mount command: support AF_INET6 in rewrite_mount_options()
This commit is contained in:
parent
5f17b62a87
commit
e237fe4711
821
nfs-utils-1.1.4-mount-textbased.patch
Normal file
821
nfs-utils-1.1.4-mount-textbased.patch
Normal file
@ -0,0 +1,821 @@
|
||||
text-based mount command: make po_rightmost() work for N options
|
||||
|
||||
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);
|
||||
|
||||
text-based mount command: Function to stuff "struct pmap" from mount options
|
||||
|
||||
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);
|
||||
|
||||
text-based mount options: Use new pmap stuffer when rewriting mount options
|
||||
|
||||
all 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;
|
||||
|
||||
text-based mount command: fix mount option rewriting logic
|
||||
|
||||
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;
|
||||
|
||||
|
||||
text-based mount command: support AF_INET6 in rewrite_mount_options()
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser
|
||||
Name: nfs-utils
|
||||
URL: http://sourceforge.net/projects/nfs
|
||||
Version: 1.1.4
|
||||
Release: 13%{?dist}
|
||||
Release: 14%{?dist}
|
||||
Epoch: 1
|
||||
|
||||
# group all 32bit related archs
|
||||
@ -45,6 +45,7 @@ Patch115: nfs-utils-1.1.4-mount-addrconfig.patch
|
||||
Patch116: nfs-utils-1.1.4-configure-uuid.patch
|
||||
Patch117: nfs-utils-1.1.4-configure-tirpc.patch
|
||||
Patch118: nfs-utils-1.1.4-tcpwrap-rulecheck.patch
|
||||
Patch119: nfs-utils-1.1.4-mount-textbased.patch
|
||||
|
||||
%if %{enablefscache}
|
||||
Patch90: nfs-utils-1.1.0-mount-fsc.patch
|
||||
@ -118,6 +119,7 @@ This package also contains the mount.nfs and umount.nfs program.
|
||||
%patch116 -p1
|
||||
%patch117 -p1
|
||||
%patch118 -p1
|
||||
%patch119 -p1
|
||||
|
||||
%if %{enablefscache}
|
||||
%patch90 -p1
|
||||
@ -281,6 +283,13 @@ fi
|
||||
%attr(4755,root,root) /sbin/umount.nfs4
|
||||
|
||||
%changelog
|
||||
* Tue Jan 27 2009 Steve Dickson <steved@redhat.com> 1.1.4-14
|
||||
- text-based mount command: make po_rightmost() work for N options
|
||||
- text-based mount command: Function to stuff "struct pmap" from mount options
|
||||
- text-based mount options: Use new pmap stuffer when rewriting mount options
|
||||
- text-based mount command: fix mount option rewriting logic
|
||||
- text-based mount command: support AF_INET6 in rewrite_mount_options()
|
||||
|
||||
* Tue Jan 20 2009 Steve Dickson <steved@redhat.com> 1.1.4-13
|
||||
- mountd: Don't do tcp wrapper check when there are no rules (bz 448898)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user