From patchwork Thu Aug 18 05:08:27 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Kent X-Patchwork-Id: 1075572 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p7I5IvUr000954 for ; Thu, 18 Aug 2011 05:18:58 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752228Ab1HRFS4 (ORCPT ); Thu, 18 Aug 2011 01:18:56 -0400 Received: from outbound.icp-qv1-irony-out4.iinet.net.au ([203.59.1.104]:32398 "EHLO outbound.icp-qv1-irony-out4.iinet.net.au" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751665Ab1HRFSz (ORCPT ); Thu, 18 Aug 2011 01:18:55 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Av4EABOeTE46B/rW/2dsb2JhbABBhEmkKHeBQAEpBFIoCAUCGA4CSRYTrieRTIEshAyBEASHXpBfi1g X-IronPort-AV: E=Sophos;i="4.68,243,1312128000"; d="scan'208";a="672412918" Received: from unknown (HELO perseus.themaw.net) ([58.7.250.214]) by outbound.icp-qv1-irony-out4.iinet.net.au with ESMTP; 18 Aug 2011 13:08:28 +0800 From: Ian Kent Subject: [PATCH] nfs-utils-1.2.4 - fix nfs4 check To: linux-nfs-list Cc: Steve Dickson Date: Thu, 18 Aug 2011 13:08:27 +0800 Message-ID: <20110818050827.15357.27820.stgit@perseus.themaw.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 18 Aug 2011 05:18:58 +0000 (UTC) From: Ian Kent nfs_umount_is_vers4() doesn't take acount of the escaping of characters seen in /proc/mounts and /etc/mtab as the functions in fstab.c do. This leads to an inability to umount a mount containing any of these escaped characters (like spaces). This patch changes nfs_umount_is_vers4() to use functions in fstab.c and adds a function to fstab.c to read /proc/mounts specifically, as it was used for the check in nfs_umount_is_vers4() previously. Signed-off-by: Ian Kent --- utils/mount/fstab.c | 52 +++++++++++++++++++++++++++++++++ utils/mount/fstab.h | 1 + utils/mount/nfsumount.c | 75 +++++++++++++++++++---------------------------- 3 files changed, 84 insertions(+), 44 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/utils/mount/fstab.c b/utils/mount/fstab.c index 1fc9efe..eedbdda 100644 --- a/utils/mount/fstab.c +++ b/utils/mount/fstab.c @@ -86,10 +86,13 @@ mtab_is_writable() { struct mntentchn mounttable; static int got_mtab = 0; +struct mntentchn procmounts; +static int got_procmounts = 0; struct mntentchn fstab; static int got_fstab = 0; static void read_mounttable(void); +static void read_procmounts(void); static void read_fstab(void); static struct mntentchn * @@ -101,6 +104,14 @@ mtab_head(void) } static struct mntentchn * +procmounts_head(void) +{ + if (!got_procmounts) + read_procmounts(); + return &procmounts; +} + +static struct mntentchn * fstab_head(void) { if (!got_fstab) @@ -186,6 +197,30 @@ read_mounttable() { read_mntentchn(mfp, fnam, mc); } +/* + * Read /proc/mounts. + * This produces a linked list. The list head procmounts is a dummy. + * Return 0 on success. + */ +static void +read_procmounts() { + mntFILE *mfp; + const char *fnam; + struct mntentchn *mc = &procmounts; + + got_procmounts = 1; + mc->nxt = mc->prev = NULL; + + fnam = PROC_MOUNTS; + mfp = nfs_setmntent(fnam, "r"); + if (mfp == NULL || mfp->mntent_fp == NULL) { + nfs_error(_("warning: can't open %s: %s"), + PROC_MOUNTS, strerror (errno)); + return; + } + read_mntentchn(mfp, fnam, mc); +} + static void read_fstab() { @@ -225,6 +260,23 @@ getmntdirbackward (const char *name, struct mntentchn *mcprev) { } /* + * Given the directory name NAME, and the place MCPREV we found it last time, + * try to find more occurrences. + */ +struct mntentchn * +getprocmntdirbackward (const char *name, struct mntentchn *mcprev) { + struct mntentchn *mc, *mc0; + + mc0 = procmounts_head(); + if (!mcprev) + mcprev = mc0; + for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) + if (streq(mc->m.mnt_dir, name)) + return mc; + return NULL; +} + +/* * Given the device name NAME, and the place MCPREV we found it last time, * try to find more occurrences. */ diff --git a/utils/mount/fstab.h b/utils/mount/fstab.h index dc7c9fc..313bf9b 100644 --- a/utils/mount/fstab.h +++ b/utils/mount/fstab.h @@ -18,6 +18,7 @@ struct mntentchn { struct mntentchn *getmntoptfile (const char *file); struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc); +struct mntentchn *getprocmntdirbackward (const char *name, struct mntentchn *mc); struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc); struct mntentchn *getfsfile (const char *file); diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c index 8cd2852..b846564 100644 --- a/utils/mount/nfsumount.c +++ b/utils/mount/nfsumount.c @@ -151,65 +151,50 @@ static int del_mtab(const char *spec, const char *node) */ static int nfs_umount_is_vers4(const struct mntentchn *mc) { - char buffer[LINELEN], *next; + struct mntentchn *pmc; + struct mount_options *options; int retval; - FILE *f; - - if ((f = fopen(MOUNTSFILE, "r")) == NULL) { - fprintf(stderr, "%s: %s\n", - MOUNTSFILE, strerror(errno)); - return -1; - } retval = -1; - while (fgets(buffer, sizeof(buffer), f) != NULL) { - char *device, *mntdir, *type, *flags; - struct mount_options *options; - char *line = buffer; - - next = strchr(line, '\n'); - if (next != NULL) - *next = '\0'; - - device = strtok(line, " \t"); - if (device == NULL) - continue; - mntdir = strtok(NULL, " \t"); - if (mntdir == NULL) - continue; - if (strcmp(device, mc->m.mnt_fsname) != 0 && - strcmp(mntdir, mc->m.mnt_dir) != 0) + pmc = getprocmntdirbackward(mc->m.mnt_dir, NULL); + if (!pmc) + goto not_found; + + do { + int nlen = strlen(pmc->m.mnt_fsname); + /* + * It's possible the mount location string in /proc/mounts + * ends with a '/'. In this case, if the entry came from + * /etc/mtab, it won't have the trailing '/' so deal with + * it. + */ + while (pmc->m.mnt_fsname[nlen - 1] == '/') + nlen--; + if (strncmp(pmc->m.mnt_fsname, mc->m.mnt_fsname, nlen) != 0) continue; - type = strtok(NULL, " \t"); - if (type == NULL) - continue; - if (strcmp(type, "nfs4") == 0) + if (strcmp(pmc->m.mnt_type, "nfs4") == 0) goto out_nfs4; - flags = strtok(NULL, " \t"); - if (flags == NULL) - continue; - options = po_split(flags); + options = po_split(pmc->m.mnt_opts); if (options != NULL) { unsigned long version; - int rc; - - rc = nfs_nfs_version(options, &version); + int rc = nfs_nfs_version(options, &version); po_destroy(options); if (rc && version == 4) goto out_nfs4; } - goto out_nfs; - } - if (retval == -1) + if (strcmp(pmc->m.mnt_type, "nfs") == 0) + goto out_nfs; + } while ((pmc = getprocmntdirbackward(mc->m.mnt_dir, pmc)) != NULL); + + if (retval == -1) { +not_found: fprintf(stderr, "%s was not found in %s\n", mc->m.mnt_dir, MOUNTSFILE); - -out: - fclose(f); - return retval; + goto out; + } out_nfs4: if (verbose) @@ -221,7 +206,9 @@ out_nfs: if (verbose) fprintf(stderr, "Legacy NFS mount point detected\n"); retval = 0; - goto out; + +out: + return retval; } static struct option umount_longopts[] =