walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
3de3019
Author: Chuck Lever <chuck.lever@oracle.com>
3de3019
Date:   Tue Feb 17 16:27:43 2009 -0500
3de3019
3de3019
    umount command: remove do_nfs_umount23 function
3de3019
    
3de3019
    Remove do_nfs_umount23() now that it is unused.
3de3019
    
3de3019
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
3de3019
    Signed-off-by: Steve Dickson <steved@redhat.com>
3de3019
3de3019
commit c735a8331b082038a0e83ec4187c2656b0804eea
3de3019
Author: Chuck Lever <chuck.lever@oracle.com>
3de3019
Date:   Tue Feb 17 16:26:31 2009 -0500
3de3019
3de3019
    umount.nfs command: Support AF_INET6 server addresses
3de3019
    
3de3019
    Replace existing mount option parser in nfsumount.c with the new pmap
3de3019
    stuffer
3de3019
    function nfs_options2pmap().  Mount option parsing for umount.nfs now
3de3019
    works
3de3019
    the same as it does for mount option rewriting in the text-based
3de3019
    mount.nfs
3de3019
    command.
3de3019
    
3de3019
    This adds a number of new features:
3de3019
    
3de3019
      1.  The new logic supports resolving AF_INET6 server addresses
3de3019
      2.  Support is added for the recently introduced "mountaddr" option.
3de3019
      3.  Parsing numeric option values is much more careful
3de3019
      4.  Option parsing no longer uses xmalloc/xstrdup, so it won't fail
3de3019
          silently if memory can't be allocated
3de3019
      5.  Mount program number set in /etc/rpc is respected
3de3019
      6.  Mount doesn't exit with EX_USAGE if the hostname lookup fails
3de3019
    
3de3019
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
3de3019
    Signed-off-by: Steve Dickson <steved@redhat.com>
3de3019
3de3019
commit 97de03f8c866b9d3e790d64f4e9ac24011aaa5b1
3de3019
Author: Chuck Lever <chuck.lever@oracle.com>
3de3019
Date:   Tue Feb 17 16:25:27 2009 -0500
3de3019
3de3019
    umount.nfs command: Add an AF_INET6-capable version of nfs_call_unmount()
3de3019
    
3de3019
    We need an AF_INET6-capable version of nfs_call_unmount() to allow the
3de3019
    umount.nfs command to support unmounting NFS servers over IPv6.  The
3de3019
    legacy
3de3019
    mount.nfs command still likes to use nfs_call_umount(), so we leave it
3de3019
    in
3de3019
    place and introduce a new API that can take a "struct sockaddr *".
3de3019
    
3de3019
    The umount.nfs command will invoke this new API, but we'll leave the
3de3019
    legacy
3de3019
    mount.nfs command and the umount.nfs4 command alone.  The umount.nfs4
3de3019
    command does not need this support because NFSv4 unmount operations are
3de3019
    entirely local.
3de3019
    
3de3019
    Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
3de3019
    Signed-off-by: Steve Dickson <steved@redhat.com>
3de3019
3de3019
diff -up nfs-utils-1.1.4/utils/mount/network.c.save nfs-utils-1.1.4/utils/mount/network.c
3de3019
--- nfs-utils-1.1.4/utils/mount/network.c.save	2009-02-17 16:37:18.000000000 -0500
3de3019
+++ nfs-utils-1.1.4/utils/mount/network.c	2009-02-17 16:38:10.000000000 -0500
3de3019
@@ -838,6 +838,59 @@ int start_statd(void)
3de3019
 }
3de3019
 
3de3019
 /**
3de3019
+ * nfs_advise_umount - ask the server to remove a share from it's rmtab
3de3019
+ * @sap: pointer to IP address of server to call
3de3019
+ * @salen: length of server address
3de3019
+ * @pmap: partially filled-in mountd RPC service tuple
3de3019
+ * @argp: directory path of share to "unmount"
3de3019
+ *
3de3019
+ * Returns one if the unmount call succeeded; zero if the unmount
3de3019
+ * failed for any reason;  rpccreateerr.cf_stat is set to reflect
3de3019
+ * the nature of the error.
3de3019
+ *
3de3019
+ * We use a fast timeout since this call is advisory only.
3de3019
+ */
3de3019
+int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
3de3019
+		      const struct pmap *pmap, const dirpath *argp)
3de3019
+{
3de3019
+	struct sockaddr_storage address;
3de3019
+	struct sockaddr *saddr = (struct sockaddr *)&address;
3de3019
+	struct pmap mnt_pmap = *pmap;
3de3019
+	struct timeval timeout = {
3de3019
+		.tv_sec		= MOUNT_TIMEOUT >> 3,
3de3019
+	};
3de3019
+	CLIENT *client;
3de3019
+	enum clnt_stat res = 0;
3de3019
+
3de3019
+	if (nfs_probe_mntport(sap, salen, &mnt_pmap) == 0)
3de3019
+		return 0;
3de3019
+
3de3019
+	memcpy(saddr, sap, salen);
3de3019
+	nfs_set_port(saddr, mnt_pmap.pm_port);
3de3019
+
3de3019
+	client = nfs_get_rpcclient(saddr, salen, mnt_pmap.pm_prot,
3de3019
+					mnt_pmap.pm_prog, mnt_pmap.pm_vers,
3de3019
+					&timeout);
3de3019
+	if (client == NULL)
3de3019
+		return 0;
3de3019
+
3de3019
+	client->cl_auth = authunix_create_default();
3de3019
+
3de3019
+	res = CLNT_CALL(client, MOUNTPROC_UMNT,
3de3019
+			(xdrproc_t)xdr_dirpath, (caddr_t)argp,
3de3019
+			(xdrproc_t)xdr_void, NULL,
3de3019
+			timeout);
3de3019
+
3de3019
+	auth_destroy(client->cl_auth);
3de3019
+	CLNT_DESTROY(client);
3de3019
+
3de3019
+	if (res != RPC_SUCCESS)
3de3019
+		return 0;
3de3019
+
3de3019
+	return 1;
3de3019
+}
3de3019
+
3de3019
+/**
3de3019
  * nfs_call_umount - ask the server to remove a share from it's rmtab
3de3019
  * @mnt_server: address of RPC MNT program server
3de3019
  * @argp: directory path of share to "unmount"
3de3019
diff -up nfs-utils-1.1.4/utils/mount/network.h.save nfs-utils-1.1.4/utils/mount/network.h
3de3019
--- nfs-utils-1.1.4/utils/mount/network.h.save	2009-02-17 16:37:26.000000000 -0500
3de3019
+++ nfs-utils-1.1.4/utils/mount/network.h	2009-02-17 16:38:10.000000000 -0500
3de3019
@@ -52,7 +52,6 @@ int nfs_present_sockaddr(const struct so
3de3019
 			 const socklen_t, char *, const size_t);
3de3019
 int nfs_callback_address(const struct sockaddr *, const socklen_t,
3de3019
 		struct sockaddr *, socklen_t *);
3de3019
-int nfs_call_umount(clnt_addr_t *, dirpath *);
3de3019
 int clnt_ping(struct sockaddr_in *, const unsigned long,
3de3019
 		const unsigned long, const unsigned int,
3de3019
 		struct sockaddr_in *);
3de3019
@@ -66,6 +65,9 @@ int start_statd(void);
3de3019
 
3de3019
 unsigned long nfsvers_to_mnt(const unsigned long);
3de3019
 
3de3019
+int nfs_call_umount(clnt_addr_t *, dirpath *);
3de3019
+int nfs_advise_umount(const struct sockaddr *, const socklen_t,
3de3019
+		      const struct pmap *, const dirpath *);
3de3019
 CLIENT *mnt_openclnt(clnt_addr_t *, int *);
3de3019
 void mnt_closeclnt(CLIENT *, int);
3de3019
 
3de3019
diff -up nfs-utils-1.1.4/utils/mount/nfsumount.c.save nfs-utils-1.1.4/utils/mount/nfsumount.c
3de3019
--- nfs-utils-1.1.4/utils/mount/nfsumount.c.save	2009-02-17 16:37:42.000000000 -0500
3de3019
+++ nfs-utils-1.1.4/utils/mount/nfsumount.c	2009-02-17 16:38:29.000000000 -0500
3de3019
@@ -34,6 +34,7 @@
3de3019
 #include "mount.h"
3de3019
 #include "error.h"
3de3019
 #include "network.h"
3de3019
+#include "parse_opt.h"
3de3019
 #include "parse_dev.h"
3de3019
 
3de3019
 #if !defined(MNT_FORCE)
3de3019
@@ -134,6 +135,64 @@ static int del_mtab(const char *spec, co
3de3019
 }
3de3019
 
3de3019
 /*
3de3019
+ * Discover mount server's hostname/address by examining mount options
3de3019
+ *
3de3019
+ * Returns a pointer to a string that the caller must free, on
3de3019
+ * success; otherwise NULL is returned.
3de3019
+ */
3de3019
+static char *nfs_umount_hostname(struct mount_options *options,
3de3019
+				 char *hostname)
3de3019
+{
3de3019
+	char *option;
3de3019
+
3de3019
+	option = po_get(options, "mountaddr");
3de3019
+	if (option)
3de3019
+		goto out;
3de3019
+	option = po_get(options, "mounthost");
3de3019
+	if (option)
3de3019
+		goto out;
3de3019
+	option = po_get(options, "addr");
3de3019
+	if (option)
3de3019
+		goto out;
3de3019
+
3de3019
+	return hostname;
3de3019
+
3de3019
+out:
3de3019
+	free(hostname);
3de3019
+	return strdup(option);
3de3019
+}
3de3019
+
3de3019
+/*
3de3019
+ * Returns EX_SUCCESS if mount options and device name have been
3de3019
+ * parsed successfully; otherwise EX_FAIL.
3de3019
+ */
3de3019
+static int nfs_umount_do_umnt(struct mount_options *options,
3de3019
+			      char **hostname, char **dirname)
3de3019
+{
3de3019
+	struct sockaddr_storage address;
3de3019
+	struct sockaddr *sap = (struct sockaddr *)&address;
3de3019
+	socklen_t salen = sizeof(address);
3de3019
+	struct pmap nfs_pmap, mnt_pmap;
3de3019
+
3de3019
+	nfs_options2pmap(options, &nfs_pmap, &mnt_pmap);
3de3019
+
3de3019
+	*hostname = nfs_umount_hostname(options, *hostname);
3de3019
+	if (!*hostname) {
3de3019
+		nfs_error(_("%s: out of memory"), progname);
3de3019
+		return EX_FAIL;
3de3019
+	}
3de3019
+
3de3019
+	if (nfs_name_to_address(*hostname, AF_UNSPEC, sap, &salen)) {
3de3019
+		if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) != 0)
3de3019
+			return EX_SUCCESS;
3de3019
+		else
3de3019
+			nfs_error(_("%s: Server failed to unmount '%s:%s'"),
3de3019
+					progname, *hostname, *dirname);
3de3019
+	}
3de3019
+	return EX_FAIL;
3de3019
+}
3de3019
+
3de3019
+/*
3de3019
  * Pick up certain mount options used during the original mount
3de3019
  * from /etc/mtab.  The basics include the server's IP address and
3de3019
  * the server pathname of the share to unregister.
3de3019
@@ -142,85 +201,28 @@ static int del_mtab(const char *spec, co
3de3019
  * version, and transport protocol used to punch through a firewall.
3de3019
  * We will need this information to get through the firewall again
3de3019
  * to do the umount.
3de3019
+ *
3de3019
+ * Note that option parsing failures won't necessarily cause the
3de3019
+ * umount request to fail.  Those values will be left zero in the
3de3019
+ * pmap tuple.  If the GETPORT call later fails to disambiguate them,
3de3019
+ * then we fail.
3de3019
  */
3de3019
-static int do_nfs_umount23(const char *spec, char *opts)
3de3019
+static int nfs_umount23(const char *devname, char *string)
3de3019
 {
3de3019
-	char *hostname;
3de3019
-	char *dirname;
3de3019
-	clnt_addr_t mnt_server = { &hostname, };
3de3019
-	struct mntent mnt = { .mnt_opts = opts };
3de3019
-	struct pmap *pmap = &mnt_server.pmap;
3de3019
-	char *p;
3de3019
-	int result = EX_USAGE;
3de3019
-
3de3019
-	if (!nfs_parse_devname(spec, &hostname, &dirname))
3de3019
-		return result;
3de3019
-
3de3019
-#ifdef NFS_MOUNT_DEBUG
3de3019
-	printf(_("host: %s, directory: %s\n"), hostname, dirname);
3de3019
-#endif
3de3019
-
3de3019
-	if (opts && (p = strstr(opts, "addr="))) {
3de3019
-		char *q;
3de3019
+	char *hostname, *dirname;
3de3019
+	struct mount_options *options;
3de3019
+	int result = EX_FAIL;
3de3019
 
3de3019
-		free(hostname);
3de3019
-		p += 5;
3de3019
-		q = p;
3de3019
-		while (*q && *q != ',') q++;
3de3019
-		hostname = xstrndup(p,q-p);
3de3019
-	}
3de3019
-
3de3019
-	if (opts && (p = strstr(opts, "mounthost="))) {
3de3019
-		char *q;
3de3019
-
3de3019
-		free(hostname);
3de3019
-		p += 10;
3de3019
-		q = p;
3de3019
-		while (*q && *q != ',') q++;
3de3019
-		hostname = xstrndup(p,q-p);
3de3019
-	}
3de3019
-
3de3019
-	pmap->pm_prog = MOUNTPROG;
3de3019
-	pmap->pm_vers = 0; /* unknown */
3de3019
-	if (opts && (p = strstr(opts, "mountprog=")) && isdigit(*(p+10)))
3de3019
-		pmap->pm_prog = atoi(p+10);
3de3019
-	if (opts && (p = strstr(opts, "mountport=")) && isdigit(*(p+10)))
3de3019
-		pmap->pm_port = atoi(p+10);
3de3019
-	if (opts && hasmntopt(&mnt, "v2"))
3de3019
-		pmap->pm_vers = nfsvers_to_mnt(2);
3de3019
-	if (opts && hasmntopt(&mnt, "v3"))
3de3019
-		pmap->pm_vers = nfsvers_to_mnt(3);
3de3019
-	if (opts && (p = strstr(opts, "vers=")) && isdigit(*(p+5)))
3de3019
-		pmap->pm_vers = nfsvers_to_mnt(atoi(p+5));
3de3019
-	if (opts && (p = strstr(opts, "mountvers=")) && isdigit(*(p+10)))
3de3019
-		pmap->pm_vers = atoi(p+10);
3de3019
-	if (opts && (hasmntopt(&mnt, "udp")
3de3019
-		     || hasmntopt(&mnt, "proto=udp")
3de3019
-		     || hasmntopt(&mnt, "mountproto=udp")
3de3019
-		    ))
3de3019
-		pmap->pm_prot = IPPROTO_UDP;
3de3019
-	if (opts && (hasmntopt(&mnt, "tcp")
3de3019
-		     || hasmntopt(&mnt, "proto=tcp")
3de3019
-		     || hasmntopt(&mnt, "mountproto=tcp")
3de3019
-		    ))
3de3019
-		pmap->pm_prot = IPPROTO_TCP;
3de3019
-
3de3019
-	if (!nfs_gethostbyname(hostname, &mnt_server.saddr)) {
3de3019
-		nfs_error(_("%s: DNS resolution of '%s' failed"),
3de3019
-				progname, hostname);
3de3019
-		goto out;
3de3019
-	}
3de3019
-
3de3019
-	if (!nfs_call_umount(&mnt_server, &dirname)) {
3de3019
-		nfs_error(_("%s: Server failed to unmount '%s'"),
3de3019
-				progname, spec);
3de3019
-		result = EX_FAIL;
3de3019
-		goto out;
3de3019
-	}
3de3019
+	if (!nfs_parse_devname(devname, &hostname, &dirname))
3de3019
+		return EX_USAGE;
3de3019
 
3de3019
-	result = EX_SUCCESS;
3de3019
+	options = po_split(string);
3de3019
+	if (options) {
3de3019
+		result = nfs_umount_do_umnt(options, &hostname, &dirname);
3de3019
+		po_destroy(options);
3de3019
+	} else
3de3019
+		nfs_error(_("%s: option parsing error"), progname);
3de3019
 
3de3019
-out:
3de3019
 	free(hostname);
3de3019
 	free(dirname);
3de3019
 	return result;
3de3019
@@ -350,16 +352,16 @@ int nfsumount(int argc, char *argv[])
3de3019
 	ret = 0;
3de3019
 	if (mc) {
3de3019
 		if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 0)
3de3019
-			/* We ignore the error from do_nfs_umount23.
3de3019
+			/* We ignore the error from nfs_umount23.
3de3019
 			 * If the actual umount succeeds (in del_mtab),
3de3019
 			 * we don't want to signal an error, as that
3de3019
 			 * could cause /sbin/mount to retry!
3de3019
 			 */
3de3019
-			do_nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
3de3019
-		ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
3de3019
+			nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
3de3019
+		ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir) ?: ret;
3de3019
 	} else if (*spec != '/') {
3de3019
 		if (!lazy)
3de3019
-			ret = do_nfs_umount23(spec, "tcp,v3");
3de3019
+			ret = nfs_umount23(spec, "tcp,v3");
3de3019
 	} else
3de3019
 		ret = del_mtab(NULL, spec);
3de3019