2017-07-13 06:30:28

by NeilBrown

[permalink] [raw]
Subject: [PATCH 0/4] Fix assorted problems with mount.nfs

These 4 patches fix various issues involves old versions of glibc, old
kernels, and parsing of old options.

Thanks,
NeilBrown

---

NeilBrown (4):
mount: support compiling with old glibc
mount: use version string that is supported by old kernels.
mount: move handling of "-t nfs4" into nfs_nfs_version()
mount: Fix problems with parsing minorversion=


utils/mount/configfile.c | 2 +-
utils/mount/network.c | 41 ++++++++++++++++++++++++++---------------
utils/mount/network.h | 2 +-
utils/mount/nfsumount.c | 2 +-
utils/mount/stropts.c | 28 +++++++++++++++++++---------
5 files changed, 48 insertions(+), 27 deletions(-)

--
Signature



2017-07-13 06:30:34

by NeilBrown

[permalink] [raw]
Subject: [PATCH 1/4] mount: support compiling with old glibc

With glibc older than 2.24, it is always possible to include
both linux/in6.h and netinet/in.h.
So if the glibc is older, just hard-code the two values we need
from linux/in6.h

Signed-off-by: NeilBrown <[email protected]>
---
utils/mount/network.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/utils/mount/network.c b/utils/mount/network.c
index 281e9354a7fa..92457c726be7 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -39,7 +39,13 @@
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/stat.h>
-#include <linux/in6.h>
+#if defined(__GLIBC__) && (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 24)
+/* Cannot safely include linux/in6.h in old glibc, so hardcode the needed values */
+# define IPV6_PREFER_SRC_PUBLIC 2
+# define IPV6_ADDR_PREFERENCES 72
+#else
+# include <linux/in6.h>
+#endif
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>



2017-07-13 06:30:45

by NeilBrown

[permalink] [raw]
Subject: [PATCH 3/4] mount: move handling of "-t nfs4" into nfs_nfs_version()

Current "-t nfs4" causes other mount options to be ignored
and an NFSv4 version to be negotiated.
This is even true when "-o vers=4.1" is given.

To address this, we need to move the handled of "-t nfs4"
into nfs_nfs_version, which means passing in the filesystem type.

Signed-off-by: NeilBrown <[email protected]>
---
utils/mount/configfile.c | 2 +-
utils/mount/network.c | 11 ++++++-----
utils/mount/network.h | 2 +-
utils/mount/nfsumount.c | 2 +-
utils/mount/stropts.c | 8 +-------
5 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c
index dc964c79107f..e4b39ef86bad 100644
--- a/utils/mount/configfile.c
+++ b/utils/mount/configfile.c
@@ -260,7 +260,7 @@ default_value(char *mopt)
}
} else if (strncasecmp(field, "vers", strlen("vers")) == 0) {
if ((options = po_split(field)) != NULL) {
- if (!nfs_nfs_version(options, &config_default_vers)) {
+ if (!nfs_nfs_version("nfs", options, &config_default_vers)) {
xlog_warn("Unable to set default version: %s",
strerror(errno));

diff --git a/utils/mount/network.c b/utils/mount/network.c
index 92457c726be7..d673391b5fff 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -1260,7 +1260,7 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
* or FALSE if the option was specified with an invalid value.
*/
int
-nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
+nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version)
{
char *version_key, *version_val, *cptr;
int i, found = 0;
@@ -1275,10 +1275,11 @@ nfs_nfs_version(struct mount_options *options, struct nfs_version *version)
}
}

- if (!found)
+ if (!found && strcmp(type, "nfs4") == 0)
+ version_val = type + 3;
+ else if (!found)
return 1;
-
- if (i <= 2 ) {
+ else if (i <= 2 ) {
/* v2, v3, v4 */
version_val = version_key + 1;
version->v_mode = V_SPECIFIC;
@@ -1650,7 +1651,7 @@ int nfs_options2pmap(struct mount_options *options,

if (!nfs_nfs_program(options, &nfs_pmap->pm_prog))
return 0;
- if (!nfs_nfs_version(options, &version))
+ if (!nfs_nfs_version("nfs", options, &version))
return 0;
if (version.v_mode == V_DEFAULT)
nfs_pmap->pm_vers = 0;
diff --git a/utils/mount/network.h b/utils/mount/network.h
index 9cc5decf19fa..ecaac33d88de 100644
--- a/utils/mount/network.h
+++ b/utils/mount/network.h
@@ -72,7 +72,7 @@ struct nfs_version {

int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
-int nfs_nfs_version(struct mount_options *options, struct nfs_version *version);
+int nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *version);
int nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);

int nfs_options2pmap(struct mount_options *,
diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
index de284f2419da..e16fb6a1bbb1 100644
--- a/utils/mount/nfsumount.c
+++ b/utils/mount/nfsumount.c
@@ -180,7 +180,7 @@ static int nfs_umount_is_vers4(const struct mntentchn *mc)
options = po_split(pmc->m.mnt_opts);
if (options != NULL) {
struct nfs_version version;
- int rc = nfs_nfs_version(options, &version);
+ int rc = nfs_nfs_version("nfs", options, &version);
po_destroy(options);
if (rc && version.major == 4)
goto out_nfs4;
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 0a371bf1811e..eb9a27ba2f50 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -327,15 +327,9 @@ static int nfs_append_sloppy_option(struct mount_options *options)

static int nfs_set_version(struct nfsmount_info *mi)
{
- if (!nfs_nfs_version(mi->options, &mi->version))
+ if (!nfs_nfs_version(mi->type, mi->options, &mi->version))
return 0;

- if (strncmp(mi->type, "nfs4", 4) == 0) {
- /* Set to default values */
- mi->version.major = NFS_DEFAULT_MAJOR;
- mi->version.minor = NFS_DEFAULT_MINOR;
- mi->version.v_mode = V_GENERAL;
- }
/*
* Before 2.6.32, the kernel NFS client didn't
* support "-t nfs vers=4" mounts, so NFS version



2017-07-13 06:30:39

by NeilBrown

[permalink] [raw]
Subject: [PATCH 2/4] mount: use version string that is supported by old kernels.

All kernels which support NFSv4.2 understand "vers=4.2".
Some kernels which support NFSv4.1 only understand "vers=4,minorversion=1".
All later kernels also support this.

Some kernels which support NFSv4.0 only understand "vers=4".
All later kernels also support this.

So use the string that is most appropriate for each version.

Signed-off-by: NeilBrown <[email protected]>
---
utils/mount/stropts.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index c2a739bca854..0a371bf1811e 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -727,7 +727,7 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
{
struct mount_options *options = po_dup(mi->options);
int result = 0;
- char version_opt[16];
+ char version_opt[32];
char *extra_opts = NULL;

if (!options) {
@@ -749,8 +749,24 @@ static int nfs_do_mount_v4(struct nfsmount_info *mi,
}

if (mi->version.v_mode != V_SPECIFIC) {
+ char *fmt;
+ switch (mi->version.minor) {
+ /* Old kernels don't support the new "vers=x.y"
+ * option, but do support old versions of NFS4.
+ * So use the format that is most widely understood.
+ */
+ case 0:
+ fmt = "vers=%lu";
+ break;
+ case 1:
+ fmt = "vers=%lu,minorversion=%lu";
+ break;
+ default:
+ fmt = "vers=%lu.%lu";
+ break;
+ }
snprintf(version_opt, sizeof(version_opt) - 1,
- "vers=%lu.%lu", mi->version.major,
+ fmt, mi->version.major,
mi->version.minor);

if (po_append(options, version_opt) == PO_FAILED) {



2017-07-13 06:30:50

by NeilBrown

[permalink] [raw]
Subject: [PATCH 4/4] mount: Fix problems with parsing minorversion=

1/ minorversion=0 is not recognized, as errors from
strtol() are not correctly detected.
2/ when there is an error in the minorversion= value,
no message is presented.
3/ Current code recognizes "minorversion" and sets V_SPECIFIC,
but then because *cptr == '\0', the v_mode is reset to V_GENERAL.
This results in minorversion negotiation, which is not wanted.

This patch addresses all of these.

Signed-off-by: NeilBrown <[email protected]>
---
utils/mount/network.c | 22 +++++++++++++---------
1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/utils/mount/network.c b/utils/mount/network.c
index d673391b5fff..11ee818f9705 100644
--- a/utils/mount/network.c
+++ b/utils/mount/network.c
@@ -100,7 +100,6 @@ static const char *nfs_version_opttbl[] = {
"v4",
"vers",
"nfsvers",
- "minorversion",
NULL,
};

@@ -1291,17 +1290,19 @@ nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *v
if (!version_val)
goto ret_error;

- if (!(version->major = strtol(version_val, &cptr, 10)))
+ version->major = strtol(version_val, &cptr, 10);
+ if (cptr == version_val || (*cptr && *cptr != '.'))
goto ret_error;
-
- if (strcmp(nfs_version_opttbl[i], "minorversion") == 0) {
+ if (version->major == 4 && *cptr != '.' &&
+ (version_val = po_get(options, "minorversion")) != NULL) {
+ version->minor = strtol(version_val, &cptr, 10);
+ i = -1;
+ if (*cptr)
+ goto ret_error;
version->v_mode = V_SPECIFIC;
- version->minor = version->major;
- version->major = 4;
} else if (version->major < 4)
version->v_mode = V_SPECIFIC;
-
- if (*cptr == '.') {
+ else if (*cptr == '.') {
version_val = ++cptr;
if (!(version->minor = strtol(version_val, &cptr, 10)) && cptr == version_val)
goto ret_error;
@@ -1315,7 +1316,10 @@ nfs_nfs_version(char *type, struct mount_options *options, struct nfs_version *v
return 1;

ret_error:
- if (i <= 2 ) {
+ if (i < 0) {
+ nfs_error(_("%s: parsing error on 'minorversion=' option"),
+ progname);
+ } else if (i <= 2 ) {
nfs_error(_("%s: parsing error on 'v' option"),
progname);
} else if (i == 3 ) {



2017-07-26 17:58:23

by Steve Dickson

[permalink] [raw]
Subject: Re: [PATCH 0/4] Fix assorted problems with mount.nfs



On 07/13/2017 02:30 AM, NeilBrown wrote:
> These 4 patches fix various issues involves old versions of glibc, old
> kernels, and parsing of old options.
>
> Thanks,
> NeilBrown
>
> ---
>
> NeilBrown (4):
> mount: support compiling with old glibc
> mount: use version string that is supported by old kernels.
> mount: move handling of "-t nfs4" into nfs_nfs_version()
> mount: Fix problems with parsing minorversion=
>
>
> utils/mount/configfile.c | 2 +-
> utils/mount/network.c | 41 ++++++++++++++++++++++++++---------------
> utils/mount/network.h | 2 +-
> utils/mount/nfsumount.c | 2 +-
> utils/mount/stropts.c | 28 +++++++++++++++++++---------
> 5 files changed, 48 insertions(+), 27 deletions(-)
All 4 committed! Thanks!!!

steved.
>
> --
> Signature
>