[comp.sources.unix] v21i098: An Automounter for NFS systems, Part10/13

rsalz@uunet.uu.net (Rich Salz) (04/11/90)

Submitted-by: Jan-Simon Pendry <jsp@doc.ic.ac.uk>
Posting-number: Volume 21, Issue 98
Archive-name: amd/part10

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 10 (of 13)."
# Contents:  ChangeLog map.c
# Wrapped by rsalz@papaya.bbn.com on Tue Apr 10 15:12:14 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ChangeLog' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ChangeLog'\"
else
echo shar: Extracting \"'ChangeLog'\" \(21923 characters\)
sed "s/^X//" >'ChangeLog' <<'END_OF_FILE'
XThu Jan 11 16:56:41 1990  Jan-Simon Pendry  (jsp at achilles)
X
X	* Release 5.1c.
X
X	* (amq*) has new options.  -f flushes the map cache and -m prints
X	information about mounted filesystem and fileservers.
X
XTue Jan  2 14:44:21 1990  Jan-Simon Pendry  (jsp at achilles)
X
X	* (util.c) am_mounted() patches the path for "direct" mounted
X	filesystems - cosmetic.
X
X	* (afs_ops.c) when possible sets a small kernel attribute cache
X	timeout on the automount points.
X
X	* (nfs_stubs.c) delete() and rmdir() operations implemented.  Used
X	when a mount point is timed out so the kernel name cache gets to
X	know about the changes.  Fixes most ESTALE errors.
X
X	* (nfs_stubs.c) New do_readlink() function added.  This is used to
X	make sure that a filesystem is mounted at the time a link is read
X	in the case of "direct" mounts.  Done so that the length of the
X	link is available when the initial getattr is done on the mountpoint.
X
X	* (sfs_ops.c) Changed implementation to avoid race conditions.
X	The link target is re-arranged so that sublink points to the
X	target and fs always points at ".".
X
X	* Fixed mount flag bug on Ultrix.
X
X	* Added support from Sjoerd Mullender for Alliant FX/4 and Encore
X	Multimax.
X
XThu Dec  7 17:55:29 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c) dfs_readlink now does a new_ttl on the node it
X	returns.
X
X	* (afs_ops.c) next_nonerror_node now implements the task after
X	which it is named.
X
XTue Nov 28 17:20:52 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Release 5.1b.
X
X	* (restart.c) Generates link nodes for any unrecognised filesystem
X	types and then marks them so that they are never deleted (since
X	they could never be automounted later).
X
X	* (os-*.h) Irrelevant #undef's deleted.
X
X	* (arch) Now knows about AIX on RTs.
X
X	* (amq.c) Rationalised the output.  Now only gives you what you
X	asked for.
X
X	* (am.h) New macro: FSRV_ISDOWN(fs), which checks whether a
X	fileserver is down.
X
X	* (afs_ops.c) When a mount fails due to a timeout the underlying
X	filesystem is ripped away and replaced with an error fs.  This
X	avoids the possibility of being left with a single error reference
X	to a valid mounted filesystem.
X
XThu Nov 23 18:04:29 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (nfs_start.c) Re-order bootstrap sequence to avoid potential
X	deadlock if restart() ends up accessing one of the automount points.
X
X	* (amq.c) Don't produce default mount output if one of the -l, -x
X	or -D options was used.
X
X	* (umount_fs.c) Add alternative unmount routine for 4.4 BSD.
X
XMon Nov 20 16:22:50 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (os-bsd44.h) Fixed redefinition of UMOUNT_FS.
X
X	* (info_ndbm.c) Added missing #include <sys/stat.h>.
X
X	* (mapc.c) Fixed typo in ifdef around gdbm config entry.
X
XSat Nov 18 16:39:13 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (util.c) If "/" is automounted, make sure it is never timed out.
X
X	* (mtab.c) Missing clock invalidation added in read_mtab (from a file).
X
X	* (mntfs.c) realloc_mntfs simplified.
X
X	* (map.c) Closed a race condition during shutdown when second and
X	subsequent duplicate mounts were deleted prematurely.
X
X	* (afs_ops.c) Duplicate mounts are now given the correct return
X	code.
X
XFri Nov 17 18:58:18 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.1 Release.
X
XThu Nov 16 17:57:02 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (mntfs.c) Make sure inherit mntfs structures are not cached
X	after last reference; otherwise a second reference to the
X	inherited filesystem will get stuck on the inherit rather than the
X	(now) fully mounted filesystem.
X
X	* (am.c, nfs_start.c) After forking the server, make sure the
X	parent does not exit until the automount points are mounted.  This
X	allows a clean sequence during system startup.
X
X	* Initial port to 4.4 BSD.  Several new configuration abstractions
X	were added to make this port possible.
X
XThu Nov  9 21:42:14 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c, opts.c) Added map logging to facilitate mount map
X	debugging without needing a -DDEBUG version of Amd.
X
X	* (afs_ops.c) Make sure the length of the fs_hostname mount
X	parameter does not exceed MAXHOSTNAMESZ.
X
XWed Nov  8 13:44:02 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Change the message log format to indicate the severity of the
X	message to allow simpler analysis of the log file.
X
XTue Nov  7 14:11:36 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 11.
X
X	* (os-bsd44.h) Initial guess at 4.4 BSD definitions.
X
X	* (os-aux.h) Port for Macintosh II from Julian Onions.
X
X	* (amq.c) Output formats cleaned up.  AMQ_MNTTREE is still broken
X	in amq_subr.c though.
X
X	* (afs_ops.c) If a mount timed out, for example an NFS server was
X	down at the time, it was possible for the error code to remain
X	unset thus jamming that mount node in a state from which it could
X	not recover.  Just make sure that the mf_error field gets filled
X	in when an error occurs.
X
X	* (afs_ops.c) strsplit is run over /defaults to avoid problems
X	with whitespace creeping in.
X
XSun Nov  5 11:50:51 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (util.c) am_mounted: Added missing initialisation of stats.s_mtime.
X
XFri Nov  3 17:33:02 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 10.
X
X	* Changed the copyright.
X
XThu Nov  2 17:07:53 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 9.
X
X	* (opts.c) new option syntax: == != :=
X
X	* (nfs_ops.c) Less caching of filehandles.  Now cached errors are
X	discarded after use.
X
X	* (mtab.c) now attempts to deal with a lack of open file slots (ENFILE).
X
X	* (mount_fs.c) automount entries in the mount table now have a
X	dev= entry in the same way as NFS and UFS.
X
X	* (mntfs.c) mntfs nodes are now cached after the last reference
X	and discarded <ALLOWED_MOUNT_TIME> seconds later.  This avoids
X	thrashing during a mount.
X
X	* (mapc.c) map default cache mode is now selected with
X	"mapdefault", not "default"
X
X	* (amd.tex) numerous clarifications.  Still more work required...
X
X	* (amq_subr.c) now allows the -x option of amq to operate.
X
X	* (afs_ops.c) afs_bgmount now keeps track of which filesystem
X	needed retrying and ensures that the mount node in the
X	continuation correctly points at an unmounted filesystem.  This
X	fixes a problem whereby a valid mounted filesystem could appear to
X	have failed to mount.
X
X	* Configure now gives more of a running commentary and checks
X	whether os-type and arch actually worked.
X
X	* Allow spurious ';'s in a mount location.
X
XFri Oct 27 14:03:31 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* foo=blah changed to foo:=blah, foo==blah and foo!=blah.
X
X	* -l stderr changed to -l /dev/stderr.
X
XThu Oct 19 15:34:28 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 6.
X
X	* LOG_INFO messages have been rationalised so that some
X	statistics, graphs and so on can be generated.
X
X	* Transaction ID's for RPC calls are now allocated by the
X	individual callers, rather than from a central pool.  This
X	decreases the load on mount daemons and NFS servers since the
X	same XID is used for retries when needed.
X
X	* Many fine details of the new data structures have been changed.
X	Some areas have been optimized.
X
XFri Oct 13 12:31:26 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Restart code re-implemented to work with the new data structures.
X
X	* Fine tuning applied to new NFS server modeling code.
X
XThu Oct 12 15:57:24 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Added ${/var} and ${var/} variable expansions.  The first gives
X	the "basename" component of the variable, the latter gives the
X	"dirname" component.  Additionally, spurious /'s are deleted after
X	the variable expansions is complete.
X
X	* Added new -C option to allow the machine's cluster name to be
X	given to amd.  ${cluster} fetches the value and can be used as
X	another selector.
X
X	* Broken the major data struct (am_node) into three layers:
X	am_node (one for each automount node), mntfs (one for each mounted
X	filesystem) and fserver (one for each file server).  Machine
X	up/down state is maintained in the fserver layer.  Filesystem
X	mount/unmount state is maintained in the mntfs layer.  This change
X	fixes the last known major problem caused by the lack of a central
X	focus for filesystem and fileserver status.  There is a dummy file
X	server layer for local filesystems (ufs, link, program, error).
X
XTue Oct 10 11:15:42 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 5.
X
X	* (nfs_ops.c) the filehandle cache is now flushed when a
X	filesystem is unmounted.  This avoids ending up with stale
X	information if a server bounces.
X
X	* (clock.c) new module to implement callouts.  Many other
X	routines changed to use callouts instead of messing with ttl
X	fields.
X
XSun Oct  1 17:08:20 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 3 & 4.
X
X	* Numerous cleanups.
X
XWed Sep 13 14:30:05 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 2.
X
X	* (nfs_ops.c) portmap information is not remembered beyond the
X	basic filehandle cache interval.  That avoids problems when a new
X	portmap and/or rpc.mountd is started and the bound port changes.
X
X	* (mapc.c) cache reloads are automatically done every hour.
X
X	* Removed xlog macro in favour of plog() so that the log level
X	can be reflected through to syslog().  log() routine renamed to
X	plog() which takes an extra parameter indicating the log level.
X
XTue Sep  5 20:00:19 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (nfs_ops.c) when a server is known to be down, any cached file
X	handles and port mapping informaton is flushed since that may have
X	changed when it comes back up.
X
X	* (map.c) timeout no longer attempts to unmount a hung mount point.
X
XMon Sep  4 14:49:18 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c) a mount node which timed out during mount is now
X	retained for the normal timeout interval rather than for a short
X	period.  This avoids wasting time retrying mounts from a server
X	which is down.
X
X	* (afs_ops.c) hung mounts are now detected and not used as a
X	duplicate mount - something which defeated the replacement fs
X	scheme.
X
X	* (nfs_ops.c) keepalive's now back-off when a server has gone
X	down.
X
XThu Aug 31 21:18:35 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* 5.0 Patchlevel 1.
X
X	* Fixed several bugs which showed up in the keepalive
X	implementation when a gateway went down causing
X	a different sequence of errors than usual.
X
XWed Aug 30 11:29:21 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (amq.x) now uses a Sun assigned program number.
X
X	* Revision 5.0 - can now start using metaconfig.
X
XTue Aug 29 14:36:48 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (os-u3_0.h, os-type) now knows about DECstations (mips).
X
X	* (nfs_stubs.c) Added hooks to readlink entry point to call
X	per-fs readlink routine if it exists, otherwise old behaviour.
X
X	* (afs_ops.c) Added implementation of "type=direct".  This is
X	the same as "type=auto" but is itself the link to the
X	mount point, rather than being a directory containing a list
X	of links to mount points.
X
XMon Aug 28 17:48:15 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c) Changed readdir to workaround a problem on
X	ultrix 3 where it seems to forget that eof has been reached.
X
XThu Aug 24 15:17:55 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Created "beta16".
X
X	* (afs_ops.c) /defaults is located along with every key.
X	this makes it possible to update the /defaults in
X	a map and get to use it.
X
X	* (mapc.c) added map cache synchronization support.  if
X	a file or ndbm map is updated the cache is junked so avoiding
X	things getting out of sync.
X
XWed Aug 23 19:17:52 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (os-u3_0.h) new file to support Ultrix 3.0
X
X	* (opts.c) allow environment variables to be accessed via
X	the same ${env} syntax used for options & selectors.
X
XTue Aug 22 13:19:49 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (opts.c, get_args.c) added support for kernel architecture
X	type to allow /usr/kvm to be automounted under SunOS 4.x.
X
X	* (os-xinu43.h) updated for june '89 release of MORE/bsd.
X
X	* (opts.c) fixed memory allocation problems where some strings
X	may not have been strdup'ed before they were free'ed so causing
X	the malloc arena to get into a twist.  This caused core dumps on
X	some machines and infinite loops on others.
X
X	* (*.c) clock handling is now done by a macro.  Global variable
X	clock_valid is > 0 (ie the time) when valid, 0 if invalid.
X
X	* (map.c) timeout code survived a complete rewrite and is now
X	O(n) rather than O(n^2).
X
X	* (info_hes.c) new database hooks for Hesiod nameserver.
X
X	* (get_args.c) the local sub-domain is picked up from the
X	hostname if it is not specifed with -d.  The subdomain is
X	then stripped from the hostname.
X
X	* (am.c) when a SIGTERM is received, an immediate abort
X	occurs - only the top-level automounts are unmounted; all
X	other mounts stay -- use amd -r to restart.
X
X	* (afs_ops.c) cleaned up key prefix handling.  Again updated
X	the "hostname" string passed to the kernel so that includes
X	the hostname, pid and mount point.
X
XTue Aug  8 16:05:23 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (nfs_ops.c) changed the way the file handle cache is managed.
X	No longer gets a race condition between something entering the
X	cache and being used and discard.
X
XTue Jul 25 20:40:51 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (map.c) changed fh_to_mp2 so that it does not return
X	ESTALE during shutdown.  it returns ENOENT instead which
X	avoids thrashing with the kernel.
X
XSun Jul 23 15:06:10 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c) make sure the incoming key from the kernel
X	does not contain any characters which could cause trouble
X	during macro expansion (such as `"! etc).
X
X	* (afs_ops.c) fixed contruction of "mtab" entry.
X
XFri Jul 21 11:01:05 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c) some changes to support the new startup
X	shutdown scheme.
X
X	* (map.c) startup and shutdown are now done using the
X	standard interfaces.  Startup is done by creating a
X	private cache map  ";root;" and then doing lookups
X	on all the names in it.  Shutdown is done by forcibly
X	timing out all the mount points including the automount
X	points.
X
X	* (info_*.c) modified to provide interface required by
X	mapc.c module.
X
X	* (mapc.c) new module to implement map caching.  Caching
X	can be controlled by an fs option.  "all" means cache
X	the entire map (if possible).  "inc" means cache things
X	incrementally.  "none" means never cache things.  Each
X	map type has a default caching mode which is used if
X	cache option "default" is used.
X
XWed Jul 19 16:14:52 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (sched.c) implements a general sleep/wakeup scheme and uses
X	it for sub-process handling.
X
X	* (nfs_start.c) task_notify() called from where it used to
X	be called.
X
X	* (nfs_ops.c) now implements a non-blocking rpc library.
X	Everything in nfs_ops was changed to use it.  This should
X	not be in this file and will be moved later. 
X
X	* (map.c) if a mount point times out and it is deferred then
X	issue a wakeup so that it can be retried.
X
X	* (map.c) when creating a new mount point fetches the entry
X	"/defaults" from the associated map if no other options are
X	specified.
X
X	* (am.c) implements the -p (print process id) option.
X
X	* (afs_ops.c) a mount attempt now has a time-to-live of twenty
X	seconds.  if only deferred attempts are waiting after that
X	interval the kernel gets sent ETIMEDOUT.
X
X	* (afs_ops.c) the name by which the kernel knows the filesystem
X	has changed from pid%d@host to /mountpoint@host.  That looks
X	better to users who get hit by it.
X
XFri Jul 14 18:46:16 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c) now knows about defered mounts - mounts which
X	are not in progress, not completed, and not failed.
X
X	* (sched.c) added new entry point sched_ast().  This simulates
X	a completed job.  The basic idea is to let something else return
X	to the main scheduling loop with a guarentee that it will be
X	called back when some other action has taken place.
X
X	* (nfs_ops.c) implemented a file handle cache.  The nfs_init
X	routine starts up a request for the filehandle and the mount
X	routine uses it when it arrives.
X
XThu Jul 13 18:07:58 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (afs_ops.c) found a race condition between an error occuring
X	and the am_node being timed out.  Fixed by updating the
X	time-to-live and keepalive counters in the node whenever
X	AMF_MOUNTING is cleared.  Also changed afs_lookuppn() so that
X	it doesn't destroy the node when it returns the error code.
X	This stops thrashing and the node is eventually timed out.
X	Now the only way a node gets deleted is by the timeout code
X	which seems more elegant.
X
XTue Jul 11 15:36:44 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Created "beta15".
X
X	* Fixed *all* references to "u2.2".  Some where missed in
X	the original change.  They are now u2_2.
X
X	* (mk-amd-map.c) new command.  Converts plain files into
X	ndbm databases for use by the info_ndbm module.  Hooks
X	included for future support for gdbm just as soon as I
X	can get a copy.
X
XSun Jul  9 19:00:22 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Created "beta14".
X
X	* (get_info.c) code to handle yp and files now split into
X	new files info_yp.c and info_file.c  New support for ndbm
X	databases is in info_ndbm.c.  A table in get_info.c controls
X	what and in which order things are searched.
X
X	* (map.c, nfs_stubs.c) better handling for hung mount points.
X	if a filehandle is passed in by the kernel which references
X	a hung node, then try to find a replacement, possibly by calling
X	lookup explicitly.
X
X	* (*.c) use new xlog(level)(message) interface
X
XThu Jun  8 20:28:55 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (nfs_ops.c, ufs_ops.c) when compiled with DEBUG, display
X	the fs options being used.
X
X	* (am.c) make test for root a little more polite.
X
X	* (get_args.c) update Usage message to include -r option.
X
XWed Jun  7 16:28:51 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (rpc_fwd.c) fwd_reply: if the recvfrom call fails because it
X	is interrupted then try again.
X
XTue Jun  6 16:39:15 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Created "beta12".
X
X	* (afs_ops.c) inheriting mount option list from command line
X	is now cumulative.  A -foo on the command line is prepended
X	to the default option list taken from the map.  This can be
X	used to override the ``default default'' options in opts.c.
X
X	* (get_args.c, am.c) added new -r (restart) option.  Restart of
X	mounted filesystems is only done if this option is specified.
X	Should *not* be specified in /etc/rc.local of course.
X
X	* (yp_master.c) make the enumeration error message more verbose
X	when debugging is enabled.
X
X	* (rpc_fwd.c) rearranged some declarations at the top.  Removed
X	a spurious call to free which was causing grief on some systems,
X	but not on Sun's.  [This problem was the reason for implementing
X	the -D mem option.]
X
X	* (opts.c) make sure opt_key and opt_path are set to a zero
X	length string unless otherwise specified.  Previously they
X	were are source of dangling pointers.
X
X	* (nfs_ops.c) make sure that the allocated nfs_private identifiers
X	are unique even when some filesystem are being restarted.  This mean
X	starting the basic allocation from 1, not zero.
X
X	* (am.h, get_args.c, util.c) added definition and implmentation of
X	a simple memory allocation trace (D_MEM).
X
X	* (afs_ops.c) afs_lookuppn: tightened up memory allocation and
X	delay string copying until last possible moment.
X
XMon Jun  5 18:01:18 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* (Makefile.com) diffs: added new rule to generate diffs
X	between versions.
X
X	* (get_info.c) search_file: added a new dlog() to note when
X	wildcards are returned.
X
X	* (afs_ops.c) afs_lookuppn: call to init_map specifies efs as
X	the default ops structure.  If the location list only contained
X	defaults and no real mounts then this previously caused a null
X	pointer dereference.
X
X	* (map.c) last_used_map: Added new variable.  Keeps track of the
X	last used map, which may be wildly different from first_free_map.
X	This fixes bugs in several routines in this file.
X
X	* (util.c) mkdirs, rmdirs: Changed directory make/unmake.  It is
X	not possible to quickly determine how many directories need to
X	be created or deleted, so we try to make as many as possible.
X
X	* (opts.c) Added default values for rfs, rhost and fs.
X	The new defaults guarentee unique names to allow the NFS
X	keepalive stuff to work.
X
XSun Jun  4 16:12:15 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* First draft of documentation included in the next release.
X
X	* Hooks for TFS added, though this still requires a lot of work.
X
X	* Re-implemented option handling.  Options are now allocated
X	dynamically on a per-mount basis in the continuation structure.
X
X	* Changed os type u2.2 to u2_2 to allow for regular expression
X	matching in selectors.
X
X	* Format of mount maps is now entirely different.  Instead of
X	guessing which filesystem type is being used, it is now explicitly
X	stated along with the required options.  Variable expansion is
X	done on the options and selectors are also implemented.  The
X	requested name can also contain any of the selectors.
X
XWed May 24 15:21:39 1989  Jan-Simon Pendry  (jsp at achilles)
X
X	* Re-implemented NFS ping algorithm to use the new RPC forwarding
X	system.  This allowed a large amount of nfs_ops specific code
X	to be removed from nfs_start.c and moved to nfs_ops.c.
X	There is still no strategy for hung file systems.  At the moment
X	it will merely try to mount an alternative (or the same again)
X	to the same place in the file system.
X
X	* Added RPC forwarding package.  This supports general RPC gatewaying
X	over a UDP transport.  The idea is to put a packet identifier into
X	each outgoing RPC packet and then match that up in a database when
X	a reply comes in.  The database records the original packet identifier
X	(so that it can be replaced), the source address for the packet and
X	a function to call to do the forwarding.
X
X	* ChangeLog added between beta8 and beta9.  Should have done this sooner.
END_OF_FILE
if test 21923 -ne `wc -c <'ChangeLog'`; then
    echo shar: \"'ChangeLog'\" unpacked with wrong size!
fi
# end of 'ChangeLog'
fi
if test -f 'map.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'map.c'\"
else
echo shar: Extracting \"'map.c'\" \(19814 characters\)
sed "s/^X//" >'map.c' <<'END_OF_FILE'
X/*
X * $Id: map.c,v 5.1.1.3 90/01/11 17:08:32 jsp Exp Locker: jsp $
X *
X * Copyright (c) 1990 Jan-Simon Pendry
X * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Jan-Simon Pendry at Imperial College, London.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by Imperial College of Science, Technology and Medicine, London, UK.
X * The names of the College and University may not be used to endorse
X * or promote products derived from this software without specific
X * prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	%W% (Berkeley) %G%
X */
X
X#include "am.h"
X#include <sys/param.h>	/* For NMOUNT */
X
X/*
X * Generation Numbers.
X *
X * Generation numbers are allocated to every node created
X * by amd.  When a filehandle is computed and sent to the
X * kernel, the generation number makes sure that it is safe
X * to reallocate a node slot even when the kernel has a cached
X * reference to its old incarnation.
X * No garbage collection is done, since it is assumed that
X * there is no way that 2^32 generation numbers could ever
X * be allocated by a single run of amd - there is simply
X * not enough cpu time available.
X */
Xstatic unsigned int am_gen = 2;	/* Initial generation number */
X#define new_gen() (am_gen++)
X
Xstruct am_node *exported_ap[NEXP_AP];
Xint first_free_map = 0;		/* First available free slot */
Xint last_used_map = -1;		/* Last unavailable used slot */
Xstatic int timeout_mp_id;	/* Id from last call to timeout */
X
X/*
X * The root of the mount tree.
X */
Xstatic am_node *root_node;
X
X/*
X * Allocate a new mount slot and create
X * a new node.
X * Fills in the map number of the node,
X * but leaves everything else uninitialised.
X */
Xstruct am_node *exported_ap_alloc(P_void)
X{
X	struct am_node *mp, **mpp;
X
X	/*
X	 * First check if there are any slots left
X	 */
X	if (first_free_map >= NEXP_AP)
X		return 0;
X
X	/*
X	 * Grab the next free slot
X	 */
X	mpp = exported_ap + first_free_map;
X	mp = *mpp = ALLOC(am_node);
X	bzero((char *) mp, sizeof(*mp));
X
X	mp->am_mapno = first_free_map++;
X
X	/*
X	 * Update free pointer
X	 */
X	while (first_free_map < NEXP_AP && exported_ap[first_free_map])
X		first_free_map++;
X
X	if (first_free_map > last_used_map)
X		last_used_map = first_free_map - 1;
X
X#ifdef DEBUG
X	/*dlog("alloc_exp: last_used_map = %d, first_free_map = %d\n",
X		last_used_map, first_free_map);*/
X#endif
X
X	return mp;
X}
X
X/*
X * Free a mount slot
X */
Xvoid exported_ap_free(mp)
Xstruct am_node *mp;
X{
X	/*
X	 * Sanity check
X	 */
X	if (!mp)
X		return;
X
X	/*
X	 * Zero the slot pointer to avoid double free's
X	 */
X	exported_ap[mp->am_mapno] = 0;
X
X	/*
X	 * Update the free and last_used indices
X	 */
X	if (mp->am_mapno == last_used_map)
X		while (last_used_map >= 0 && exported_ap[last_used_map] == 0)
X			--last_used_map;
X
X	if (first_free_map > mp->am_mapno)
X		first_free_map = mp->am_mapno;
X
X#ifdef DEBUG
X	/*dlog("free_exp: last_used_map = %d, first_free_map = %d\n",
X		last_used_map, first_free_map);*/
X#endif
X
X	/*
X	 * Free the mount node
X	 */
X	free(mp);
X}
X
X/*
X * Insert mp into the correct place,
X * where p_mp is its parent node.
X * A new node gets placed as the youngest sibling
X * of any other children, and the parent's child
X * pointer is adjusted to point to the new child node.
X */
Xvoid insert_am(mp, p_mp)
Xam_node *mp;
Xam_node *p_mp;
X{
X	/*
X	 * If this is going in at the root then flag it
X	 * so that it cannot be unmounted by amq.
X	 */
X	if (p_mp == root_node)
X		mp->am_flags |= AMF_ROOT;
X	/*
X	 * Fill in n-way links
X	 */
X	mp->am_parent = p_mp;
X	mp->am_osib = p_mp->am_child;
X	if (mp->am_osib)
X		mp->am_osib->am_ysib = mp;
X	p_mp->am_child = mp;
X}
X
X/*
X * Remove am from its place in the mount tree
X */
Xvoid remove_am(mp)
Xam_node *mp;
X{
X	/*
X	 * 1.  Consistency check
X	 */
X	if (mp->am_child && mp->am_parent) {
X		plog(XLOG_WARNING, "children of \"%s\" still exist - deleting anyway", mp->am_path);
X	}
X
X	/*
X	 * 2.  Update parent's child pointer
X	 */
X	if (mp->am_parent && mp->am_parent->am_child == mp)
X		mp->am_parent->am_child = mp->am_osib;
X
X	/*
X	 * 3.  Unlink from sibling chain
X	 */
X	if (mp->am_ysib)
X		mp->am_ysib->am_osib = mp->am_osib;
X	if (mp->am_osib)
X		mp->am_osib->am_ysib = mp->am_ysib;
X}
X
X/*
X * Compute a new time to live value for a node.
X */
Xvoid new_ttl(mp)
Xam_node *mp;
X{
X	mp->am_timeo_w = 0;
X
X	mp->am_ttl = clocktime();
X	mp->am_mnt->mf_fattr.atime.seconds = mp->am_ttl;
X	mp->am_ttl += mp->am_timeo;	/* sun's -tl option */
X}
X
X/*
X * Initialise an allocated mount node.
X * It is assumed that the mount node was bzero'd
X * before getting here so anything that would
X * be set to zero isn't done here.
X */
Xvoid init_map(mp, dir)
Xam_node *mp;
Xchar *dir;
X{
X	/* mp->am_mapno initalised by exported_ap_alloc */
X	mp->am_mnt = new_mntfs();
X	mp->am_name = strdup(dir);
X	mp->am_path = strdup(dir);
X	/*mp->am_link = 0;*/
X	/*mp->am_parent = 0;*/
X	/*mp->am_ysib = 0;*/
X	/*mp->am_osib = 0;*/
X	/*mp->am_child = 0;*/
X	/*mp->am_flags = 0;*/
X	/*mp->am_error = 0;*/
X	mp->am_gen = new_gen();
X	/*mp->am_pref = 0;*/
X
X	mp->am_timeo = am_timeo;
X	new_ttl(mp);
X	mp->am_stats.s_mtime = mp->am_mnt->mf_fattr.atime.seconds;
X	/*mp->am_private = 0;*/
X}
X
X/*
X * Free a mount node.
X * The node must be already unmounted.
X */
Xvoid free_map(mp)
Xam_node *mp;
X{
X	remove_am(mp);
X
X	if (mp->am_link)
X		free(mp->am_link);
X	if (mp->am_name)
X		free(mp->am_name);
X	if (mp->am_path)
X		free(mp->am_path);
X	if (mp->am_pref)
X		free(mp->am_pref);
X
X	if (mp->am_mnt)
X		free_mntfs(mp->am_mnt);
X
X	if (mp->am_flags & AMF_MKPATH)
X		rmdirs(mp->am_path);
X	exported_ap_free(mp);
X}
X
X/*
X * Convert from file handle to
X * automount node.
X */
Xam_node *fh_to_mp3(fhp, rp, c_or_d)
Xnfs_fh *fhp;
Xint *rp;
Xint c_or_d;
X{
X	struct am_fh *fp = (struct am_fh *) fhp;
X	am_node *ap = 0;
X
X	/*
X	 * Check process id matches
X	 * If it doesn't then it is probably
X	 * from an old kernel cached filehandle
X	 * which is now out of date.
X	 */
X	if (fp->fhh_pid != mypid)
X		goto drop;
X
X	/*
X	 * Make sure the index is valid before
X	 * exported_ap is referenced.
X	 */
X	if (fp->fhh_id < 0 || fp->fhh_id >= NEXP_AP)
X		goto drop;
X
X	/*
X	 * Get hold of the supposed mount node
X	 */
X	ap = exported_ap[fp->fhh_id];
X
X	/*
X	 * If it exists then maybe...
X	 */
X	if (ap) {
X		/*
X		 * Check the generation number in the node
X		 * matches the one from the kernel.  If not
X		 * then the old node has been timed out and
X		 * a new one allocated.
X		 */
X		if (ap->am_gen != fp->fhh_gen) {
X			ap = 0;
X			goto drop;
X		}
X
X		/*
X		 * If the node is hung then locate a new node
X		 * for it.  This implements the replicated filesystem
X		 * retries.
X		 */
X		if (ap->am_mnt && FSRV_ISDOWN(ap->am_mnt->mf_server) && ap->am_parent) {
X			int error;
X#ifdef DEBUG
X			dlog("fh_to_mp3: %s (%s) is hung:- call lookup", ap->am_path, ap->am_mnt->mf_info);
X#endif
X			/*
X			 * Update last access to original node.  This
X			 * avoids timing it out and so sending ESTALE
X			 * back to the kernel.
X			 */
X			new_ttl(ap);
X
X			/*
X			 * Call the parent's lookup routine for an object
X			 * with the same name.  This may return -1 in error
X			 * if a mount is in progress.  In any case, if no
X			 * mount node is returned the error code is propagated
X			 * to the caller.
X			 */
X			if (c_or_d == VLOOK_CREATE) {
X				ap = (*ap->am_parent->am_mnt->mf_ops->lookuppn)(ap->am_parent,
X						ap->am_name, &error, c_or_d);
X			} else {
X				ap = 0;
X				error = ESTALE;
X			}
X			if (ap == 0) {
X				*rp = error;
X				return 0;
X			}
X		}
X		/*
X		 * Disallow references to objects being unmounted, unless
X		 * they are automount points.
X		 */
X		if (ap->am_mnt && (ap->am_mnt->mf_flags & MFF_UNMOUNTING) &&
X				!(ap->am_flags & AMF_ROOT)) {
X			*rp = -1;
X			return 0;
X		}
X		new_ttl(ap);
X	}
X
Xdrop:
X	if (!ap || !ap->am_mnt) {
X		/*
X		 * If we are shutting down then it is likely
X		 * that this node has disappeared because of
X		 * a fast timeout.  To avoid things thrashing
X		 * just pretend it doesn't exist at all.  If
X		 * ESTALE is returned, some NFS clients just
X		 * keep retrying (stupid or what - if it's
X		 * stale now, what's it going to be in 5 minutes?)
X		 */
X		if (amd_state == Finishing)
X			*rp = ENOENT;
X		else
X			*rp = ESTALE;
X		amd_stats.d_stale++;
X	}
X
X	return ap;
X}
X
Xam_node *fh_to_mp(fhp)
Xnfs_fh *fhp;
X{
X	int dummy;
X	return fh_to_mp2(fhp, &dummy);
X}
X
X/*
X * Convert from automount node to
X * file handle.
X */
Xvoid mp_to_fh(mp, fhp)
Xam_node *mp;
Xstruct nfs_fh *fhp;
X{
X	struct am_fh *fp = (struct am_fh *) fhp;
X
X	/*
X	 * Take the process id
X	 */
X	fp->fhh_pid = mypid;
X	/*
X	 * .. the map number
X	 */
X	fp->fhh_id = mp->am_mapno;
X	/*
X	 * .. and the generation number
X	 */
X	fp->fhh_gen = mp->am_gen;
X	/*
X	 * .. to make a "unique" triple that will never
X	 * be reallocated except across reboots (which doesn't matter)
X	 * or if we are unlucky enough to be given the same
X	 * pid as a previous amd (very unlikely).
X	 */
X}
X
Xstatic am_node *find_ap2(dir, mp)
Xchar *dir;
Xam_node *mp;
X{
X	if (mp) {
X		am_node *mp2;
X		if (strcmp(mp->am_path, dir) == 0)
X			return mp;
X
X		if ((mp->am_mnt->mf_flags & MFF_MOUNTED) &&
X			strcmp(mp->am_mnt->mf_mount, dir) == 0)
X			return mp;
X
X		mp2 = find_ap2(dir, mp->am_osib);
X		if (mp2)
X			return mp2;
X		return find_ap2(dir, mp->am_child);
X	}
X
X	return 0;
X}
X
X/*
X * Find the mount node corresponding
X * to dir.  dir can match either the
X * automount path or, if the node is
X * mounted, the mount location.
X */
Xam_node *find_ap(dir)
Xchar *dir;
X{
X	int i;
X
X	for (i = last_used_map; i >= 0; --i) {
X		am_node *mp = exported_ap[i];
X		if (mp && (mp->am_flags & AMF_ROOT)) {
X			mp = find_ap2(dir, exported_ap[i]);
X			if (mp)
X				return mp;
X		}
X	}
X
X	return 0;
X}
X
X/*
X * Get the filehandle for a particular named directory.
X * This is used during the bootstrap to tell the kernel
X * the filehandles of the initial automount points.
X */
Xnfs_fh *root_fh(dir)
Xchar *dir;
X{
X	static nfs_fh nfh;
X	am_node *mp = root_ap(dir, TRUE);
X	if (mp) {
X		mp_to_fh(mp, &nfh);
X		return &nfh;
X	}
X
X	/*
X	 * Should never get here...
X	 */
X	plog(XLOG_ERROR, "Can't find root filehandle for %s", dir);
X	return 0;
X}
X
Xam_node *root_ap(dir, path)
Xchar *dir;
Xint path;
X{
X	am_node *mp = find_ap(dir);
X	if (mp && mp->am_parent == root_node)
X		return mp;
X
X	return 0;
X}
X
X/*
X * Mount a top level automount node
X * by calling lookup in the parent
X * (root) node which will cause the
X * automount node to be automounted (!)
X */
Xstatic void mount_auto_node(dir)
Xchar *dir;
X{
X	int error = 0;
X	(void) afs_ops.lookuppn(root_node, dir, &error, VLOOK_CREATE);
X	if (error) {
X		errno = error; /* XXX */
X		plog(XLOG_ERROR, "Could not start server on %s: %m", dir);
X	}
X}
X
X/*
X * Cause all the top-level mount nodes
X * to be automounted
X */
Xint mount_exported()
X{
X	/*
X	 * Iterate over all the nodes to be started
X	 */
X	return root_keyiter(mount_auto_node);
X}
X
X/*
X * Construct top-level node
X */
Xvoid make_root_node()
X{
X	mntfs *root_mnt;
X	char *rootmap = ROOT_MAP;
X	root_node = exported_ap_alloc();
X
X	init_map(root_node, "");
X	root_mnt = find_mntfs(&afs_ops, (am_opts *) 0, "", rootmap, "");
X	root_mnt->mf_mount = strealloc(root_mnt->mf_mount, pid_fsname);
X	root_mnt->mf_private = (voidp) mapc_find(rootmap, "");
X	root_mnt->mf_prfree = mapc_free;
X	free_mntfs(root_node->am_mnt);
X	root_node->am_mnt = root_mnt;
X	root_node->am_flags |= AMF_NOTIMEOUT;
X	root_mnt->mf_error = 0;
X}
X
X/*
X * Cause all the nodes to be unmounted by timing
X * them out.
X */
Xvoid umount_exported(P_void)
X{
X	int i;
X	for (i = last_used_map; i >= 0; --i) {
X		am_node *mp = exported_ap[i];
X		if (mp) {
X			mntfs *mf = mp->am_mnt;
X			if (mf->mf_flags & MFF_UNMOUNTING) {
X				/*
X				 * If this node is being unmounted then
X				 * just ignore it.  However, this could
X				 * prevent amd from finishing if the
X				 * unmount gets blocked since the am_node
X				 * will never be free'd.  am_unmounted needs
X				 * telling about this possibility. - XXX
X				 */
X				continue;
X			}
X			if (mf && mf->mf_ops == &dfs_ops) {
X				/*
X				 * When shutting down this had better
X				 * look like a directory, otherwise it
X				 * can't be unmounted!
X				 */
X				mf->mf_fattr.type = NFDIR;
X				mf->mf_fattr.mode = NFSMODE_DIR | 0555;
X			}
X			if ((--immediate_abort < 0 && !(mp->am_flags & AMF_ROOT) && mp->am_parent) ||
X			    (mf->mf_flags & MFF_RESTART)) {
X				/*
X				 * Just throw this node away without
X				 * bothering to unmount it.  If the
X				 * server is not known to be up then
X				 * don't discard the mounted on directory
X				 * or Amd might hang...
X				 */
X				if (mf->mf_server &&
X					(mf->mf_server->fs_flags & (FSF_DOWN|FSF_VALID)) != FSF_VALID)
X					mf->mf_flags &= ~MFF_MKMNT;
X				am_unmounted(mp);
X			} else {
X				/*
X				 * Any other node gets forcibly
X				 * timed out
X				 */
X				mp->am_flags &= ~AMF_NOTIMEOUT;
X				mp->am_mnt->mf_flags &= ~MFF_RSTKEEP;
X				mp->am_ttl = 0;
X				mp->am_timeo = 1;
X				mp->am_timeo_w = 0;
X			}
X		}
X	}
X}
X
Xstatic int unmount_node P((am_node *mp));
Xstatic int unmount_node(mp)
Xam_node *mp;
X{
X	mntfs *mf = mp->am_mnt;
X	int error;
X
X	if ((mf->mf_flags & MFF_ERROR) || mf->mf_refc > 1) {
X		/*
X		 * Just unlink
X		 */
X#ifdef DEBUG
X		if (mf->mf_flags & MFF_ERROR)
X			dlog("No-op unmount of error node %s", mf->mf_info);
X#endif
X		error = 0;
X	} else {
X#ifdef DEBUG
X		dlog("Unmounting %s (%s)", mf->mf_mount, mf->mf_info);
X#endif
X		error = (*mf->mf_ops->umount_fs)(mp);
X	}
X
X	if (error) {
X#ifdef DEBUG
X		errno = error; /* XXX */
X		dlog("%s: unmount: %m", mf->mf_mount);
X#endif
X	}
X
X	return error;
X}
X
Xstatic int unmount_node_wrap P((voidp vp));
Xstatic int unmount_node_wrap(vp)
Xvoidp vp;
X{
X	/*
X	 * This code should just say:
X	 * return unmount_node((am_node *) vp);
X	 *
X	 * However...
X	 * The kernel keeps a cached copy of filehandles,
X	 * and doesn't ever cache them (apparently).  So
X	 * when Amd times out a node the kernel will have a
X	 * stale filehandle.  When the kernel next uses the
X	 * filehandle it gets ESTALE.
X	 *
X	 * The workaround:
X	 * Arrange that when a node is removed an unlink or
X	 * rmdir is done on that path so that the kernel
X	 * cache is done.  Yes - yuck.
X	 *
X	 * This can all be removed (and the background
X	 * unmount flag in sfs_ops) if/when the kernel does
X	 * something smarter.
X	 */
X	am_node *mp = (am_node *) vp;
X	int isauto = mp->am_parent && (mp->am_parent->am_mnt->mf_fattr.type == NFDIR);
X	int error = unmount_node(mp);
X	if (error)
X		return error;
X	if (isauto && (int)amd_state < (int)Finishing) {
X		int islink = (mp->am_mnt->mf_fattr.type == NFLNK);
X		int isdir = (mp->am_mnt->mf_fattr.type == NFDIR);
X		if (islink) {
X			if (unlink(mp->am_path) < 0)
X				return errno;
X		} else if (isdir) {
X			if (rmdir(mp->am_path) < 0)
X				return errno;
X		}
X	}
X	return 0;
X}
X
Xstatic void free_map_if_success(rc, term, closure)
Xint rc;
Xint term;
Xvoidp closure;
X{
X	am_node *mp = (am_node *) closure;
X	mntfs *mf = mp->am_mnt;
X
X	/*
X	 * Not unmounting any more
X	 */
X	mf->mf_flags &= ~MFF_UNMOUNTING;
X
X	/*
X	 * If a timeout was defered because the underlying filesystem
X	 * was busy then arrange for a timeout as soon as possible.
X	 */
X	if (mf->mf_flags & MFF_WANTTIMO) {
X		mf->mf_flags &= ~MFF_WANTTIMO;
X		reschedule_timeout_mp();
X	}
X
X	if (term) {
X		plog(XLOG_ERROR, "unmount for %s got signal %d", mp->am_path, term);
X#ifdef DEBUG
X		/*
X		 * dbx likes to put a trap on exit().
X		 * Pretend it succeeded for now...
X		 */
X		if (term == SIGTRAP) {
X			am_unmounted(mp);
X		}
X#endif
X		amd_stats.d_uerr++;
X	} else if (rc) {
X		if (rc == EBUSY) {
X			plog(XLOG_STATS, "\"%s\" on %s still active", mp->am_path, mf->mf_mount);
X		} else {
X			errno = rc;	/* XXX */
X			plog(XLOG_ERROR, "%s: unmount: %m", mp->am_path);
X		}
X		amd_stats.d_uerr++;
X	} else {
X		am_unmounted(mp);
X	}
X
X	/*
X	 * Wakeup anything waiting for this mount
X	 */
X	wakeup((voidp) mf);
X}
X
Xstatic void unmount_mp(mp)
Xam_node *mp;
X{
X	mntfs *mf = mp->am_mnt;
X#ifdef notdef
X	plog(XLOG_INFO, "\"%s\" on %s timed out", mp->am_path, mp->am_mnt->mf_mount);
X#endif
X	if ((mf->mf_ops->fs_flags & FS_UBACKGROUND) &&
X			(mf->mf_flags & MFF_MOUNTED) /* &&
X			mf->mf_refc == 1 */) {
X		if (FSRV_ISDOWN(mf->mf_server)) {
X			/*
X			 * Don't try to unmount from a server that is known to be down
X			 */
X			if (!(mf->mf_flags & MFF_LOGDOWN)) {
X				/* Only log this once, otherwise gets a bit boring */
X				plog(XLOG_STATS, "file server %s is down - timeout of \"%s\" ignored", mf->mf_server->fs_host, mp->am_path);
X				mf->mf_flags |= MFF_LOGDOWN;
X			}
X		} else {
X			/* Clear logdown flag - since the server must be up */
X			mf->mf_flags &= ~MFF_LOGDOWN;
X#ifdef DEBUG
X			/*dlog("Will background the unmount attempt");*/
X#endif
X			/*
X			 * Note that we are unmounting this node
X			 */
X			mf->mf_flags |= MFF_UNMOUNTING;
X			run_task(unmount_node_wrap, (voidp) mp,
X				 free_map_if_success, (voidp) mp);
X#ifdef DEBUG
X			dlog("unmount attempt backgrounded");
X#endif
X		}
X	} else {
X#ifdef DEBUG
X		dlog("Trying unmount in foreground");
X#endif
X		mf->mf_flags |= MFF_UNMOUNTING;
X		free_map_if_success(unmount_node(mp), 0, (voidp) mp);
X#ifdef DEBUG
X		dlog("unmount attempt done");
X#endif
X	}
X}
X
Xvoid timeout_mp()
X{
X#define NEVER (time_t) 0
X#define	smallest_t(t1, t2) \
X	(t1 != NEVER ? (t2 != NEVER ? (t1 < t2 ? t1 : t2) : t1) : t2)
X#define IGNORE_FLAGS (MFF_MOUNTING|MFF_UNMOUNTING|MFF_RESTART)
X
X	int i;
X	time_t t = NEVER;
X	time_t now = clocktime();
X
X#ifdef DEBUG
X	dlog("Timing out automount points...");
X#endif
X	for (i = last_used_map; i >= 0; --i) {
X		am_node *mp = exported_ap[i];
X		mntfs *mf;
X		/*
X		 * Just continue if nothing mounted, or can't be timed out.
X		 */
X		if (!mp || (mp->am_flags & AMF_NOTIMEOUT))
X			continue;
X		/*
X		 * Pick up mounted filesystem
X		 */
X		mf = mp->am_mnt;
X		if (!mf)
X			continue;
X		/*
X		 * Don't delete last reference to a restarted filesystem.
X		 */
X		if ((mf->mf_flags & MFF_RSTKEEP) && mf->mf_refc == 1)
X			continue;
X		/*
X		 * If there is action on this filesystem then ignore it
X		 */
X		if (!(mf->mf_flags & IGNORE_FLAGS)) {
X			int expired = 0;
X			mf->mf_flags &= ~MFF_WANTTIMO;
X#ifdef DEBUG
X			/*dlog("t is initially @%d, zero in %d secs", t, t - now);*/
X#endif
X			if (now >= mp->am_ttl) {
X				expired = 1;
X				/*
X				 * Move the ttl forward to avoid thrashing effects
X				 * on the next call to timeout!
X				 */
X				/* sun's -tw option */
X				if (mp->am_timeo_w < 4 * am_timeo_w)
X					mp->am_timeo_w += am_timeo_w;
X				mp->am_ttl = now + mp->am_timeo_w;
X			}
X			/*
X			 * If the next ttl is smallest, use that
X			 */
X			t = smallest_t(t, mp->am_ttl);
X
X#ifdef DEBUG
X			/*dlog("after ttl t is @%d, zero in %d secs", t, t - now);*/
X#endif
X
X			if (!mp->am_child && mf->mf_error >= 0 && expired)
X				unmount_mp(mp);
X		} else if (mf->mf_flags & MFF_UNMOUNTING) {
X			mf->mf_flags |= MFF_WANTTIMO;
X		}
X	}
X
X	if (t == NEVER) {
X#ifdef DEBUG
X		dlog("No further timeouts");
X#endif
X		t = now + ONE_HOUR;
X	}
X
X	/*
X	 * Sanity check to avoid runaways.
X	 * Absolutely should never get this but
X	 * if you do without this trap amd will thrash.
X	 */
X	if (t <= now) {
X		t = now + 6;	/* XXX */
X		plog(XLOG_ERROR, "Got a zero interval in timeout_mp()!");
X	}
X	/*
X	 * XXX - when shutting down, make things happen faster
X	 */
X	if ((int)amd_state >= (int)Finishing)
X		t = now + 1;
X#ifdef DEBUG
X	dlog("Next mount timeout in %ds", t - now);
X#endif
X
X	timeout_mp_id = timeout(t - now, timeout_mp, 0);
X
X#undef NEVER
X#undef smallest_t
X#undef IGNORE_FLAGS
X}
X
X/*
X * Cause timeout_mp to be called soonest
X */
Xvoid reschedule_timeout_mp()
X{
X	if (timeout_mp_id)
X		untimeout(timeout_mp_id);
X	timeout_mp_id = timeout(0, timeout_mp, 0);
X}
END_OF_FILE
if test 19814 -ne `wc -c <'map.c'`; then
    echo shar: \"'map.c'\" unpacked with wrong size!
fi
# end of 'map.c'
fi
echo shar: End of archive 10 \(of 13\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 13 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.