From 3de3019b29d0ae505ea9b48118b406909c9568bd Mon Sep 17 00:00:00 2001 From: Steve Dickson Date: Tue, 17 Feb 2009 21:46:26 +0000 Subject: [PATCH] - umount.nfs command: Add an AF_INET6-capable version of nfs_call_unmount() - umount.nfs command: Support AF_INET6 server addresses - umount command: remove do_nfs_umount23 function --- nfs-utils-1.1.4-umount-ipv6.patch | 343 ++++++++++++++++++++++++++++++ nfs-utils.spec | 9 +- 2 files changed, 351 insertions(+), 1 deletion(-) create mode 100644 nfs-utils-1.1.4-umount-ipv6.patch diff --git a/nfs-utils-1.1.4-umount-ipv6.patch b/nfs-utils-1.1.4-umount-ipv6.patch new file mode 100644 index 0000000..3c3e965 --- /dev/null +++ b/nfs-utils-1.1.4-umount-ipv6.patch @@ -0,0 +1,343 @@ +Author: Chuck Lever +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 + Signed-off-by: Steve Dickson + +commit c735a8331b082038a0e83ec4187c2656b0804eea +Author: Chuck Lever +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 + Signed-off-by: Steve Dickson + +commit 97de03f8c866b9d3e790d64f4e9ac24011aaa5b1 +Author: Chuck Lever +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 + Signed-off-by: Steve Dickson + +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); + diff --git a/nfs-utils.spec b/nfs-utils.spec index 9eabe66..6a88252 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -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: 17%{?dist} +Release: 18%{?dist} Epoch: 1 # group all 32bit related archs @@ -50,6 +50,7 @@ Patch120: nfs-utils-1.1.4-tcpwrap-cleanup.patch Patch121: nfs-utils-1.1.4-mount-textbased.patch Patch122: nfs-utils-1.1.4-mount-nolock.patch Patch123: nfs-utils-1.1.4-mount-udponly.patch +Patch124: nfs-utils-1.1.4-umount-ipv6.patch %if %{enablefscache} Patch90: nfs-utils-1.1.0-mount-fsc.patch @@ -128,6 +129,7 @@ This package also contains the mount.nfs and umount.nfs program. %patch121 -p1 %patch122 -p1 %patch123 -p1 +%patch124 -p1 %if %{enablefscache} %patch90 -p1 @@ -291,6 +293,11 @@ fi %attr(4755,root,root) /sbin/umount.nfs4 %changelog +* Tue Feb 17 2009 Steve Dickson 1.1.4-18 +- umount.nfs command: Add an AF_INET6-capable version of nfs_call_unmount() +- umount.nfs command: Support AF_INET6 server addresses +- umount command: remove do_nfs_umount23 function + * Tue Feb 17 2009 Steve Dickson 1.1.4-17 - Integrated the upstream fix for bz 483375 - mount: segmentation faults on UDP mounts (bz 485448)