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