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