walters / rpms / nfs-utils

Forked from rpms/nfs-utils 6 years ago
Clone
4af23bc
diff --git a/support/include/conffile.h b/support/include/conffile.h
4af23bc
index 132a149..672020a 100644
4af23bc
--- a/support/include/conffile.h
4af23bc
+++ b/support/include/conffile.h
4af23bc
@@ -34,6 +34,7 @@
4af23bc
 #define _CONFFILE_H_
4af23bc
 
4af23bc
 #include <sys/queue.h>
4af23bc
+#include <ctype.h>
4af23bc
 
4af23bc
 struct conf_list_node {
4af23bc
 	TAILQ_ENTRY(conf_list_node) link;
4af23bc
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
4af23bc
index 9626d42..2d0b143 100644
4af23bc
--- a/tools/nfs-iostat/nfs-iostat.py
4af23bc
+++ b/tools/nfs-iostat/nfs-iostat.py
4af23bc
@@ -1,4 +1,4 @@
4af23bc
-#!/usr/bin/env python
4af23bc
+#!/usr/bin/python
4af23bc
 # -*- python-mode -*-
4af23bc
 """Emulate iostat for NFS mount points using /proc/self/mountstats
4af23bc
 """
4af23bc
@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
4af23bc
 """
4af23bc
 
4af23bc
 import sys, os, time
4af23bc
+from optparse import OptionParser, OptionGroup
4af23bc
 
4af23bc
 Iostats_version = '0.2'
4af23bc
 
4af23bc
@@ -353,6 +354,12 @@ class DeviceData:
4af23bc
         print '\t%7.3f' % rtt_per_op,
4af23bc
         print '\t%7.3f' % exe_per_op
4af23bc
 
4af23bc
+    def ops(self, sample_time):
4af23bc
+        sends = float(self.__rpc_data['rpcsends'])
4af23bc
+        if sample_time == 0:
4af23bc
+            sample_time = float(self.__nfs_data['age'])
4af23bc
+        return (sends / sample_time)
4af23bc
+
4af23bc
     def display_iostats(self, sample_time, which):
4af23bc
         """Display NFS and RPC stats in an iostat-like way
4af23bc
         """
4af23bc
@@ -395,33 +402,6 @@ class DeviceData:
4af23bc
 # Functions
4af23bc
 #
4af23bc
 
4af23bc
-def print_iostat_help(name):
4af23bc
-    print 'usage: %s [ <interval> [ <count> ] ] [ <options> ] [ <mount point> ] ' % name
4af23bc
-    print
4af23bc
-    print ' Version %s' % Iostats_version
4af23bc
-    print
4af23bc
-    print ' Sample iostat-like program to display NFS client per-mount statistics.'
4af23bc
-    print
4af23bc
-    print ' The <interval> parameter specifies the amount of time in seconds between'
4af23bc
-    print ' each report.  The first report contains statistics for the time since each'
4af23bc
-    print ' file system was mounted.  Each subsequent report contains statistics'
4af23bc
-    print ' collected during the interval since the previous report.'
4af23bc
-    print
4af23bc
-    print ' If the <count> parameter is specified, the value of <count> determines the'
4af23bc
-    print ' number of reports generated at <interval> seconds apart.  If the interval'
4af23bc
-    print ' parameter is specified without the <count> parameter, the command generates'
4af23bc
-    print ' reports continuously.'
4af23bc
-    print
4af23bc
-    print ' Options include "--attr", which displays statistics related to the attribute'
4af23bc
-    print ' cache, "--dir", which displays statistics related to directory operations,'
4af23bc
-    print ' and "--page", which displays statistics related to the page cache.'
4af23bc
-    print ' By default, if no option is specified, statistics related to file I/O are'
4af23bc
-    print ' displayed.'
4af23bc
-    print
4af23bc
-    print ' If one or more <mount point> names are specified, statistics for only these'
4af23bc
-    print ' mount points will be displayed.  Otherwise, all NFS mount points on the'
4af23bc
-    print ' client are listed.'
4af23bc
-
4af23bc
 def parse_stats_file(filename):
4af23bc
     """pop the contents of a mountstats file into a dictionary,
4af23bc
     keyed by mount point.  each value object is a list of the
4af23bc
@@ -446,109 +426,198 @@ def parse_stats_file(filename):
4af23bc
 
4af23bc
     return ms_dict
4af23bc
 
4af23bc
-def print_iostat_summary(old, new, devices, time, ac):
4af23bc
-    for device in devices:
4af23bc
-        stats = DeviceData()
4af23bc
-        stats.parse_stats(new[device])
4af23bc
-        if not old:
4af23bc
-            stats.display_iostats(time, ac)
4af23bc
-        else:
4af23bc
+def print_iostat_summary(old, new, devices, time, options):
4af23bc
+    stats = {}
4af23bc
+    diff_stats = {}
4af23bc
+
4af23bc
+    if old:
4af23bc
+        # Trim device list to only include intersection of old and new data,
4af23bc
+        # this addresses umounts due to autofs mountpoints
4af23bc
+        devicelist = filter(lambda x:x in devices,old)
4af23bc
+    else:
4af23bc
+        devicelist = devices
4af23bc
+
4af23bc
+    for device in devicelist:
4af23bc
+        stats[device] = DeviceData()
4af23bc
+        stats[device].parse_stats(new[device])
4af23bc
+        if old:
4af23bc
             old_stats = DeviceData()
4af23bc
             old_stats.parse_stats(old[device])
4af23bc
-            diff_stats = stats.compare_iostats(old_stats)
4af23bc
-            diff_stats.display_iostats(time, ac)
4af23bc
+            diff_stats[device] = stats[device].compare_iostats(old_stats)
4af23bc
+
4af23bc
+    if options.sort:
4af23bc
+        if old:
4af23bc
+            # We now have compared data and can print a comparison
4af23bc
+            # ordered by mountpoint ops per second
4af23bc
+            devicelist.sort(key=lambda x: diff_stats[x].ops(time), reverse=True)
4af23bc
+        else:
4af23bc
+            # First iteration, just sort by newly parsed ops/s
4af23bc
+            devicelist.sort(key=lambda x: stats[x].ops(time), reverse=True)
4af23bc
+
4af23bc
+    count = 1
4af23bc
+    for device in devicelist:
4af23bc
+        if old:
4af23bc
+            diff_stats[device].display_iostats(time, options.which)
4af23bc
+        else:
4af23bc
+            stats[device].display_iostats(time, options.which)
4af23bc
+
4af23bc
+        count += 1
4af23bc
+        if (count > options.list):
4af23bc
+            return
4af23bc
+
4af23bc
+
4af23bc
+def list_nfs_mounts(givenlist, mountstats):
4af23bc
+    """return a list of NFS mounts given a list to validate or
4af23bc
+       return a full list if the given list is empty -
4af23bc
+       may return an empty list if none found
4af23bc
+    """
4af23bc
+    list = []
4af23bc
+    if len(givenlist) > 0:
4af23bc
+        for device in givenlist:
4af23bc
+            stats = DeviceData()
4af23bc
+            stats.parse_stats(mountstats[device])
4af23bc
+            if stats.is_nfs_mountpoint():
4af23bc
+                list += [device]
4af23bc
+    else:
4af23bc
+        for device, descr in mountstats.iteritems():
4af23bc
+            stats = DeviceData()
4af23bc
+            stats.parse_stats(descr)
4af23bc
+            if stats.is_nfs_mountpoint():
4af23bc
+                list += [device]
4af23bc
+    return list
4af23bc
 
4af23bc
 def iostat_command(name):
4af23bc
     """iostat-like command for NFS mount points
4af23bc
     """
4af23bc
     mountstats = parse_stats_file('/proc/self/mountstats')
4af23bc
     devices = []
4af23bc
-    which = 0
4af23bc
+    origdevices = []
4af23bc
     interval_seen = False
4af23bc
     count_seen = False
4af23bc
 
4af23bc
-    for arg in sys.argv:
4af23bc
-        if arg in ['-h', '--help', 'help', 'usage']:
4af23bc
-            print_iostat_help(name)
4af23bc
-            return
4af23bc
-
4af23bc
-        if arg in ['-v', '--version', 'version']:
4af23bc
-            print '%s version %s' % (name, Iostats_version)
4af23bc
-            return
4af23bc
-
4af23bc
-        if arg in ['-a', '--attr']:
4af23bc
-            which = 1
4af23bc
-            continue
4af23bc
-
4af23bc
-        if arg in ['-d', '--dir']:
4af23bc
-            which = 2
4af23bc
-            continue
4af23bc
-
4af23bc
-        if arg in ['-p', '--page']:
4af23bc
-            which = 3
4af23bc
-            continue
4af23bc
+    mydescription= """
4af23bc
+Sample iostat-like program to display NFS client per-mount'
4af23bc
+statistics.  The <interval> parameter specifies the amount of time in seconds
4af23bc
+between each report.  The first report contains statistics for the time since
4af23bc
+each file system was mounted.  Each subsequent report contains statistics
4af23bc
+collected during the interval since the previous report.  If the <count>
4af23bc
+parameter is specified, the value of <count> determines the number of reports
4af23bc
+generated at <interval> seconds apart.  If the interval parameter is specified
4af23bc
+without the <count> parameter, the command generates reports continuously.
4af23bc
+If one or more <mount point> names are specified, statistics for only these
4af23bc
+mount points will be displayed.  Otherwise, all NFS mount points on the
4af23bc
+client are listed.
4af23bc
+"""
4af23bc
+    parser = OptionParser(
4af23bc
+        usage="usage: %prog [ <interval> [ <count> ] ] [ <options> ] [ <mount point> ]",
4af23bc
+        description=mydescription,
4af23bc
+        version='version %s' % Iostats_version)
4af23bc
+    parser.set_defaults(which=0, sort=False, list=sys.maxint)
4af23bc
+
4af23bc
+    statgroup = OptionGroup(parser, "Statistics Options",
4af23bc
+                            'File I/O is displayed unless one of the following is specified:')
4af23bc
+    statgroup.add_option('-a', '--attr',
4af23bc
+                            action="store_const",
4af23bc
+                            dest="which",
4af23bc
+                            const=1,
4af23bc
+                            help='displays statistics related to the attribute cache')
4af23bc
+    statgroup.add_option('-d', '--dir',
4af23bc
+                            action="store_const",
4af23bc
+                            dest="which",
4af23bc
+                            const=2,
4af23bc
+                            help='displays statistics related to directory operations')
4af23bc
+    statgroup.add_option('-p', '--page',
4af23bc
+                            action="store_const",
4af23bc
+                            dest="which",
4af23bc
+                            const=3,
4af23bc
+                            help='displays statistics related to the page cache')
4af23bc
+    parser.add_option_group(statgroup)
4af23bc
+    displaygroup = OptionGroup(parser, "Display Options",
4af23bc
+                               'Options affecting display format:')
4af23bc
+    displaygroup.add_option('-s', '--sort',
4af23bc
+                            action="store_true",
4af23bc
+                            dest="sort",
4af23bc
+                            help="Sort NFS mount points by ops/second")
4af23bc
+    displaygroup.add_option('-l','--list',
4af23bc
+                            action="store",
4af23bc
+                            type="int",
4af23bc
+                            dest="list",
4af23bc
+                            help="only print stats for first LIST mount points")
4af23bc
+    parser.add_option_group(displaygroup)
4af23bc
+
4af23bc
+    (options, args) = parser.parse_args(sys.argv)
4af23bc
+
4af23bc
+    for arg in args:
4af23bc
 
4af23bc
         if arg == sys.argv[0]:
4af23bc
             continue
4af23bc
 
4af23bc
         if arg in mountstats:
4af23bc
-            devices += [arg]
4af23bc
+            origdevices += [arg]
4af23bc
         elif not interval_seen:
4af23bc
-            interval = int(arg)
4af23bc
+            try:
4af23bc
+                interval = int(arg)
4af23bc
+            except:
4af23bc
+                print 'Illegal <interval> value %s' % arg
4af23bc
+                return
4af23bc
             if interval > 0:
4af23bc
                 interval_seen = True
4af23bc
             else:
4af23bc
-                print 'Illegal <interval> value'
4af23bc
+                print 'Illegal <interval> value %s' % arg
4af23bc
                 return
4af23bc
         elif not count_seen:
4af23bc
-            count = int(arg)
4af23bc
+            try:
4af23bc
+                count = int(arg)
4af23bc
+            except:
4af23bc
+                print 'Ilegal <count> value %s' % arg
4af23bc
+                return
4af23bc
             if count > 0:
4af23bc
                 count_seen = True
4af23bc
             else:
4af23bc
-                print 'Illegal <count> value'
4af23bc
+                print 'Illegal <count> value %s' % arg
4af23bc
                 return
4af23bc
 
4af23bc
     # make certain devices contains only NFS mount points
4af23bc
-    if len(devices) > 0:
4af23bc
-        check = []
4af23bc
-        for device in devices:
4af23bc
-            stats = DeviceData()
4af23bc
-            stats.parse_stats(mountstats[device])
4af23bc
-            if stats.is_nfs_mountpoint():
4af23bc
-                check += [device]
4af23bc
-        devices = check
4af23bc
-    else:
4af23bc
-        for device, descr in mountstats.iteritems():
4af23bc
-            stats = DeviceData()
4af23bc
-            stats.parse_stats(descr)
4af23bc
-            if stats.is_nfs_mountpoint():
4af23bc
-                devices += [device]
4af23bc
+    devices = list_nfs_mounts(origdevices, mountstats)
4af23bc
     if len(devices) == 0:
4af23bc
         print 'No NFS mount points were found'
4af23bc
         return
4af23bc
 
4af23bc
+
4af23bc
     old_mountstats = None
4af23bc
     sample_time = 0.0
4af23bc
 
4af23bc
     if not interval_seen:
4af23bc
-        print_iostat_summary(old_mountstats, mountstats, devices, sample_time, which)
4af23bc
+        print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
4af23bc
         return
4af23bc
 
4af23bc
     if count_seen:
4af23bc
         while count != 0:
4af23bc
-            print_iostat_summary(old_mountstats, mountstats, devices, sample_time, which)
4af23bc
+            print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
4af23bc
             old_mountstats = mountstats
4af23bc
             time.sleep(interval)
4af23bc
             sample_time = interval
4af23bc
             mountstats = parse_stats_file('/proc/self/mountstats')
4af23bc
+            # automount mountpoints add and drop, if automount is involved
4af23bc
+            # we need to recheck the devices list when reparsing
4af23bc
+            devices = list_nfs_mounts(origdevices,mountstats)
4af23bc
+            if len(devices) == 0:
4af23bc
+                print 'No NFS mount points were found'
4af23bc
+                return
4af23bc
             count -= 1
4af23bc
     else: 
4af23bc
         while True:
4af23bc
-            print_iostat_summary(old_mountstats, mountstats, devices, sample_time, which)
4af23bc
+            print_iostat_summary(old_mountstats, mountstats, devices, sample_time, options)
4af23bc
             old_mountstats = mountstats
4af23bc
             time.sleep(interval)
4af23bc
             sample_time = interval
4af23bc
             mountstats = parse_stats_file('/proc/self/mountstats')
4af23bc
+            # automount mountpoints add and drop, if automount is involved
4af23bc
+            # we need to recheck the devices list when reparsing
4af23bc
+            devices = list_nfs_mounts(origdevices,mountstats)
4af23bc
+            if len(devices) == 0:
4af23bc
+                print 'No NFS mount points were found'
4af23bc
+                return
4af23bc
 
4af23bc
 #
4af23bc
 # Main
4af23bc
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
4af23bc
index 02239d2..37e2aa5 100644
4af23bc
--- a/utils/gssd/gssd_proc.c
4af23bc
+++ b/utils/gssd/gssd_proc.c
4af23bc
@@ -840,42 +840,48 @@ handle_krb5_upcall(struct clnt_info *clp)
4af23bc
 	}
4af23bc
 	if (create_resp != 0) {
4af23bc
 		if (uid == 0 && root_uses_machine_creds == 1) {
4af23bc
+			int nocache = 0;
4af23bc
 			int success = 0;
4af23bc
-
4af23bc
-			gssd_refresh_krb5_machine_credential(clp->servername,
4af23bc
-							     NULL);
4af23bc
-			/*
4af23bc
-			 * Get a list of credential cache names and try each
4af23bc
-			 * of them until one works or we've tried them all
4af23bc
-			 */
4af23bc
-			if (gssd_get_krb5_machine_cred_list(&credlist)) {
4af23bc
-				printerr(0, "ERROR: No credentials found "
4af23bc
-					 "for connection to server %s\n",
4af23bc
-					 clp->servername);
4af23bc
-					goto out_return_error;
4af23bc
-			}
4af23bc
-			for (ccname = credlist; ccname && *ccname; ccname++) {
4af23bc
-				gssd_setup_krb5_machine_gss_ccache(*ccname);
4af23bc
-				if ((create_auth_rpc_client(clp, &rpc_clnt,
4af23bc
-							    &auth, uid,
4af23bc
-							    AUTHTYPE_KRB5)) == 0) {
4af23bc
-					/* Success! */
4af23bc
-					success++;
4af23bc
-					break;
4af23bc
+			do {
4af23bc
+				gssd_refresh_krb5_machine_credential(clp->servername,
4af23bc
+								     NULL, nocache);
4af23bc
+				/*
4af23bc
+				 * Get a list of credential cache names and try each
4af23bc
+				 * of them until one works or we've tried them all
4af23bc
+				 */
4af23bc
+				if (gssd_get_krb5_machine_cred_list(&credlist)) {
4af23bc
+					printerr(0, "ERROR: No credentials found "
4af23bc
+						 "for connection to server %s\n",
4af23bc
+						 clp->servername);
4af23bc
+						goto out_return_error;
4af23bc
 				}
4af23bc
-				printerr(2, "WARNING: Failed to create krb5 context "
4af23bc
-					 "for user with uid %d with credentials "
4af23bc
-					 "cache %s for server %s\n",
4af23bc
-					 uid, *ccname, clp->servername);
4af23bc
-			}
4af23bc
-			gssd_free_krb5_machine_cred_list(credlist);
4af23bc
-			if (!success) {
4af23bc
-				printerr(1, "WARNING: Failed to create krb5 context "
4af23bc
-					 "for user with uid %d with any "
4af23bc
-					 "credentials cache for server %s\n",
4af23bc
-					 uid, clp->servername);
4af23bc
-				goto out_return_error;
4af23bc
-			}
4af23bc
+				for (ccname = credlist; ccname && *ccname; ccname++) {
4af23bc
+					gssd_setup_krb5_machine_gss_ccache(*ccname);
4af23bc
+					if ((create_auth_rpc_client(clp, &rpc_clnt,
4af23bc
+								    &auth, uid,
4af23bc
+								    AUTHTYPE_KRB5)) == 0) {
4af23bc
+						/* Success! */
4af23bc
+						success++;
4af23bc
+						break;
4af23bc
+					} 
4af23bc
+					printerr(2, "WARNING: Failed to create machine krb5 context "
4af23bc
+						 "with credentials cache %s for server %s\n",
4af23bc
+						 *ccname, clp->servername);
4af23bc
+				}
4af23bc
+				gssd_free_krb5_machine_cred_list(credlist);			
4af23bc
+				if (!success) {
4af23bc
+					if(nocache == 0) {
4af23bc
+						nocache++;
4af23bc
+						printerr(2, "WARNING: Machine cache is prematurely expired or corrupted "
4af23bc
+						            "trying to recreate cache for server %s\n", clp->servername);
4af23bc
+					} else {
4af23bc
+						printerr(1, "WARNING: Failed to create machine krb5 context "
4af23bc
+						 "with any credentials cache for server %s\n",
4af23bc
+						 clp->servername);
4af23bc
+						goto out_return_error;
4af23bc
+					}
4af23bc
+				}
4af23bc
+			} while(!success);
4af23bc
 		} else {
4af23bc
 			printerr(1, "WARNING: Failed to create krb5 context "
4af23bc
 				 "for user with uid %d for server %s\n",
4af23bc
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
4af23bc
index 3009cc5..78e9775 100644
4af23bc
--- a/utils/gssd/krb5_util.c
4af23bc
+++ b/utils/gssd/krb5_util.c
4af23bc
@@ -137,7 +137,7 @@ static int select_krb5_ccache(const struct dirent *d);
4af23bc
 static int gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
4af23bc
 		struct dirent **d);
4af23bc
 static int gssd_get_single_krb5_cred(krb5_context context,
4af23bc
-		krb5_keytab kt, struct gssd_k5_kt_princ *ple);
4af23bc
+		krb5_keytab kt, struct gssd_k5_kt_princ *ple, int nocache);
4af23bc
 static int query_krb5_ccache(const char* cred_cache, char **ret_princname,
4af23bc
 		char **ret_realm);
4af23bc
 
4af23bc
@@ -359,7 +359,8 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
4af23bc
 static int
4af23bc
 gssd_get_single_krb5_cred(krb5_context context,
4af23bc
 			  krb5_keytab kt,
4af23bc
-			  struct gssd_k5_kt_princ *ple)
4af23bc
+			  struct gssd_k5_kt_princ *ple,
4af23bc
+			  int nocache)
4af23bc
 {
4af23bc
 #if HAVE_KRB5_GET_INIT_CREDS_OPT_SET_ADDRESSLESS
4af23bc
 	krb5_get_init_creds_opt *init_opts = NULL;
4af23bc
@@ -379,7 +380,7 @@ gssd_get_single_krb5_cred(krb5_context context,
4af23bc
 
4af23bc
 	memset(&my_creds, 0, sizeof(my_creds));
4af23bc
 
4af23bc
-	if (ple->ccname && ple->endtime > now) {
4af23bc
+	if (ple->ccname && ple->endtime > now && !nocache) {
4af23bc
 		printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
4af23bc
 			 ple->ccname, ple->endtime);
4af23bc
 		code = 0;
4af23bc
@@ -1095,7 +1096,7 @@ gssd_get_krb5_machine_cred_list(char ***list)
4af23bc
 	for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
4af23bc
 		if (ple->ccname) {
4af23bc
 			/* Make sure cred is up-to-date before returning it */
4af23bc
-			retval = gssd_refresh_krb5_machine_credential(NULL, ple);
4af23bc
+			retval = gssd_refresh_krb5_machine_credential(NULL, ple, 0);
4af23bc
 			if (retval)
4af23bc
 				continue;
4af23bc
 			if (i + 1 > listsize) {
4af23bc
@@ -1185,7 +1186,7 @@ gssd_destroy_krb5_machine_creds(void)
4af23bc
  */
4af23bc
 int
4af23bc
 gssd_refresh_krb5_machine_credential(char *hostname,
4af23bc
-				     struct gssd_k5_kt_princ *ple)
4af23bc
+				     struct gssd_k5_kt_princ *ple, int nocache)
4af23bc
 {
4af23bc
 	krb5_error_code code = 0;
4af23bc
 	krb5_context context;
4af23bc
@@ -1240,7 +1241,7 @@ gssd_refresh_krb5_machine_credential(char *hostname,
4af23bc
 			goto out;
4af23bc
 		}
4af23bc
 	}
4af23bc
-	retval = gssd_get_single_krb5_cred(context, kt, ple);
4af23bc
+	retval = gssd_get_single_krb5_cred(context, kt, ple, nocache);
4af23bc
 out:
4af23bc
 	if (kt)
4af23bc
 		krb5_kt_close(context, kt);
4af23bc
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
4af23bc
index 3d39300..4b6b281 100644
4af23bc
--- a/utils/gssd/krb5_util.h
4af23bc
+++ b/utils/gssd/krb5_util.h
4af23bc
@@ -30,7 +30,7 @@ void gssd_free_krb5_machine_cred_list(char **list);
4af23bc
 void gssd_setup_krb5_machine_gss_ccache(char *servername);
4af23bc
 void gssd_destroy_krb5_machine_creds(void);
4af23bc
 int  gssd_refresh_krb5_machine_credential(char *hostname,
4af23bc
-					  struct gssd_k5_kt_princ *ple);
4af23bc
+					  struct gssd_k5_kt_princ *ple, int nocache);
4af23bc
 char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
4af23bc
 void gssd_k5_get_default_realm(char **def_realm);
4af23bc
 
4af23bc
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
4af23bc
index 65a6a2a..573abaa 100644
4af23bc
--- a/utils/idmapd/idmapd.c
4af23bc
+++ b/utils/idmapd/idmapd.c
4af23bc
@@ -139,6 +139,7 @@ static void nametoidres(struct idmap_msg *);
4af23bc
 
4af23bc
 static int nfsdopen(void);
4af23bc
 static int nfsdopenone(struct idmap_client *);
4af23bc
+static void nfsdreopen_one(struct idmap_client *);
4af23bc
 static void nfsdreopen(void);
4af23bc
 
4af23bc
 size_t  strlcat(char *, const char *, size_t);
4af23bc
@@ -502,7 +503,8 @@ nfsdcb(int fd, short which, void *data)
4af23bc
 		xlog_warn("nfsdcb: read(%s) failed: errno %d (%s)",
4af23bc
 			     ic->ic_path, len?errno:0, 
4af23bc
 			     len?strerror(errno):"End of File");
4af23bc
-		goto out;
4af23bc
+		nfsdreopen_one(ic);
4af23bc
+		return;
4af23bc
 	}
4af23bc
 
4af23bc
 	/* Get rid of newline and terminate buffer*/
4af23bc
@@ -514,11 +516,11 @@ nfsdcb(int fd, short which, void *data)
4af23bc
 	/* Authentication name -- ignored for now*/
4af23bc
 	if (getfield(&bp, authbuf, sizeof(authbuf)) == -1) {
4af23bc
 		xlog_warn("nfsdcb: bad authentication name in upcall\n");
4af23bc
-		return;
4af23bc
+		goto out;
4af23bc
 	}
4af23bc
 	if (getfield(&bp, typebuf, sizeof(typebuf)) == -1) {
4af23bc
 		xlog_warn("nfsdcb: bad type in upcall\n");
4af23bc
-		return;
4af23bc
+		goto out;
4af23bc
 	}
4af23bc
 	if (verbose > 0)
4af23bc
 		xlog_warn("nfsdcb: authbuf=%s authtype=%s",
4af23bc
@@ -532,26 +534,26 @@ nfsdcb(int fd, short which, void *data)
4af23bc
 		im.im_conv = IDMAP_CONV_NAMETOID;
4af23bc
 		if (getfield(&bp, im.im_name, sizeof(im.im_name)) == -1) {
4af23bc
 			xlog_warn("nfsdcb: bad name in upcall\n");
4af23bc
-			return;
4af23bc
+			goto out;
4af23bc
 		}
4af23bc
 		break;
4af23bc
 	case IC_IDNAME:
4af23bc
 		im.im_conv = IDMAP_CONV_IDTONAME;
4af23bc
 		if (getfield(&bp, buf1, sizeof(buf1)) == -1) {
4af23bc
 			xlog_warn("nfsdcb: bad id in upcall\n");
4af23bc
-			return;
4af23bc
+			goto out;
4af23bc
 		}
4af23bc
 		tmp = strtoul(buf1, (char **)NULL, 10);
4af23bc
 		im.im_id = (u_int32_t)tmp;
4af23bc
 		if ((tmp == ULONG_MAX && errno == ERANGE)
4af23bc
 				|| (unsigned long)im.im_id != tmp) {
4af23bc
 			xlog_warn("nfsdcb: id '%s' too big!\n", buf1);
4af23bc
-			return;
4af23bc
+			goto out;
4af23bc
 		}
4af23bc
 		break;
4af23bc
 	default:
4af23bc
 		xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which);
4af23bc
-		return;
4af23bc
+		goto out;
4af23bc
 	}
4af23bc
 
4af23bc
 	imconv(ic, &im);
4af23bc
@@ -612,7 +614,7 @@ nfsdcb(int fd, short which, void *data)
4af23bc
 		break;
4af23bc
 	default:
4af23bc
 		xlog_warn("nfsdcb: Unknown which type %d", ic->ic_which);
4af23bc
-		return;
4af23bc
+		goto out;
4af23bc
 	}
4af23bc
 
4af23bc
 	bsiz = sizeof(buf) - bsiz;
4af23bc
diff --git a/utils/mount/mount_config.h b/utils/mount/mount_config.h
4af23bc
index 9a885a9..3023306 100644
4af23bc
--- a/utils/mount/mount_config.h
4af23bc
+++ b/utils/mount/mount_config.h
4af23bc
@@ -20,6 +20,8 @@ inline void mount_config_init(char *);
4af23bc
 
4af23bc
 #ifdef MOUNT_CONFIG
4af23bc
 #include "conffile.h"
4af23bc
+#include "xlog.h"
4af23bc
+
4af23bc
 extern char *conf_get_mntopts(char *, char *, char *);
4af23bc
 
4af23bc
 inline void mount_config_init(char *program)
4af23bc
diff --git a/utils/mount/network.c b/utils/mount/network.c
4af23bc
index f6fa5fd..bd621be 100644
4af23bc
--- a/utils/mount/network.c
4af23bc
+++ b/utils/mount/network.c
4af23bc
@@ -90,6 +90,7 @@ static const char *nfs_transport_opttbl[] = {
4af23bc
 static const char *nfs_version_opttbl[] = {
4af23bc
 	"v2",
4af23bc
 	"v3",
4af23bc
+	"v4",
4af23bc
 	"vers",
4af23bc
 	"nfsvers",
4af23bc
 	NULL,
4af23bc
@@ -1203,7 +1204,7 @@ nfs_nfs_program(struct mount_options *options, unsigned long *program)
4af23bc
  * Returns TRUE if @version contains a valid value for this option,
4af23bc
  * or FALSE if the option was specified with an invalid value.
4af23bc
  */
4af23bc
-static int
4af23bc
+int
4af23bc
 nfs_nfs_version(struct mount_options *options, unsigned long *version)
4af23bc
 {
4af23bc
 	long tmp;
4af23bc
@@ -1215,10 +1216,13 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version)
4af23bc
 	case 1: /* v3 */
4af23bc
 		*version = 3;
4af23bc
 		return 1;
4af23bc
-	case 2:	/* vers */
4af23bc
+	case 2: /* v4 */
4af23bc
+		*version = 4;
4af23bc
+		return 1;
4af23bc
+	case 3:	/* vers */
4af23bc
 		switch (po_get_numeric(options, "vers", &tmp)) {
4af23bc
 		case PO_FOUND:
4af23bc
-			if (tmp >= 2 && tmp <= 3) {
4af23bc
+			if (tmp >= 2 && tmp <= 4) {
4af23bc
 				*version = tmp;
4af23bc
 				return 1;
4af23bc
 			}
4af23bc
@@ -1229,10 +1233,10 @@ nfs_nfs_version(struct mount_options *options, unsigned long *version)
4af23bc
 		case PO_BAD_VALUE:
4af23bc
 			return 0;
4af23bc
 		}
4af23bc
-	case 3: /* nfsvers */
4af23bc
+	case 4: /* nfsvers */
4af23bc
 		switch (po_get_numeric(options, "nfsvers", &tmp)) {
4af23bc
 		case PO_FOUND:
4af23bc
-			if (tmp >= 2 && tmp <= 3) {
4af23bc
+			if (tmp >= 2 && tmp <= 4) {
4af23bc
 				*version = tmp;
4af23bc
 				return 1;
4af23bc
 			}
4af23bc
diff --git a/utils/mount/network.h b/utils/mount/network.h
4af23bc
index db5134c..402e0a5 100644
4af23bc
--- a/utils/mount/network.h
4af23bc
+++ b/utils/mount/network.h
4af23bc
@@ -56,6 +56,7 @@ int clnt_ping(struct sockaddr_in *, const unsigned long,
4af23bc
 
4af23bc
 struct mount_options;
4af23bc
 
4af23bc
+int nfs_nfs_version(struct mount_options *options, unsigned long *version);
4af23bc
 int nfs_options2pmap(struct mount_options *,
4af23bc
 		      struct pmap *, struct pmap *);
4af23bc
 
4af23bc
diff --git a/utils/mount/nfsumount.c b/utils/mount/nfsumount.c
4af23bc
index f81db14..c5505b1 100644
4af23bc
--- a/utils/mount/nfsumount.c
4af23bc
+++ b/utils/mount/nfsumount.c
4af23bc
@@ -179,6 +179,10 @@ static int nfs_umount_do_umnt(struct mount_options *options,
4af23bc
 		return EX_FAIL;
4af23bc
 	}
4af23bc
 
4af23bc
+	/* Skip UMNT call for vers=4 mounts */
4af23bc
+	if (nfs_pmap.pm_vers == 4)
4af23bc
+		return EX_SUCCESS;
4af23bc
+
4af23bc
 	*hostname = nfs_umount_hostname(options, *hostname);
4af23bc
 	if (!*hostname) {
4af23bc
 		nfs_error(_("%s: out of memory"), progname);
4af23bc
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
4af23bc
index a12ace7..3eb661e 100644
4af23bc
--- a/utils/mount/stropts.c
4af23bc
+++ b/utils/mount/stropts.c
4af23bc
@@ -84,6 +84,7 @@ struct nfsmount_info {
4af23bc
 	struct mount_options	*options;	/* parsed mount options */
4af23bc
 	char			**extra_opts;	/* string for /etc/mtab */
4af23bc
 
4af23bc
+	unsigned long		version;	/* NFS version */
4af23bc
 	int			flags,		/* MS_ flags */
4af23bc
 				fake,		/* actually do the mount? */
4af23bc
 				child;		/* forked bg child? */
4af23bc
@@ -272,7 +273,12 @@ static int nfs_validate_options(struct nfsmount_info *mi)
4af23bc
 	if (!nfs_name_to_address(mi->hostname, sap, &salen))
4af23bc
 		return 0;
4af23bc
 
4af23bc
-	if (strncmp(mi->type, "nfs4", 4) == 0) {
4af23bc
+	if (!nfs_nfs_version(mi->options, &mi->version))
4af23bc
+		return 0;
4af23bc
+	if (strncmp(mi->type, "nfs4", 4) == 0)
4af23bc
+		mi->version = 4;
4af23bc
+
4af23bc
+	if (mi->version == 4) {
4af23bc
 		if (!nfs_append_clientaddr_option(sap, salen, mi->options))
4af23bc
 			return 0;
4af23bc
 	} else {
4af23bc
@@ -488,7 +494,7 @@ static int nfs_try_mount(struct nfsmount_info *mi)
4af23bc
 	char *options = NULL;
4af23bc
 	int result;
4af23bc
 
4af23bc
-	if (strncmp(mi->type, "nfs4", 4) != 0) {
4af23bc
+	if (mi->version != 4) {
4af23bc
 		if (!nfs_rewrite_pmap_mount_options(mi->options))
4af23bc
 			return 0;
4af23bc
 	}
4af23bc
diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c
4af23bc
index b59f939..888fd8c 100644
4af23bc
--- a/utils/mountd/mountd.c
4af23bc
+++ b/utils/mountd/mountd.c
4af23bc
@@ -359,6 +359,11 @@ static void set_authflavors(struct mountres3_ok *ok, nfs_export *exp)
4af23bc
 		flavors[i] = s->flav->fnum;
4af23bc
 		i++;
4af23bc
 	}
4af23bc
+	if (i == 0) {
4af23bc
+		/* default when there is no sec= option: */
4af23bc
+		i = 1;
4af23bc
+		flavors[0] = AUTH_UNIX;
4af23bc
+	}
4af23bc
 	ok->auth_flavors.auth_flavors_val = flavors;
4af23bc
 	ok->auth_flavors.auth_flavors_len = i;
4af23bc
 }
4af23bc
diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c
4af23bc
index 650c593..1cda1e5 100644
4af23bc
--- a/utils/nfsd/nfsd.c
4af23bc
+++ b/utils/nfsd/nfsd.c
4af23bc
@@ -27,6 +27,15 @@
4af23bc
 #include "nfssvc.h"
4af23bc
 #include "xlog.h"
4af23bc
 
4af23bc
+/*
4af23bc
+ * IPv6 support for nfsd was finished before some of the other daemons (mountd
4af23bc
+ * and statd in particular). That could be a problem in the future if someone
4af23bc
+ * were to boot a kernel that supports IPv6 serving with  an older nfs-utils. For
4af23bc
+ * now, hardcode the IPv6 switch into the off position until the other daemons
4af23bc
+ * are functional.
4af23bc
+ */
4af23bc
+#undef IPV6_SUPPORTED
4af23bc
+
4af23bc
 static void	usage(const char *);
4af23bc
 
4af23bc
 static struct option longopts[] =
4af23bc
diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c
4af23bc
index ee862b2..12d3253 100644
4af23bc
--- a/utils/nfsd/nfssvc.c
4af23bc
+++ b/utils/nfsd/nfssvc.c
4af23bc
@@ -22,6 +22,15 @@
4af23bc
 #include "nfslib.h"
4af23bc
 #include "xlog.h"
4af23bc
 
4af23bc
+/*
4af23bc
+ * IPv6 support for nfsd was finished before some of the other daemons (mountd
4af23bc
+ * and statd in particular). That could be a problem in the future if someone
4af23bc
+ * were to boot a kernel that supports IPv6 serving with an older nfs-utils. For
4af23bc
+ * now, hardcode the IPv6 switch into the off position until the other daemons
4af23bc
+ * are functional.
4af23bc
+ */
4af23bc
+#undef IPV6_SUPPORTED
4af23bc
+
4af23bc
 #define NFSD_PORTS_FILE     "/proc/fs/nfsd/portlist"
4af23bc
 #define NFSD_VERS_FILE    "/proc/fs/nfsd/versions"
4af23bc
 #define NFSD_THREAD_FILE  "/proc/fs/nfsd/threads"