LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File nfs-utils-improve-v4-umount of Package nfs-utils (Project openSUSE:11.4)

Return-Path: <linux-nfs-owner@vger.kernel.org>
Received: from imap.suse.de ([unix socket])
	 by imap-int (Cyrus v2.2.12) with LMTPA;
	 Mon, 11 Oct 2010 02:06:26 +0200
X-Sieve: CMU Sieve 2.2
Received: from relay1.suse.de (relay1.suse.de [149.44.160.133])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(Client CN "relay.suse.de", Issuer "CAcert Class 3 Root" (verified OK))
	by imap.suse.de (Postfix) with ESMTP id DDF033C416B3
	for <nfbrown@imap.suse.de>; Mon, 11 Oct 2010 02:06:26 +0200 (CEST)
Received: by relay1.suse.de (Postfix)
	id D5C57344BA64; Mon, 11 Oct 2010 02:06:26 +0200 (CEST)
Received: from relay1.suse.de (localhost [127.0.0.1])
	by relay1.suse.de (Postfix) with ESMTP id CB887344BA63
	for <neilb@suse.de>; Mon, 11 Oct 2010 02:06:26 +0200 (CEST)
Received: from relay1.suse.de ([127.0.0.1])
 by relay1.suse.de (relay1.suse.de [127.0.0.1]) (amavisd-new, port 10026)
 with ESMTP id 05752-10 for <neilb@suse.de>;
 Mon, 11 Oct 2010 02:06:26 +0200 (CEST)
Received: from mx2.suse.de (cantor2.suse.de [195.135.220.15])
	by relay1.suse.de (Postfix) with ESMTP id 82936344BA61
	for <neilb@suse.de>; Mon, 11 Oct 2010 02:06:26 +0200 (CEST)
Received: from vger.kernel.org (vger.kernel.org [209.132.180.67])
	by mx2.suse.de (Postfix) with ESMTP id 0560C8738D
	for <neilb@suse.de>; Mon, 11 Oct 2010 02:06:26 +0200 (CEST)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
	id S1752633Ab0JKAGZ (ORCPT <rfc822;neilb@suse.de>);
	Sun, 10 Oct 2010 20:06:25 -0400
Received: from mail-iw0-f174.google.com ([209.85.214.174]:38170 "EHLO
	mail-iw0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
	with ESMTP id S1752630Ab0JKAGZ (ORCPT
	<rfc822;linux-nfs@vger.kernel.org>); Sun, 10 Oct 2010 20:06:25 -0400
Received: by mail-iw0-f174.google.com with SMTP id 6so2668490iwn.19
        for <linux-nfs@vger.kernel.org>; Sun, 10 Oct 2010 17:06:24 -0700 (PDT)
DKIM-Signature:	v=1; a=rsa-sha256; c=relaxed/relaxed;
        d=gmail.com; s=gamma;
        h=domainkey-signature:received:received:sender:from:subject:to:cc
         :date:message-id:in-reply-to:references:user-agent:mime-version
         :content-type:content-transfer-encoding;
        bh=1dui3wv1qJqGDKTTO6lTgXqRJbuKWPHSrtmMEkpD7hs=;
        b=vXeac3fZfpDsuWOMQbwU3mNfRKsvUjveCnLymxOiOUVf6/3mMfeTXvJLCw0YUB7H4u
         xsJyFvmFmbeRUaK4urW63lqMp6ZZIcuioSUaS10SbiFvuoK1y5DX2w6rjYWblUQuXpao
         nYJlG0vuogoUCGZfrrXL1tRJA+dgl7XDSjjhk=
DomainKey-Signature: a=rsa-sha1; c=nofws;
        d=gmail.com; s=gamma;
        h=sender:from:subject:to:cc:date:message-id:in-reply-to:references
         :user-agent:mime-version:content-type:content-transfer-encoding;
        b=UiUdZXRO8dSOpNik05iHQfjFfwuBqGhgAIwHe4k+aUO9FvIGEDtsFub1GqSEvFKHll
         obvKa3PfyOAt0PU6Az8+dMTEt0wRESkKVqMrxBWLkCDZ64/EE31FCCVTTvxQbVzB878Y
         00pk3YJo+YPJmXsvclpbCl6LYYaBkfnqdJ/yA=
Received: by 10.231.32.140 with SMTP id c12mr3925655ibd.90.1286755583476;
        Sun, 10 Oct 2010 17:06:23 -0700 (PDT)
Received: from ellison.1015granger.net (adsl-76-241-169-38.dsl.sfldmi.sbcglobal.net [76.241.169.38])
        by mx.google.com with ESMTPS id x10sm6553992iba.10.2010.10.10.17.06.21
        (version=TLSv1/SSLv3 cipher=RC4-MD5);
        Sun, 10 Oct 2010 17:06:22 -0700 (PDT)
From: Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH 14/15] umount.nfs: Distinguish between nfs4 and nfs mounts
To: steved@redhat.com
Cc: linux-nfs@vger.kernel.org
Date:	Sun, 10 Oct 2010 20:06:20 -0400
Message-ID: <20101011000620.6667.79025.stgit@ellison.1015granger.net>
In-Reply-To: <20101010234836.6667.4057.stgit@ellison.1015granger.net>
References: <20101010234836.6667.4057.stgit@ellison.1015granger.net>
User-Agent: StGIT/0.14.3
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
Sender: linux-nfs-owner@vger.kernel.org
Precedence: bulk
List-ID: <linux-nfs.vger.kernel.org>
X-Mailing-List:	linux-nfs@vger.kernel.org
X-Virus-Scanned: by amavisd-new at relay1.suse.de
X-Spam-Status: No, score=-6.11 tagged_above=-20 required=5
 tests=[BAYES_05=-1.11, MY_LINUX=-1, RCVD_IN_DNSWL_MED=-4]
X-Spam-Score: -6.11
X-Spam-Level: 
X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.2

Neil Brown reports that umount.nfs is still confused by "-t nfs -o
vers=4" mounts.

/etc/mtab can be confused.  /proc/mounts is authoritative on the
fstype of a mount.  Have umount.nfs consult it to determine which
mechanism to use for unmounting.  The code to read /proc/mounts was
lifted from the nfsstat command.

The code introduced by this patch may look like belt-n-suspenders, but
we have two use cases to consider:

  1.  Old kernels don't support the "vers=4" mount option, so
      umount.nfs must look for the "nfs4" fstype
  2.  Upcoming kernels may eliminate support the "nfs4" fstype, so
      umount.nfs must look for the "vers=4" mount option

Thus this logic checks for "nfs4" first then looks for the NFS version
setting.

Note that we could handle unmounting entirely in the kernel, but that
won't help older kernels that have this issue.

See:
  https://bugzilla.linux-nfs.org/show_bug.cgi?id=189

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---

 utils/mount/nfsumount.c |  111 ++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 104 insertions(+), 7 deletions(-)

--- nfs-utils-1.2.3.orig/utils/mount/nfsumount.c
+++ nfs-utils-1.2.3/utils/mount/nfsumount.c
@@ -37,6 +37,9 @@
 #include "parse_opt.h"
 #include "parse_dev.h"
 
+#define MOUNTSFILE	"/proc/mounts"
+#define LINELEN		(4096)
+
 #if !defined(MNT_FORCE)
 /* dare not try to include <linux/mount.h> -- lots of errors */
 #define MNT_FORCE 1
@@ -241,6 +244,91 @@ static int nfs_umount23(const char *devn
 	return result;
 }
 
+/*
+ * Detect NFSv4 mounts.
+ *
+ * Consult /proc/mounts to determine if the mount point
+ * is an NFSv4 mount.  The kernel is authoritative about
+ * what type of mount this is.
+ *
+ * Returns 1 if "mc" is an NFSv4 mount, zero if not, and
+ * -1 if some error occurred.
+ */
+static int nfs_umount_is_vers4(const struct mntentchn *mc)
+{
+	char buffer[LINELEN], *next;
+	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)
+			continue;
+
+		type = strtok(NULL, " \t");
+		if (type == NULL)
+			continue;
+		if (strcmp(type, "nfs4") == 0)
+			goto out_nfs4;
+
+		flags = strtok(NULL, " \t");
+		if (flags == NULL)
+			continue;
+		options = po_split(flags);
+		if (options != NULL) {
+			unsigned long version;
+			int rc;
+
+			rc = nfs_nfs_version(options, &version);
+			po_destroy(options);
+			if (rc && version == 4)
+				goto out_nfs4;
+		}
+
+		goto out_nfs;
+	}
+	if (retval == -1)
+		fprintf(stderr, "%s was not found in %s\n",
+			mc->m.mnt_dir, MOUNTSFILE);
+
+out:
+	fclose(f);
+	return retval;
+
+out_nfs4:
+	if (verbose)
+		fprintf(stderr, "NFSv4 mount point detected\n");
+	retval = 1;
+	goto out;
+
+out_nfs:
+	if (verbose)
+		fprintf(stderr, "Legacy NFS mount point detected\n");
+	retval = 0;
+	goto out;
+}
+
 static struct option umount_longopts[] =
 {
   { "force", 0, 0, 'f' },
@@ -364,13 +452,22 @@ int nfsumount(int argc, char *argv[])
 
 	ret = 0;
 	if (mc) {
-		if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 0)
-			/* 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!
-			 */
-			nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
+		if (!lazy) {
+			switch (nfs_umount_is_vers4(mc)) {
+			case 0:
+				/* 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!
+				 */
+				nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
+				break;
+			case 1:
+				break;
+			default:
+				return EX_FAIL;
+			}
+		}
 		ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir) ?: ret;
 	} else if (*spec != '/') {
 		if (!lazy)