From 56166bf634b5b5988e6a28f0d754a7b79dac41dc Mon Sep 17 00:00:00 2001 From: Erez Zadok Date: Sat, 17 Sep 2005 22:19:44 +0000 Subject: [PATCH] * libamu/xutil.c (clocktime): newly implemented routine. Uses gettimeofday() each time to return a high-resolution clock time, and does not "cache" the last time. Returns time in seconds, just like the old implementation. If passed a non-null argument, will fill it in with the current time in seconds+microseconds. * libamu/xutil.c: remove actual declaration of clock_valid, and another never-used declaration for xclock_valid. * include/am_utils.h: remove defunct definition of clocktime() macro and clock_valid variable. Add extern for new definition. * libamu/mount_fs.c (mount_fs), hlfsd/homedir.c (homedir, hlfsd_diskspace, hlfsd_getpwent, plt_reset, table_add), hlfsd/hlfsd.c (main, hlfsd_init, reload, cleanup), conf/mtab/mtab_mach3.c (open_locked_mtab), conf/mtab/mtab_file.c (open_locked_mtab), amd/nfs_start.c (do_select, run_rpc), amd/autil.c (host_normalize): remove defunct clock_valid. * amd/nfs_subr.c (nfsproc_getattr_2_svc): Print microseconds for node's mtime. (fh_to_mp3): use new clocktime() to update mtime and get a better time resolution. * amd/mapc.c (mapc_reload_map): change prototype from returning void to returning an int. If reloading was needed and succeeded, return 1; else return 0. (mapc_sync): update mtime of parent node if needed. This is a CRITICAL FIX, to ensure that the kernel flushes its DNLC/dcache when we run "amq -f" manually or when a map is reloaded. * amd/map.c (new_ttl): update am_ttl and na_atime in one shot. (init_map): use new clocktime(). (unmount_mp): if the OS doesn't support a "symttl" option, then update the mtime of the parent node using the clocktime(); but if the time hasn't gotten changed because of rapid Amd accesses on systems that don't have a micro-second NFS-client resolution, then increment mtime by one arbitrarily (this could, on some systems and under pathological cases, result in mtime's that are in the future). * amd/autil.c (forcibly_timeout_mp): MAJOR BUG FIX: force mtime update of parent dir, to prevent DNLC/dcache from caching the old entry, which could result in ESTALE errors, bad symlinks, and more. (am_mounted): record mount time, and update am_stats at the same time, using the double-action redone clocktime() routine. (am_mounted): update parent's mtime from that of the child. (am_unmounted): when unmounting an entry, update mtime of parent node. * amd/amfs_generic.c (amfs_bgmount): now that clocktime() doesn't remember it's last non-zero value, save it in a temporary variable to avoid a TOCTOU problem (between an "if" and a "dlog"). * libamu/xutil.c (show_time_host_and_name), conf/autofs/autofs_linux.c (autofs_mounted, autofs_timeout_mp), amd/srvr_nfs.c (nfs_keepalive_callback, nfs_keepalive_timeout) (find_nfs_srvr), amd/rpc_fwd.c (fwd_alloc), amd/nfs_subr.c (nfsproc_getattr_2_svc), amd/nfs_start.c (do_select, run_rpc), amd/mapc.c (root_init), amd/map.c(map_flush_srvr, timeout_mp), amd/info_ndbm.c (ndbm_init), amd/info_ldap.c (amu_ldap_rebind), amd/info_file.c (file_open), amd/info_exec.c (fgets_timed, exec_search), amd/clock.c (timeout, softclock), amd/autil.c (forcibly_timeout_mp), amd/amfs_generic.c (amfs_retry, amfs_bgmount, amfs_generic_mount_child), amd/amd.c (main): pass NULL to clocktime(). --- ChangeLog | 70 ++++++++++++++++++++++++++++++++++++++ NEWS | 25 +++++++++++++- amd/amd.c | 2 +- amd/amfs_generic.c | 11 +++--- amd/autil.c | 19 +++++++---- amd/clock.c | 6 ++-- amd/info_exec.c | 6 ++-- amd/info_file.c | 2 +- amd/info_ldap.c | 2 +- amd/info_ndbm.c | 2 +- amd/map.c | 22 +++++++----- amd/mapc.c | 58 ++++++++++++++++++++----------- amd/nfs_start.c | 12 +++---- amd/nfs_subr.c | 9 ++--- amd/rpc_fwd.c | 2 +- amd/srvr_nfs.c | 8 ++--- conf/autofs/autofs_linux.c | 4 +-- conf/mtab/mtab_file.c | 1 - conf/mtab/mtab_mach3.c | 1 - hlfsd/hlfsd.c | 10 ------ hlfsd/homedir.c | 10 ------ include/am_utils.h | 5 +-- libamu/mount_fs.c | 2 -- libamu/xutil.c | 36 ++++++++++++++++---- vers.m4 | 2 +- 25 files changed, 222 insertions(+), 105 deletions(-) diff --git a/ChangeLog b/ChangeLog index 45c5d7c..19c08db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,73 @@ +2005-09-17 Erez Zadok + + * libamu/xutil.c (clocktime): newly implemented routine. Uses + gettimeofday() each time to return a high-resolution clock time, + and does not "cache" the last time. Returns time in seconds, just + like the old implementation. If passed a non-null argument, will + fill it in with the current time in seconds+microseconds. + + * libamu/xutil.c: remove actual declaration of clock_valid, and + another never-used declaration for xclock_valid. + + * include/am_utils.h: remove defunct definition of clocktime() + macro and clock_valid variable. Add extern for new definition. + + * libamu/mount_fs.c (mount_fs), hlfsd/homedir.c (homedir, + hlfsd_diskspace, hlfsd_getpwent, plt_reset, table_add), + hlfsd/hlfsd.c (main, hlfsd_init, reload, cleanup), + conf/mtab/mtab_mach3.c (open_locked_mtab), conf/mtab/mtab_file.c + (open_locked_mtab), amd/nfs_start.c (do_select, run_rpc), + amd/autil.c (host_normalize): remove defunct clock_valid. + + * amd/nfs_subr.c (nfsproc_getattr_2_svc): Print microseconds for + node's mtime. + (fh_to_mp3): use new clocktime() to update mtime and get a better + time resolution. + + * amd/mapc.c (mapc_reload_map): change prototype from returning + void to returning an int. If reloading was needed and succeeded, + return 1; else return 0. + (mapc_sync): update mtime of parent node if needed. This is a + CRITICAL FIX, to ensure that the kernel flushes its DNLC/dcache + when we run "amq -f" manually or when a map is reloaded. + + * amd/map.c (new_ttl): update am_ttl and na_atime in one shot. + (init_map): use new clocktime(). + (unmount_mp): if the OS doesn't support a "symttl" option, then + update the mtime of the parent node using the clocktime(); but if + the time hasn't gotten changed because of rapid Amd accesses on + systems that don't have a micro-second NFS-client resolution, then + increment mtime by one arbitrarily (this could, on some systems + and under pathological cases, result in mtime's that are in the + future). + + * amd/autil.c (forcibly_timeout_mp): MAJOR BUG FIX: force mtime + update of parent dir, to prevent DNLC/dcache from caching the old + entry, which could result in ESTALE errors, bad symlinks, and + more. + (am_mounted): record mount time, and update am_stats at the same + time, using the double-action redone clocktime() routine. + (am_mounted): update parent's mtime from that of the child. + (am_unmounted): when unmounting an entry, update mtime of parent + node. + + * amd/amfs_generic.c (amfs_bgmount): now that clocktime() doesn't + remember it's last non-zero value, save it in a temporary variable + to avoid a TOCTOU problem (between an "if" and a "dlog"). + + * libamu/xutil.c (show_time_host_and_name), + conf/autofs/autofs_linux.c (autofs_mounted, autofs_timeout_mp), + amd/srvr_nfs.c (nfs_keepalive_callback, nfs_keepalive_timeout) + (find_nfs_srvr), amd/rpc_fwd.c (fwd_alloc), amd/nfs_subr.c + (nfsproc_getattr_2_svc), amd/nfs_start.c (do_select, run_rpc), + amd/mapc.c (root_init), amd/map.c(map_flush_srvr, timeout_mp), + amd/info_ndbm.c (ndbm_init), amd/info_ldap.c (amu_ldap_rebind), + amd/info_file.c (file_open), amd/info_exec.c (fgets_timed, + exec_search), amd/clock.c (timeout, softclock), amd/autil.c + (forcibly_timeout_mp), amd/amfs_generic.c (amfs_retry, + amfs_bgmount, amfs_generic_mount_child), amd/amd.c (main): pass + NULL to clocktime(). + 2005-09-07 Erez Zadok * minor new port: powerpc-apple-darwin8.2.0. diff --git a/NEWS b/NEWS index a6d53ff..d84695c 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,27 @@ -*** Notes specific to am-utils version 6.1.2-rc1 +*** Notes specific to am-utils version 6.1.2 + +MAJOR BUG FIXES: Synchronize Amd's view of its file systems with the +kernel's NFS client-side DNLC/dcache. Amd changes its view when it reloads +maps (automatically or via "amq -f") because new map entries could be added, +old one removed, or existing ones changed. Amd also changes its view when a +simple entry has expired and was flushed, or was forced out via "amq -u". +Amd was not updating the mtime of its parent directory (often the amd +automount point): this resulted in the kernel re-using cached entries, which +are now possibly stale. Many users had seen this problem in the form of +occasional ESTALE errors, or dangling/broken automounted symlinks, +especially on systems under heavy use. To tell the kernel to ignore (flush) +its old entries for an directory, the mtime of the directory must be updated +(monotonically incremented). Amd was indeed doing so in several places, but +unfortunately it was using time(2) which only provides a one-second +resolution clock: this was fine a decade ago, but not good enough on today's +fast systems; using only a one-second resolution clock meant that on busy +systems that invoke Amd many times a second, some rapidly changing entries +do not get flushed from the kernel, and the kernel thus uses stale entries. +The solution to all of these was to rework the whole clock timer updates to +use gettimeofday(), using a micro-second resolution timer, and to use that +time whenever Amd needs to update an mtime/atime/ctime of any node. +Finally, we now update the mtime in places that were never updated before +(when a whole map is flushed or a single entry times out). - minor new ports: i386-pc-linux-deb3.1 diff --git a/amd/amd.c b/amd/amd.c index ead5ac2..cbac56d 100644 --- a/amd/amd.c +++ b/amd/amd.c @@ -551,7 +551,7 @@ main(int argc, char *argv[]) do_memory_locking(); } - do_mapc_reload = clocktime() + gopt.map_reload_interval; + do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval; /* * Register automounter with system. diff --git a/amd/amfs_generic.c b/amd/amfs_generic.c index 1330ed4..f60a22c 100644 --- a/amd/amfs_generic.c +++ b/amd/amfs_generic.c @@ -598,7 +598,7 @@ amfs_retry(int rc, int term, opaque_t arg) new_ttl(mp); - if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime()) { + if ((cp->start + ALLOWED_MOUNT_TIME) < clocktime(NULL)) { /* * The entire mount has timed out. Set the error code and skip past all * the mntfs's so that amfs_bgmount will not have any more @@ -789,8 +789,9 @@ amfs_bgmount(struct continuation *cp) * has not expired. */ int i = atoi(mf->mf_fo->opt_delay); - if (i > 0 && clocktime() < (cp->start + i)) { - dlog("Mount of %s delayed by %lds", mf->mf_mount, (long) (i - clocktime() + cp->start)); + time_t now = clocktime(NULL); + if (i > 0 && now < (cp->start + i)) { + dlog("Mount of %s delayed by %lds", mf->mf_mount, (long) (i - now + cp->start)); goto retry; } } @@ -855,7 +856,7 @@ amfs_bgmount(struct continuation *cp) cp->callout = timeout(RETRY_INTERVAL, wakeup, (opaque_t) get_mntfs_wchan(mf)); - mp->am_ttl = clocktime() + RETRY_INTERVAL; + mp->am_ttl = clocktime(NULL) + RETRY_INTERVAL; /* * Not done yet - so don't return anything @@ -1082,7 +1083,7 @@ amfs_generic_mount_child(am_node *new_mp, int *error_return) cp->callout = 0; cp->mp = new_mp; cp->retry = TRUE; - cp->start = clocktime(); + cp->start = clocktime(NULL); cp->mf = new_mp->am_mfarray; /* diff --git a/amd/autil.c b/amd/autil.c index 7a42151..755db79 100644 --- a/amd/autil.c +++ b/amd/autil.c @@ -201,7 +201,6 @@ host_normalize(char **chp) */ if (gopt.flags & CFM_NORMALIZE_HOSTNAMES) { struct hostent *hp; - clock_valid = 0; hp = gethostbyname(*chp); if (hp && hp->h_addrtype == AF_INET) { dlog("Hostname %s normalized to %s", *chp, hp->h_name); @@ -244,7 +243,13 @@ forcibly_timeout_mp(am_node *mp) } else { plog(XLOG_INFO, "\"%s\" forcibly timed out", mp->am_path); mp->am_flags &= ~AMF_NOTIMEOUT; - mp->am_ttl = clocktime(); + mp->am_ttl = clocktime(NULL); + /* + * Force mtime update of parent dir, to prevent DNLC/dcache from caching + * the old entry, which could result in ESTALE errors, bad symlinks, and + * more. + */ + clocktime(&mp->am_parent->am_fattr.na_mtime); reschedule_timeout_mp(); } } @@ -378,16 +383,16 @@ am_mounted(am_node *mp) mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mf->mf_mount); /* - * Record mount time + * Record mount time, and update am_stats at the same time. */ - mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime(); + mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime); new_ttl(mp); /* - * Update mtime of parent node + * Update mtime of parent node (copying "struct nfstime" in '=' below) */ if (mp->am_parent && mp->am_parent->am_mnt) - mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime; + mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime; /* * This is ugly, but essentially unavoidable @@ -769,7 +774,7 @@ am_unmounted(am_node *mp) * Update mtime of parent node */ if (mp->am_parent && mp->am_parent->am_mnt) - mp->am_parent->am_fattr.na_mtime.nt_seconds = clocktime(); + clocktime(&mp->am_parent->am_fattr.na_mtime); if (mp->am_flags & AMF_REMOUNT) { char *fname = strdup(mp->am_name); diff --git a/amd/clock.c b/amd/clock.c index ff4adf2..bc5f7d9 100644 --- a/amd/clock.c +++ b/amd/clock.c @@ -119,13 +119,13 @@ free_callout(callout *cp) /* * Schedule a callout. * - * (*fn)(fn_arg) will be called at clocktime() + secs + * (*fn)(fn_arg) will be called at clocktime(NULL) + secs */ int timeout(u_int secs, callout_fun *fn, opaque_t fn_arg) { callout *cp, *cp2; - time_t t = clocktime() + secs; + time_t t = clocktime(NULL) + secs; /* * Allocate and fill in a new callout structure @@ -208,7 +208,7 @@ softclock(void) if (task_notify_todo) do_task_notify(); - now = clocktime(); + now = clocktime(NULL); /* * While there are more callouts waiting... diff --git a/amd/info_exec.c b/amd/info_exec.c index 74d2619..0d87451 100644 --- a/amd/info_exec.c +++ b/amd/info_exec.c @@ -78,7 +78,7 @@ fgets_timed(char *s, int size, int rdfd, int secs) if (size == 0) return s; - start = clocktime(); + start = clocktime(NULL); while (s[i] != '\n' && i < size-1) { s[i+1] = 0; /* places the requisite trailing '\0' */ @@ -99,7 +99,7 @@ fgets_timed(char *s, int size, int rdfd, int secs) } timeo.tv_usec = 0; - now = clocktime() - start; + now = clocktime(NULL) - start; if (secs <= 0) timeo.tv_sec = 0; else if (now < secs) @@ -413,7 +413,7 @@ exec_search(mnt_map *m, char *map, char *key, char **pval, time_t *tp) if (mapfd >= 0) { if (tp) - *tp = clocktime(); + *tp = clocktime(NULL); return exec_parse_qanswer(mapfd, map, key, pval, tp); } diff --git a/amd/info_file.c b/amd/info_file.c index a961e69..9f242e5 100644 --- a/amd/info_file.c +++ b/amd/info_file.c @@ -197,7 +197,7 @@ file_open(char *map, time_t *tp) if (mapf && tp) { struct stat stb; if (fstat(fileno(mapf), &stb) < 0) - *tp = clocktime(); + *tp = clocktime(NULL); else *tp = stb.st_mtime; } diff --git a/amd/info_ldap.c b/amd/info_ldap.c index 9da26c2..6cc80fc 100644 --- a/amd/info_ldap.c +++ b/amd/info_ldap.c @@ -276,7 +276,7 @@ amu_ldap_rebind(ALD *a) LDAP *ld; HE_ENT *h; CR *c = a->credentials; - time_t now = clocktime(); + time_t now = clocktime(NULL); int try; dlog("-> amu_ldap_rebind\n"); diff --git a/amd/info_ndbm.c b/amd/info_ndbm.c index aed668e..d783500 100644 --- a/amd/info_ndbm.c +++ b/amd/info_ndbm.c @@ -123,7 +123,7 @@ ndbm_init(mnt_map *m, char *map, time_t *tp) error = fstat(dbm_pagfno(db), &stb); #endif /* not DBM_SUFFIX */ if (error < 0) - *tp = clocktime(); + *tp = clocktime(NULL); else *tp = stb.st_mtime; dbm_close(db); diff --git a/amd/map.c b/amd/map.c index 47279de..c977ed9 100644 --- a/amd/map.c +++ b/amd/map.c @@ -367,8 +367,7 @@ void new_ttl(am_node *mp) { mp->am_timeo_w = 0; - mp->am_ttl = clocktime(); - mp->am_fattr.na_atime.nt_seconds = mp->am_ttl; + mp->am_ttl = clocktime(&mp->am_fattr.na_atime); mp->am_ttl += mp->am_timeo; /* sun's -tl option */ } @@ -423,8 +422,8 @@ init_map(am_node *mp, char *dir) mp->am_fattr = gen_fattr; mp->am_fattr.na_fsid = 42; mp->am_fattr.na_fileid = mp->am_gen; - mp->am_fattr.na_atime.nt_seconds = clocktime(); - mp->am_fattr.na_atime.nt_useconds = 0; + clocktime(&mp->am_fattr.na_atime); + /* next line copies a "struct nfstime" among several fields */ mp->am_fattr.na_mtime = mp->am_fattr.na_ctime = mp->am_fattr.na_atime; new_ttl(mp); @@ -587,7 +586,7 @@ map_flush_srvr(fserver *fs) am_node *mp = exported_ap[i]; if (mp && mp->am_mnt && mp->am_mnt->mf_server == fs) { plog(XLOG_INFO, "Flushed %s; dependent on %s", mp->am_path, fs->fs_host); - mp->am_ttl = clocktime(); + mp->am_ttl = clocktime(NULL); done = 1; } } @@ -894,11 +893,16 @@ unmount_mp(am_node *mp) * symlink-cache at mount time (such as Irix 5.x and 6.x). -Erez. * * Additionally, Linux currently ignores the nt_useconds field, - * so we must update the nt_seconds field every time. + * so we must update the nt_seconds field every time if clocktime(NULL) + * didn't return a new number of seconds. */ - if (mp->am_parent) + if (mp->am_parent) { + time_t last = mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds; + clocktime(&mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime); /* defensive programming... can't we assert the above condition? */ - mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds++; + if (last == mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds) + mp->am_parent->am_attr.ns_u.ns_attr_u.na_mtime.nt_seconds++; + } #endif /* not MNT2_NFS_OPT_SYMTTL */ if (mf->mf_refc == 1 && !FSRV_ISUP(mf->mf_server)) { @@ -942,7 +946,7 @@ timeout_mp(opaque_t v) /* argument not used?! */ { int i; time_t t = NEVER; - time_t now = clocktime(); + time_t now = clocktime(NULL); int backoff = NumChildren / 4; dlog("Timing out automount points..."); diff --git a/amd/mapc.c b/amd/mapc.c index 00d9bf5..8395492 100644 --- a/amd/mapc.c +++ b/amd/mapc.c @@ -514,11 +514,12 @@ mapc_find_wildcard(mnt_map *m) * Do a map reload. * Attempt to reload without losing current data by switching the hashes * round. + * If reloading was needed and succeeded, return 1; else return 0. */ -static void +static int mapc_reload_map(mnt_map *m) { - int error; + int error, ret = 0; kv *maphash[NKVHASH], *tmphash[NKVHASH]; time_t t; @@ -536,7 +537,7 @@ mapc_reload_map(mnt_map *m) plog(XLOG_INFO, "reload of map %s is not needed (in sync)", m->map_name); dlog("map %s last load time is %d, last modify time is %d", m->map_name, (int) m->modify, (int) t); - return; + return ret; } } @@ -565,6 +566,7 @@ mapc_reload_map(mnt_map *m) mapc_clear(m); memcpy((voidp) m->kvhash, (voidp) tmphash, sizeof(m->kvhash)); m->modify = t; + ret = 1; } m->wildcard = 0; @@ -572,6 +574,7 @@ mapc_reload_map(mnt_map *m) error = mapc_search(m, wildcard, &m->wildcard); if (error) m->wildcard = 0; + return ret; } @@ -929,25 +932,42 @@ mapc_search(mnt_map *m, char *key, char **pval) static void mapc_sync(mnt_map *m) { - if (m->alloc != MAPC_ROOT) { + int need_mtime_update = 0; - /* do not clear map if map service is down */ - if (m->isup) { - if (!((*m->isup)(m, m->map_name))) { - plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name); - return; - } + if (m->alloc == MAPC_ROOT) + return; /* nothing to do */ + + /* do not clear map if map service is down */ + if (m->isup) { + if (!((*m->isup)(m, m->map_name))) { + plog(XLOG_ERROR, "mapc_sync: map %s is down: not clearing map", m->map_name); + return; } + } - if (m->alloc >= MAPC_ALL) { - /* mapc_reload_map() always works */ - mapc_reload_map(m); + if (m->alloc >= MAPC_ALL) { + /* mapc_reload_map() always works */ + need_mtime_update = mapc_reload_map(m); + } else { + mapc_clear(m); + /* + * Attempt to find the wildcard entry + */ + mapc_find_wildcard(m); + need_mtime_update = 1; /* because mapc_clear always works */ + } + + /* + * To be safe, update the mtime of the mnt_map's own node, so that the + * kernel will flush all of its cached entries. + */ + if (need_mtime_update && m->cfm) { + am_node *mp = find_ap(m->cfm->cfm_dir); + if (mp) { + clocktime(&mp->am_fattr.na_mtime); } else { - mapc_clear(m); - /* - * Attempt to find the wildcard entry - */ - mapc_find_wildcard(m); + plog(XLOG_ERROR, "cannot find map %s to update its mtime", + m->cfm->cfm_dir); } } } @@ -984,7 +1004,7 @@ mapc_reload(void) static int root_init(mnt_map *m, char *map, time_t *tp) { - *tp = clocktime(); + *tp = clocktime(NULL); return STREQ(map, ROOT_MAP) ? 0 : ENOENT; } diff --git a/amd/nfs_start.c b/amd/nfs_start.c index f9acb97..9268674 100644 --- a/amd/nfs_start.c +++ b/amd/nfs_start.c @@ -121,10 +121,6 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp) errno = EINTR; } else { select_intr_valid = 1; - /* - * Invalidate the current clock value - */ - clock_valid = 0; /* * Allow interrupts. If a signal * occurs, then it will cause a longjmp @@ -152,9 +148,9 @@ do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp) /* * Perhaps reload the cache? */ - if (do_mapc_reload < clocktime()) { + if (do_mapc_reload < clocktime(NULL)) { mapc_reload(); - do_mapc_reload = clocktime() + gopt.map_reload_interval; + do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval; } return nsel; } @@ -195,7 +191,7 @@ run_rpc(void) int smask = sigblock(MASKED_SIGS); #endif /* not HAVE_SIGACTION */ - next_softclock = clocktime(); + next_softclock = clocktime(NULL); amd_state = Run; @@ -228,7 +224,7 @@ run_rpc(void) * If the full timeout code is not called, * then recompute the time delta manually. */ - now = clocktime(); + now = clocktime(NULL); if (next_softclock <= now) { if (amd_state == Finishing) diff --git a/amd/nfs_subr.c b/amd/nfs_subr.c index 94e2547..7d04f8f 100644 --- a/amd/nfs_subr.c +++ b/amd/nfs_subr.c @@ -131,7 +131,7 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) static nfsattrstat res; am_node *mp; int retry; - time_t now = clocktime(); + time_t now = clocktime(NULL); if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "getattr:"); @@ -151,10 +151,11 @@ nfsproc_getattr_2_svc(am_nfs_fh *argp, struct svc_req *rqstp) res = mp->am_attr; if (amuDebug(D_TRACE)) - plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld", + plog(XLOG_DEBUG, "\tstat(%s), size = %d, mtime=%ld.%ld", mp->am_path, (int) res.ns_u.ns_attr_u.na_size, - (long) res.ns_u.ns_attr_u.na_mtime.nt_seconds); + (long) res.ns_u.ns_attr_u.na_mtime.nt_seconds, + (long) res.ns_u.ns_attr_u.na_mtime.nt_useconds); /* Delay unmount of what was looked up */ if (mp->am_timeo_w < 4 * gopt.am_timeo_w) @@ -698,7 +699,7 @@ fh_to_mp3(am_nfs_fh *fhp, int *rp, int vop) * With any luck the kernel will re-stat * the child node and get new information. */ - orig_ap->am_fattr.na_mtime.nt_seconds = clocktime(); + clocktime(&orig_ap->am_fattr.na_mtime); /* * Call the parent's lookup routine for an object diff --git a/amd/rpc_fwd.c b/amd/rpc_fwd.c index ae7aa0e..5363167 100644 --- a/amd/rpc_fwd.c +++ b/amd/rpc_fwd.c @@ -93,7 +93,7 @@ static u_int xid; static rpc_forward * fwd_alloc(void) { - time_t now = clocktime(); + time_t now = clocktime(NULL); rpc_forward *p = 0, *p2; /* diff --git a/amd/srvr_nfs.c b/amd/srvr_nfs.c index a1355b9..37fc24c 100644 --- a/amd/srvr_nfs.c +++ b/amd/srvr_nfs.c @@ -409,7 +409,7 @@ nfs_keepalive_callback(voidp pkt, int len, struct sockaddr_in *sp, struct sockad /* * Update ttl for this server */ - np->np_ttl = clocktime() + + np->np_ttl = clocktime(NULL) + (MAX_ALLOWED_PINGS - 1) * FAST_NFS_PING + fs->fs_pinger - 1; /* @@ -503,7 +503,7 @@ nfs_keepalive_timeout(voidp v) /* * If ttl has expired then guess that it is dead */ - if (np->np_ttl < clocktime()) { + if (np->np_ttl < clocktime(NULL)) { int oflags = fs->fs_flags; dlog("ttl has expired"); if ((fs->fs_flags & FSF_DOWN) == 0) { @@ -970,7 +970,7 @@ no_dns: * after MAX_ALLOWED_PINGS of the fast variety * have failed. */ - np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime() - 1; + np->np_ttl = MAX_ALLOWED_PINGS * FAST_NFS_PING + clocktime(NULL) - 1; start_nfs_pings(fs, pingval); if (fserver_is_down) fs->fs_flags |= FSF_VALID | FSF_DOWN; @@ -1021,7 +1021,7 @@ no_dns: * Initially the server will be deemed dead after * MAX_ALLOWED_PINGS of the fast variety have failed. */ - np->np_ttl = clocktime() + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1; + np->np_ttl = clocktime(NULL) + MAX_ALLOWED_PINGS * FAST_NFS_PING - 1; fs->fs_private = (voidp) np; fs->fs_prfree = (void (*)(voidp)) free; diff --git a/conf/autofs/autofs_linux.c b/conf/autofs/autofs_linux.c index 16bee0a..387c224 100644 --- a/conf/autofs/autofs_linux.c +++ b/conf/autofs/autofs_linux.c @@ -180,7 +180,7 @@ autofs_mounted(am_node *mp) plog(XLOG_ERROR, "AUTOFS_IOC_SETTIMEOUT: %s", strerror(errno)); /* tell the daemon to call us for expirations */ - mp->am_autofs_ttl = clocktime() + gopt.am_timeo_w; + mp->am_autofs_ttl = clocktime(NULL) + gopt.am_timeo_w; } @@ -808,7 +808,7 @@ static int autofs_timeout_mp_task(void *arg) void autofs_timeout_mp(am_node *mp) { autofs_fh_t *fh = mp->am_autofs_fh; - time_t now = clocktime(); + time_t now = clocktime(NULL); /* update the ttl */ mp->am_autofs_ttl = now + gopt.am_timeo_w; diff --git a/conf/mtab/mtab_file.c b/conf/mtab/mtab_file.c index 4d2201e..cddf6b3 100644 --- a/conf/mtab/mtab_file.c +++ b/conf/mtab/mtab_file.c @@ -129,7 +129,6 @@ again: endmntent(mfp); mfp = 0; } - clock_valid = 0; if (stat(mnttabname, &st_before) < 0) { plog(XLOG_ERROR, "%s: stat: %m", mnttabname); if (errno == ESTALE) { diff --git a/conf/mtab/mtab_mach3.c b/conf/mtab/mtab_mach3.c index 51d9790..261455a 100644 --- a/conf/mtab/mtab_mach3.c +++ b/conf/mtab/mtab_mach3.c @@ -127,7 +127,6 @@ again: endmntent(mfp); mfp = 0; } - clock_valid = 0; if (stat(mnttabname, &st_before) < 0) { plog(XLOG_ERROR, "%s: stat: %m", mnttabname); if (errno == ESTALE) { diff --git a/hlfsd/hlfsd.c b/hlfsd/hlfsd.c index c81d64f..f5dca3f 100644 --- a/hlfsd/hlfsd.c +++ b/hlfsd/hlfsd.c @@ -336,8 +336,6 @@ main(int argc, char *argv[]) exit(3); } - clock_valid = 0; /* invalidate logging clock */ - if (!forcefast) { /* make sure mount point exists and is at least mode 555 */ if (stat(dir_name, &stmodes) < 0) @@ -571,8 +569,6 @@ main(int argc, char *argv[]) *************************************************************************/ compute_automounter_nfs_args(&nfs_args, &mnt); - clock_valid = 0; /* invalidate logging clock */ - /* * For some reason, this mount may have to be done in the background, if I am * using -D daemon. I suspect that the actual act of mounting requires @@ -639,8 +635,6 @@ hlfsd_init(void) struct sigaction sa; #endif /* HAVE_SIGACTION */ - clock_valid = 0; /* invalidate logging clock */ - /* * Initialize file handles. */ @@ -780,8 +774,6 @@ reload(int signum) int child; int status; - clock_valid = 0; /* invalidate logging clock */ - if (getpid() != masterpid) return; @@ -833,8 +825,6 @@ cleanup(int signum) struct stat stbuf; int umount_result; - clock_valid = 0; /* invalidate logging clock */ - if (!amuDebug(D_DAEMON)) { if (getpid() != masterpid) return; diff --git a/hlfsd/homedir.c b/hlfsd/homedir.c index 18374a7..0a6f6c8 100644 --- a/hlfsd/homedir.c +++ b/hlfsd/homedir.c @@ -89,8 +89,6 @@ homedir(int userid, int groupid) struct stat homestat; int old_groupid, old_userid; - clock_valid = 0; /* invalidate logging clock */ - if ((found = plt_search(userid)) == (uid2home_t *) NULL) { return alt_spooldir; /* use alt spool for unknown uid */ } @@ -229,8 +227,6 @@ hlfsd_diskspace(char *path) char buf[MAXPATHLEN]; int fd, len; - clock_valid = 0; /* invalidate logging clock */ - sprintf(buf, "%s/._hlfstmp_%lu", path, (long) getpid()); if ((fd = open(buf, O_RDWR | O_CREAT, 0600)) < 0) { plog(XLOG_ERROR, "cannot open %s: %m", buf); @@ -484,8 +480,6 @@ hlfsd_getpwent(void) return getpwent(); } - clock_valid = 0; /* invalidate logging clock */ - /* return here to read another entry */ readent: @@ -594,8 +588,6 @@ plt_reset(void) { int i; - clock_valid = 0; /* invalidate logging clock */ - hlfsd_setpwent(); if (hlfsd_getpwent() == (struct passwd *) NULL) { hlfsd_endpwent(); @@ -640,8 +632,6 @@ table_add(u_int u, const char *h, const char *n) { int i; - clock_valid = 0; /* invalidate logging clock */ - if (max_pwtab_num <= 0) { /* was never initialized */ max_pwtab_num = 1; pwtab = (uid2home_t *) xmalloc(max_pwtab_num * diff --git a/include/am_utils.h b/include/am_utils.h index 24b193f..5d7a168 100644 --- a/include/am_utils.h +++ b/include/am_utils.h @@ -112,8 +112,6 @@ #define XLOG_DEFSTR "all,nomap,nostats" /* Default log options */ #define XLOG_ALL (XLOG_FATAL|XLOG_ERROR|XLOG_USER|XLOG_WARNING|XLOG_INFO|XLOG_MAP|XLOG_STATS) -#define clocktime() (clock_valid ? clock_valid : time(&clock_valid)) - #define NO_SUBNET "notknown" /* default subnet name for no subnet */ #define NEXP_AP (1022) /* gdmr: was 254 */ #define NEXP_AP_MARGIN (128) /* ???? not used */ @@ -267,7 +265,6 @@ extern int xlog_level_init; extern serv_state amd_state; /* Should we go now */ extern struct in_addr myipaddr; /* (An) IP address of this host */ extern struct opt_tab xlog_opt[]; -extern time_t clock_valid; /* Clock needs recalculating */ extern u_short nfs_port; /* Our NFS service port */ /* @@ -334,7 +331,7 @@ extern u_long get_nfs_version(char *host, struct sockaddr_in *sin, u_long nfs_ve extern long get_server_pid(void); extern int xsnprintf(char *str, size_t size, const char *format, ...); extern void setup_sighandler(int signum, void (*handler)(int)); - +extern time_t clocktime(nfstime *nt); #ifdef MOUNT_TABLE_ON_FILE extern void rewrite_mtab(mntlist *, const char *); diff --git a/libamu/mount_fs.c b/libamu/mount_fs.c index 163b170..fe4ed62 100644 --- a/libamu/mount_fs.c +++ b/libamu/mount_fs.c @@ -180,8 +180,6 @@ mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts); again: - clock_valid = 0; - error = MOUNT_TRAP(type, mnt, flags, mnt_data); if (error < 0) { diff --git a/libamu/xutil.c b/libamu/xutil.c index 51837cb..f3c4a67 100644 --- a/libamu/xutil.c +++ b/libamu/xutil.c @@ -68,9 +68,6 @@ int xlog_level = XLOG_ALL & ~XLOG_MAP & ~XLOG_STATS; int xlog_level_init = ~0; static int amd_program_number = AMQ_PROGRAM; -time_t clock_valid = 0; -time_t xclock_valid = 0; - #ifdef DEBUG_MEM # if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_VERIFY) static int mem_bytes; @@ -336,7 +333,7 @@ show_time_host_and_name(int lvl) } else #endif /* defined(HAVE_CLOCK_GETTIME) && defined(DEBUG) */ - t = clocktime(); + t = clocktime(NULL); if (t != last_t) { last_ctime = ctime(&t); @@ -842,9 +839,14 @@ switch_to_logfile(char *logfile, int old_umask, int truncate_log) void unregister_amq(void) { - if (!amuDebug(D_AMQ)) + if (amuDebug(D_AMQ)) { /* find which instance of amd to unregister */ - pmap_unset(get_amd_program_number(), AMQ_VERSION); + u_long amd_prognum = get_amd_program_number(); + + if (pmap_unset(amd_prognum, AMQ_VERSION) != 1) + dlog("failed to de-register Amd program %lu, version %lu", + amd_prognum, AMQ_VERSION); + } } @@ -1000,3 +1002,25 @@ setup_sighandler(int signum, void (*handler)(int)) } +/* + * Return current time in seconds. If passed a non-null argyument, then + * fill it in with the current time in seconds and microseconds (useful + * for mtime updates). + */ +time_t +clocktime(nfstime *nt) +{ + static struct timeval now; /* keep last time, as default */ + + if (gettimeofday(&now, NULL) < 0) { + plog(XLOG_ERROR, "clocktime: gettimeofday: %m"); + /* hack: force time to have incremented by at least 1 second */ + now.tv_sec++; + } + /* copy seconds and microseconds. may demote a long to an int */ + if (nt) { + nt->nt_seconds = (u_int) now.tv_sec; + nt->nt_useconds = (u_int) now.tv_usec; + } + return (time_t) now.tv_sec; +} diff --git a/vers.m4 b/vers.m4 index 656ddea..931a075 100644 --- a/vers.m4 +++ b/vers.m4 @@ -1 +1 @@ -[6.1.2-rc1]dnl +[6.1.2]dnl -- 2.43.0