* conf/nfs_prot/nfs_prot_aix5_2.h: define compatible
authorErez Zadok <ezk@cs.sunysb.edu>
Wed, 20 Jul 2005 03:32:30 +0000 (03:32 +0000)
committerErez Zadok <ezk@cs.sunysb.edu>
Wed, 20 Jul 2005 03:32:30 +0000 (03:32 +0000)
forced-unmount flag.

* conf/umount/umount_default.c (umount_fs): if regular umount got
EBUSY, EIO, or ESTALE, then try forced unmount, if supported.  Try
umount2 (Solaris) or uvmount (AIX).

* conf/umount/umount_{bsd44,osf}.c (umount_fs): if default
umount() failed with EIO or ESTALE, also try forced unmount.

* amd/autil.c (amfs_mount), amd/amfs_toplvl.c
(amfs_toplvl_umount): enable forced/lazy unmounts only if user
asked for it (and dlog it).

* scripts/amd.conf.5: document new force_unmount global parameter.

* doc/am-utils.texi (forced_unmounts Parameter): document new
global parameter.

* amd/conf.c (gopt_forced_unmounts): process forced_unmounts
option (default "no").  Exit with an error if user specified the
option as "yes" but configure couldn't find support for either the
MNT_FORCE or MNT_DETACH flags.

* scripts/amd.conf-sample (forced_unmounts): example usage of new
option.

* amd/amd.h (CFM_FORCED_UNMOUNTS): new flag for forced_unmounts
option.

* m4/macros/header_templates.m4: templates for _DETACH and _FORCE.

* configure.in: check for generic u/mount options "detach" and
"force".

* include/am_utils.h (UMOUNT_FS, umount_fs): new prototypes.
Define AMU_UMOUNT flags for force, detach, and autofs.

* amd/amfs_toplvl.c (amfs_toplvl_umount): pass _FORCE and _DETACH
unmount flags unconditionally.  Pass them to UMOUNT_FS().

* conf/nfs_prot/nfs_prot_linux.h: define MNT_FORCE and MNT_DETACH
if needed, because some Linux systems don't define them
(presumably because it would be too dangerous to expose these
flags to users).

* amd/autil.c (amfs_mount): if mount(2) failed with ESTALE or EIO,
then assume that we're in trouble, possibly because a previous
mount is hung.  So, first try to force a lazy unmount of the old
mount.  If the forced unmount worked, then try again to mount the
desired file system.  If the forced unmount failed, then don't
retry: just return an error.

* amd/amfs_generic.c (amfs_generic_umount), amd/amfs_host.c
(amfs_host_umount), amd/ops_cachefs.c (cachefs_umount),
amd/ops_cdfs.c (cdfs_umount), amd/ops_efs.c (efs_umount),
amd/ops_lofs.c (lofs_umount), amd/ops_nfs.c (nfs_umount),
amd/ops_pcfs.c (pcfs_umount), amd/ops_ufs.c (ufs_umount),
amd/ops_xfs.c (xfs_umount), conf/umount/umount_bsd44.c
(umount_fs), conf/umount/umount_default.c (umount_fs),
conf/umount/umount_linux.c (umount_fs), conf/umount/umount_osf.c
(umount_fs): compute and use unmount specific flags.

28 files changed:
ChangeLog
NEWS
amd/amd.h
amd/amfs_generic.c
amd/amfs_host.c
amd/amfs_toplvl.c
amd/autil.c
amd/conf.c
amd/ops_cachefs.c
amd/ops_cdfs.c
amd/ops_efs.c
amd/ops_lofs.c
amd/ops_nfs.c
amd/ops_pcfs.c
amd/ops_ufs.c
amd/ops_xfs.c
conf/nfs_prot/nfs_prot_aix5_2.h
conf/nfs_prot/nfs_prot_linux.h
conf/umount/umount_bsd44.c
conf/umount/umount_default.c
conf/umount/umount_linux.c
conf/umount/umount_osf.c
configure.in
doc/am-utils.texi
include/am_utils.h
m4/macros/header_templates.m4
scripts/amd.conf-sample
scripts/amd.conf.5

index df30c4f8dd7b98392958f4607dcd57524c451633..8d5c953bb09b6e43c547472f972464f4c16779c5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,70 @@
+2005-07-19  Erez Zadok  <ezk@cs.sunysb.edu>
+
+       * conf/nfs_prot/nfs_prot_aix5_2.h: define compatible
+       forced-unmount flag.
+
+       * conf/umount/umount_default.c (umount_fs): if regular umount got
+       EBUSY, EIO, or ESTALE, then try forced unmount, if supported.  Try
+       umount2 (Solaris) or uvmount (AIX).
+
+       * conf/umount/umount_{bsd44,osf}.c (umount_fs): if default
+       umount() failed with EIO or ESTALE, also try forced unmount.
+
+2005-07-18  Erez Zadok  <ezk@cs.sunysb.edu>
+
+       * amd/autil.c (amfs_mount), amd/amfs_toplvl.c
+       (amfs_toplvl_umount): enable forced/lazy unmounts only if user
+       asked for it (and dlog it).
+
+       * scripts/amd.conf.5: document new force_unmount global parameter.
+
+       * doc/am-utils.texi (forced_unmounts Parameter): document new
+       global parameter.
+
+       * amd/conf.c (gopt_forced_unmounts): process forced_unmounts
+       option (default "no").  Exit with an error if user specified the
+       option as "yes" but configure couldn't find support for either the
+       MNT_FORCE or MNT_DETACH flags.
+
+       * scripts/amd.conf-sample (forced_unmounts): example usage of new
+       option.
+
+       * amd/amd.h (CFM_FORCED_UNMOUNTS): new flag for forced_unmounts
+       option.
+
+       * m4/macros/header_templates.m4: templates for _DETACH and _FORCE.
+
+       * configure.in: check for generic u/mount options "detach" and
+       "force".
+
+       * include/am_utils.h (UMOUNT_FS, umount_fs): new prototypes.
+       Define AMU_UMOUNT flags for force, detach, and autofs.
+
+       * amd/amfs_toplvl.c (amfs_toplvl_umount): pass _FORCE and _DETACH
+       unmount flags unconditionally.  Pass them to UMOUNT_FS().
+
+       * conf/nfs_prot/nfs_prot_linux.h: define MNT_FORCE and MNT_DETACH
+       if needed, because some Linux systems don't define them
+       (presumably because it would be too dangerous to expose these
+       flags to users).
+
+       * amd/autil.c (amfs_mount): if mount(2) failed with ESTALE or EIO,
+       then assume that we're in trouble, possibly because a previous
+       mount is hung.  So, first try to force a lazy unmount of the old
+       mount.  If the forced unmount worked, then try again to mount the
+       desired file system.  If the forced unmount failed, then don't
+       retry: just return an error.
+
+       * amd/amfs_generic.c (amfs_generic_umount), amd/amfs_host.c
+       (amfs_host_umount), amd/ops_cachefs.c (cachefs_umount),
+       amd/ops_cdfs.c (cdfs_umount), amd/ops_efs.c (efs_umount),
+       amd/ops_lofs.c (lofs_umount), amd/ops_nfs.c (nfs_umount),
+       amd/ops_pcfs.c (pcfs_umount), amd/ops_ufs.c (ufs_umount),
+       amd/ops_xfs.c (xfs_umount), conf/umount/umount_bsd44.c
+       (umount_fs), conf/umount/umount_default.c (umount_fs),
+       conf/umount/umount_linux.c (umount_fs), conf/umount/umount_osf.c
+       (umount_fs): compute and use unmount specific flags.
+
 2005-07-16  Erez Zadok  <ezk@cs.sunysb.edu>
 
        * configure.in: better help for users, if nfs_args can't be found.
diff --git a/NEWS b/NEWS
index 65318072ca4cd3f74335ca2f94820045190c004a..80a54f025f9431f60be44309fa73cabb4c0273d8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,15 @@
 *** Notes specific to am-utils version 6.1.1-rc1
 
+New amd.conf global parameter: forced_unmounts (default to "no").  If set to
+"yes," and the client OS supports forced or lazy unmounts, then Amd will
+attempt to use them if it gets any of three serious error conditions when
+trying to unmount an existing mount point or mount on top of one: EIO,
+ESTALE, or EBUSY.  This could be useful to recover from serious conditions
+such as hardware failure of mounted disks, or NFS servers which are down
+permanently, were migrated, or changed their IP address.  Only
+"type:=toplvl" mounts hung with EBUSY are forcibly unmounted using this
+option, which is useful to recover from a hung Amd).
+
 - minor new ports:
        i386-pc-linux-fc4
        i386-pc-linux-suse9.3
index 30a570660cc63aa00f932eeab0d4779febc1bfbb..e5b1ab6178d049cae0df979e55b7200326d6ff58 100644 (file)
--- a/amd/amd.h
+++ b/amd/amd.h
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amd.h,v 1.66 2005/06/04 16:34:33 ezk Exp $
+ * $Id: amd.h,v 1.67 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
 #endif /* MOUNT_TABLE_ON_FILE */
 
 /* options for amd.conf */
-#define CFM_BROWSABLE_DIRS             0x0001
-#define CFM_MOUNT_TYPE_AUTOFS          0x0002 /* use kernel autofs support */
-#define CFM_SELECTORS_IN_DEFAULTS      0x0004
-#define CFM_NORMALIZE_HOSTNAMES                0x0008
-#define CFM_PROCESS_LOCK               0x0010
-#define CFM_PRINT_PID                  0x0020
-#define CFM_RESTART_EXISTING_MOUNTS    0x0040
-#define CFM_SHOW_STATFS_ENTRIES                0x0080
-#define CFM_FULLY_QUALIFIED_HOSTS      0x0100
-#define CFM_BROWSABLE_DIRS_FULL                0x0200 /* allow '/' in readdir() */
-#define CFM_UNMOUNT_ON_EXIT            0x0400 /* when amd finishing */
-#define CFM_USE_TCPWRAPPERS            0x0800
-#define CFM_AUTOFS_USE_LOFS            0x1000
-#define CFM_NFS_INSECURE_PORT          0x2000
-#define CFM_DOMAIN_STRIP               0x4000
-#define CFM_NORMALIZE_SLASHES          0x8000 /* normalize slashes? */
+#define CFM_BROWSABLE_DIRS             0x00000001
+#define CFM_MOUNT_TYPE_AUTOFS          0x00000002 /* use kernel autofs support */
+#define CFM_SELECTORS_IN_DEFAULTS      0x00000004
+#define CFM_NORMALIZE_HOSTNAMES                0x00000008
+#define CFM_PROCESS_LOCK               0x00000010
+#define CFM_PRINT_PID                  0x00000020
+#define CFM_RESTART_EXISTING_MOUNTS    0x00000040
+#define CFM_SHOW_STATFS_ENTRIES                0x00000080
+#define CFM_FULLY_QUALIFIED_HOSTS      0x00000100
+#define CFM_BROWSABLE_DIRS_FULL                0x00000200 /* allow '/' in readdir() */
+#define CFM_UNMOUNT_ON_EXIT            0x00000400 /* when amd finishing */
+#define CFM_USE_TCPWRAPPERS            0x00000800
+#define CFM_AUTOFS_USE_LOFS            0x00001000
+#define CFM_NFS_INSECURE_PORT          0x00002000
+#define CFM_DOMAIN_STRIP               0x00004000
+#define CFM_NORMALIZE_SLASHES          0x00008000 /* normalize slashes? */
+#define CFM_FORCED_UNMOUNTS            0x00010000 /* normalize slashes? */
 /* defaults global flags: plock, tcpwrappers, and autofs/lofs */
 #define CFM_DEFAULT_FLAGS      (CFM_PROCESS_LOCK|CFM_USE_TCPWRAPPERS|CFM_AUTOFS_USE_LOFS|CFM_DOMAIN_STRIP|CFM_NORMALIZE_SLASHES)
 
index 3d37194ded64e7c56c0f0df07e2b53c046be478c..5b84e75f56eff1dcb31fdcad494242859b2b12df 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amfs_generic.c,v 1.30 2005/05/16 18:08:53 ezk Exp $
+ * $Id: amfs_generic.c,v 1.31 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -1220,9 +1220,9 @@ amfs_generic_umount(am_node *mp, mntfs *mf)
   int error = 0;
 
 #ifdef HAVE_FS_AUTOFS
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
   if (mf->mf_flags & MFF_IS_AUTOFS)
-    error = UMOUNT_FS(mp->am_path, mnttab_file_name, on_autofs);
+    error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
 #endif /* HAVE_FS_AUTOFS */
 
   return error;
index 781b2793cb3009200b9347b1aecb7942b7541f1d..de5f976b1a849b6770677a3d40d83787aa485557 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amfs_host.c,v 1.31 2005/05/02 00:27:47 ottavio Exp $
+ * $Id: amfs_host.c,v 1.32 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -529,7 +529,7 @@ static int
 amfs_host_umount(am_node *am, mntfs *mf)
 {
   mntlist *ml, *mprev;
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
   int xerror = 0;
 
   /*
@@ -568,7 +568,7 @@ amfs_host_umount(am_node *am, mntfs *mf)
       /*
        * Unmount "dir"
        */
-      error = UMOUNT_FS(dir, mnttab_file_name, on_autofs);
+      error = UMOUNT_FS(dir, mnttab_file_name, unmount_flags);
       /*
        * Keep track of errors
        */
@@ -579,9 +579,9 @@ amfs_host_umount(am_node *am, mntfs *mf)
         * 'xerror' is the return value for this function.
         *
         * We do not want to pass ENOENT as an error because if the
-        * directory does not exists our work is done anyway. 
+        * directory does not exists our work is done anyway.
         */
-       if (!xerror && error != ENOENT) 
+       if (!xerror && error != ENOENT)
          xerror = error;
        if (error != EBUSY) {
          errno = error;
index 56a5b194c3dc6bd7ad478daa29d9bc7b5656dda7..be7daf7848eca2cd9c5aa49e5114c49a041758b9 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: amfs_toplvl.c,v 1.38 2005/04/17 03:05:54 ezk Exp $
+ * $Id: amfs_toplvl.c,v 1.39 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -219,9 +219,15 @@ int
 amfs_toplvl_umount(am_node *mp, mntfs *mf)
 {
   struct stat stb;
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
   int error;
 
+  /* if user wants forced/lazy unmount semantics, set those flags */
+  if (gopt.flags & CFM_FORCED_UNMOUNTS) {
+    dlog("enabling forced/lazy unmounts for toplvl node %s", mp->am_path);
+    unmount_flags |= (AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH);
+  }
+
 again:
   /*
    * The lstat is needed if this mount is type=direct.
@@ -245,7 +251,7 @@ again:
     goto out;
   }
 
-  error = UMOUNT_FS(mp->am_path, mnttab_file_name, on_autofs);
+  error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
   if (error == EBUSY) {
 #ifdef HAVE_FS_AUTOFS
     /*
index e57c6dadb43378bafb34415f2d14f3a953236b74..7f43af8279c62db63a44b9fb1bf96e0cd4434c54 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: autil.c,v 1.51 2005/04/17 03:05:54 ezk Exp $
+ * $Id: autil.c,v 1.52 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -516,6 +516,7 @@ amfs_mount(am_node *mp, mntfs *mf, char *opts)
   char *dir = mf->mf_mount;
   mntent_t mnt;
   MTYPE_TYPE type;
+  int forced_unmount = 0;      /* are we using forced unmounts? */
 
   memset((voidp) &mnt, 0, sizeof(mnt));
   mnt.mnt_dir = dir;
@@ -583,6 +584,7 @@ amfs_mount(am_node *mp, mntfs *mf, char *opts)
 #endif /* HAVE_FS_AUTOFS */
   genflags |= compute_automounter_mount_flags(&mnt);
 
+again:
   if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
     nfs_args_t nfs_args;
     am_nfs_fh *fhp;
@@ -684,6 +686,29 @@ amfs_mount(am_node *mp, mntfs *mf, char *opts)
                     retry, type, 0, NULL, mnttab_file_name, on_autofs);
 #endif /* HAVE_FS_AUTOFS */
   }
+  if (error == 0 || forced_unmount)
+     return error;
+
+  /*
+   * If user wants forced/lazy unmount semantics, then try it iff the
+   * current mount failed with EIO or ESTALE.
+   */
+  if (gopt.flags & CFM_FORCED_UNMOUNTS) {
+    switch (errno) {
+    case ESTALE:
+    case EIO:
+      forced_unmount = errno;
+      plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
+      if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
+                            AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
+       plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
+       errno = forced_unmount;
+      } else
+       goto again;
+    default:
+      break;
+    }
+  }
 
   return error;
 }
index 4a9faf0e414ccd64a0aeba0a16a963771f9ed691..73877c5abf213493f2e9e7247c08c19439e39230 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: conf.c,v 1.32 2005/04/17 03:05:54 ezk Exp $
+ * $Id: conf.c,v 1.33 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -86,6 +86,7 @@ static int gopt_debug_options(const char *val);
 static int gopt_dismount_interval(const char *val);
 static int gopt_domain_strip(const char *val);
 static int gopt_exec_map_timeout(const char *val);
+static int gopt_forced_unmounts(const char *val);
 static int gopt_full_os(const char *val);
 static int gopt_fully_qualified_hosts(const char *val);
 static int gopt_hesiod_base(const char *val);
@@ -163,6 +164,7 @@ static struct _func_map glob_functable[] = {
   {"dismount_interval",                gopt_dismount_interval},
   {"domain_strip",             gopt_domain_strip},
   {"exec_map_timeout",         gopt_exec_map_timeout},
+  {"forced_unmounts",          gopt_forced_unmounts},
   {"fully_qualified_hosts",    gopt_fully_qualified_hosts},
   {"full_os",                  gopt_full_os},
   {"hesiod_base",              gopt_hesiod_base},
@@ -492,6 +494,27 @@ gopt_exec_map_timeout(const char *val)
 }
 
 
+static int
+gopt_forced_unmounts(const char *val)
+{
+  if (STREQ(val, "yes")) {
+#if !defined(MNT2_GEN_OPT_DETACH) && !defined(MNT2_GEN_OPT_FORCE)
+    fprintf(stderr, "conf: forced_unmounts unsupported on this system.\n");
+    return 1;
+#else /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
+    gopt.flags |= CFM_FORCED_UNMOUNTS;
+    return 0;
+#endif /* defined(MNT2_GEN_OPT_DETACH) || defined(MNT2_GEN_OPT_FORCE) */
+  } else if (STREQ(val, "no")) {
+    gopt.flags &= ~CFM_FORCED_UNMOUNTS;
+    return 0;
+  }
+
+  fprintf(stderr, "conf: unknown value to unmount_on_exit \"%s\"\n", val);
+  return 1;                    /* unknown value */
+}
+
+
 static int
 gopt_full_os(const char *val)
 {
index 9574949fc3db96d0baa2d3a5f7f83202c5f4e197..54e9f1303dacdcda8bfa57ab088de15e4ae81a1c 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_cachefs.c,v 1.18 2005/03/06 03:19:01 ezk Exp $
+ * $Id: ops_cachefs.c,v 1.19 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -229,10 +229,10 @@ cachefs_mount(am_node *am, mntfs *mf)
 static int
 cachefs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
   int error;
 
-  error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 
   /*
    * In the case of cachefs, we must fsck the cache directory.  Otherwise,
index 7275558708a847c660c2af2eca83359cb5909c21..2a4b04b041fee137abedf3ffed4811f2c422caa3 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_cdfs.c,v 1.24 2005/01/03 20:56:45 ezk Exp $
+ * $Id: ops_cdfs.c,v 1.25 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -222,6 +222,7 @@ cdfs_mount(am_node *am, mntfs *mf)
 static int
 cdfs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
index e19f9ad3797fd74d8c799e78cd5b66b652358bef..9ae8dad0e42b5095c89be8a4fbd9d9a975c06297 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_efs.c,v 1.19 2005/01/03 20:56:45 ezk Exp $
+ * $Id: ops_efs.c,v 1.20 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -165,7 +165,8 @@ efs_mount(am_node *am, mntfs *mf)
 static int
 efs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
 
index 2ea06b1292ba96ffa35affd3c59d2d4b9a642f5b..c0bc7fa730e0e803d05c1fd1617dd7356d3027e0 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_lofs.c,v 1.18 2005/01/03 20:56:45 ezk Exp $
+ * $Id: ops_lofs.c,v 1.19 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -153,6 +153,7 @@ lofs_mount(am_node *am, mntfs *mf)
 static int
 lofs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
index 2abfb176f9ea24cb1f0a86b5c008c4015b45860b..a22972acadf64c414eaab085f5e2cfb3d0e1de2c 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_nfs.c,v 1.43 2005/06/04 16:34:33 ezk Exp $
+ * $Id: ops_nfs.c,v 1.44 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -925,8 +925,8 @@ nfs_mount(am_node *am, mntfs *mf)
 static int
 nfs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
-  int error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+  int error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 
   /*
    * Here is some code to unmount 'restarted' file systems.
@@ -955,12 +955,14 @@ nfs_umount(am_node *am, mntfs *mf)
 
       if (NSTREQ(mf->mf_mount, new_mf->mf_mount, len) &&
          new_mf->mf_mount[len] == '/') {
-       UMOUNT_FS(new_mf->mf_mount, mnttab_file_name, 0);
+       int new_unmount_flags =
+         (new_mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+       UMOUNT_FS(new_mf->mf_mount, mnttab_file_name, new_unmount_flags);
        didsome = 1;
       }
     }
     if (didsome)
-      error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+      error = UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
   }
   if (error)
     return error;
index 0604b44ca56695c47683ef455f2af30630e7aeaf..89e7dca6aead59fb296c6274f3cea06bdafdd250 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_pcfs.c,v 1.19 2005/01/03 20:56:45 ezk Exp $
+ * $Id: ops_pcfs.c,v 1.20 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -184,6 +184,7 @@ pcfs_mount(am_node *am, mntfs *mf)
 static int
 pcfs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
index 2f5a76070f716a9b60ab1cd74dfbdf13f2ce2b1c..c8f5de76ca17981b362d344c8efb0254e967e0f2 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_ufs.c,v 1.18 2005/01/03 20:56:45 ezk Exp $
+ * $Id: ops_ufs.c,v 1.19 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -174,6 +174,7 @@ ufs_mount(am_node *am, mntfs *mf)
 static int
 ufs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
index 646e089492eb00e4be9df43077255635f70e09ed..26b6148bdd34d892b1d35b5f4bb8ff7e4bf71ae5 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: ops_xfs.c,v 1.20 2005/01/03 20:56:45 ezk Exp $
+ * $Id: ops_xfs.c,v 1.21 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -165,6 +165,7 @@ xfs_mount(am_node *am, mntfs *mf)
 static int
 xfs_umount(am_node *am, mntfs *mf)
 {
-  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
-  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, on_autofs);
+  int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
+
+  return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
 }
index 2a7c9b7ce9e870f996062cf2f2235dba787e175d..0202a906df5fb0350249b676068b6e06236d37b0 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: nfs_prot_aix5_2.h,v 1.10 2005/05/26 13:36:35 ezk Exp $
+ * $Id: nfs_prot_aix5_2.h,v 1.11 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -86,6 +86,11 @@ struct thread_credentials;
 # define MNTNAMLEN 255
 #endif /* not MNTNAMLEN */
 
+/* compatible macro name with other OSs */
+#ifdef UVMNT_FORCE
+# define MS_FORCE UVMNT_FORCE
+#endif /* UVMNT_FORCE */
+
 /********************************************************************************/
 /*
  * NFS mount option flags (out of mount.h)
index 610ddfcab6dba0baded55c684b3b14123b65f9da..8dbad6f9a91de772ffe01cb29ca1f00035c1bd49 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: nfs_prot_linux.h,v 1.21 2005/01/03 20:56:45 ezk Exp $
+ * $Id: nfs_prot_linux.h,v 1.22 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
 #ifndef MNTTYPE_NFS3
 # define MNTTYPE_NFS3  "nfs"
 #endif /* not MNTTYPE_NFS3 */
-
 #endif /* HAVE_FS_NFS3 */
 
+/*
+ * These two force/lazy unmount flags are sometimes missing from some linux
+ * systems' headers.
+ */
+#ifdef HAVE_UMOUNT2
+# ifndef MNT_FORCE
+#  define MNT_FORCE    0x1     /* from <sys/mount.h> */
+# endif /* not MNT_FORCE */
+# ifndef MNT_DETACH
+#  define MNT_DETACH   0x2     /* from kernel <linux/fs.h> */
+# endif /* not MNT_DETACH */
+#endif /* HAVE_UMOUNT2 */
+
 /* XXX: hack until we have a better way to detect /dev/loop devices */
 #ifdef HAVE_LINUX_LOOP_H
 # define HAVE_LOOP_DEVICE
index 36096e5414ee6c94e13108e166a7eed0f7f2fe10..05ca413ee19759fc6aa832756d9884162ab8a6ef 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: umount_bsd44.c,v 1.12 2005/01/03 20:56:45 ezk Exp $
+ * $Id: umount_bsd44.c,v 1.13 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -53,7 +53,7 @@
 
 
 int
-umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
+umount_fs(char *mntdir, const char *mnttabname, int unmount_flags)
 {
   int error;
 
@@ -75,6 +75,20 @@ eintr:
     dlog("%s: unmount: %m", mntdir);
     goto eintr;
 
+#ifdef MNT2_GEN_OPT_FORCE
+  case EBUSY:
+  case EIO:
+  case ESTALE:
+    /* caller determines if forced unmounts should be used */
+    if (unmount_flags & AMU_UMOUNT_FORCE) {
+      if ((error = unmount(mntdir, MNT2_GEN_OPT_FORCE)) < 0)
+       error = errno;
+      else
+        return error;
+    }
+    /* fallthrough */
+#endif /* MNT2_GEN_OPT_FORCE */
+
   default:
     dlog("%s: unmount: %m", mntdir);
     break;
index 3bd0572da9679da56a90a6e279a7c890d3122f31..817d0dcb33101e9b3b2e4c6f4ac00032c329725a 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: umount_default.c,v 1.14 2005/01/17 19:31:54 ib42 Exp $
+ * $Id: umount_default.c,v 1.15 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -53,7 +53,7 @@
 
 
 int
-umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
+umount_fs(char *mntdir, const char *mnttabname, int unmount_flags)
 {
   mntlist *mlist, *mp, *mp_save = 0;
   int error = 0;
@@ -83,7 +83,7 @@ umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
 #endif /* MOUNT_TABLE_ON_FILE */
 
 #ifdef NEED_AUTOFS_SPACE_HACK
-    if (on_autofs) {
+    if (unmount_flags & AMU_UMOUNT_AUTOFS) {
       char *mnt_dir_save = mp_save->mnt->mnt_dir;
       mp_save->mnt->mnt_dir = autofs_strdup_space_hack(mnt_dir_save);
       error = UNMOUNT_TRAP(mp_save->mnt);
@@ -93,7 +93,7 @@ umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
 #endif /* NEED_AUTOFS_SPACE_HACK */
       error = UNMOUNT_TRAP(mp_save->mnt);
     if (error < 0) {
-      switch (error = errno) {
+      switch ((error = errno)) {
       case EINVAL:
       case ENOTBLK:
        plog(XLOG_WARNING, "unmount: %s is not mounted", mp_save->mnt->mnt_dir);
@@ -110,6 +110,26 @@ umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
        plog(XLOG_ERROR, "mount point %s: %m", mp_save->mnt->mnt_dir);
        break;
 
+#if defined(MNT2_GEN_OPT_FORCE) && (defined(HAVE_UMOUNT2) || defined(HAVE_UVMOUNT))
+      case EBUSY:
+      case EIO:
+      case ESTALE:
+       /* caller determines if forced unmounts should be used */
+       if (unmount_flags & AMU_UMOUNT_FORCE) {
+# ifdef HAVE_UMOUNT2
+         error = umount2(mntdir, MNT2_GEN_OPT_FORCE); /* Solaris */
+# else /* not HAVE_UMOUNT2 */
+#  ifdef HAVE_UVMOUNT
+         error = uvmount(mp_save->mnt->mnt_passno, MNT2_GEN_OPT_FORCE); /* AIX */
+#  endif /* HAVE_UVMOUNT */
+# endif /* not HAVE_UMOUNT2 */
+         if (error < 0)
+           error = errno;
+         else
+           break;              /* all is OK */
+       }
+       /* fallthrough */
+#endif /* MNT2_GEN_OPT_FORCE && (HAVE_UMOUNT2 || HAVE_UVMOUNT) */
       default:
        dlog("%s: unmount: %m", mp_save->mnt->mnt_dir);
        break;
index 4e5e4cf35bc7a959f1e75e5fb2f33e18b24f326e..f4b6e047693f582392faf687bccd8870193223c7 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: umount_linux.c,v 1.5 2005/07/10 21:41:49 ezk Exp $
+ * $Id: umount_linux.c,v 1.6 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -54,8 +54,9 @@
 
 
 int
-umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
+umount_fs(char *mntdir, const char *mnttabname, int unmount_flags)
 {
+  struct stat dummy;
   mntlist *mlist, *mp, *mp_save = 0;
   int error = 0;
 
@@ -83,7 +84,27 @@ umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
     unlock_mntlist();
 #endif /* MOUNT_TABLE_ON_FILE */
 
-    error = UNMOUNT_TRAP(mp_save->mnt);
+#if defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH)
+    /*
+     * If user asked to try forced unmounts, then do a quick check to see if
+     * the mount point is hung badly.  If so, then try to detach it by
+     * force; if the latter works, we're done.
+     *
+     * XXX: the stat() below may hang this unmount attempt of a toplvl
+     * mount.  In that case, you may have to kill -9 the Amd process.  A
+     * better way to handle this would be to check mtab for an old amd
+     * process, send a kill -0 to it to see if the Amd process is alive, and
+     * only do the forced unmount if the older Amd process died.
+     */
+    if ((unmount_flags & AMU_UMOUNT_DETACH) &&
+       (stat(mp_save->mnt->mnt_dir, &dummy) < 0 &&
+         (errno == ESTALE || errno == EIO))) {
+      plog(XLOG_INFO, "Forcibly unmounting stale/bad %s (%m)",
+          mp_save->mnt->mnt_dir);
+      error = umount2(mp_save->mnt->mnt_dir, MNT2_GEN_OPT_DETACH);
+    } else
+#endif /* defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH) */
+      error = UNMOUNT_TRAP(mp_save->mnt);
     if (error < 0) {
       plog(XLOG_WARNING, "unmount(%s) failed: %m", mp_save->mnt->mnt_dir);
       switch ((error = errno)) {
@@ -103,20 +124,24 @@ umount_fs(char *mntdir, const char *mnttabname, int on_autofs)
        plog(XLOG_ERROR, "mount point %s: %m", mp_save->mnt->mnt_dir);
        break;
 
-#ifdef HAVE_UMOUNT2
-# ifndef MNT_DETACH
-#  define MNT_DETACH   0x2     /* from kernel <linux/fs.h> */
-# endif /* not MNT_DETACH */
-      case EIO:
-      case ESTALE:
-       plog(XLOG_ERROR, "umount %s failed (retrying): %m", mp_save->mnt->mnt_dir);
-       error = umount2(mp_save->mnt->mnt_dir, MNT_DETACH | MNT_FORCE);
-       if (error < 0) {
-           dlog("%s: unmount2(detach+force): %m", mp_save->mnt->mnt_dir);
+#if defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH)
+      case EBUSY:
+       /*
+        * Caller determines if forced unmounts should be used now (for
+        * EBUSY).  If caller asked to force an unmount, *and* the above
+        * "trivial" unmount attempt failed with EBUSY, then try to force
+        * the unmount.
+        */
+       if (unmount_flags & AMU_UMOUNT_FORCE) {
+         error = umount2(mp_save->mnt->mnt_dir, MNT2_GEN_OPT_FORCE);
+         if (error < 0) {
+           plog(XLOG_WARNING, "%s: unmount/detach: %m",
+                mp_save->mnt->mnt_dir);
            error = errno;
+         }
        }
        break;
-#endif /* HAVE_UMOUNT2 */
+#endif /* defined(HAVE_UMOUNT2) && defined(MNT2_GEN_OPT_DETACH) */
 
       default:
        dlog("%s: unmount: %m", mp_save->mnt->mnt_dir);
index dbb6f4a646ff6bd00cc005676b7200e9272bf3c4..57719a9367bfe8fecb493b3c9b38aa468489453c 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: umount_osf.c,v 1.11 2005/01/03 20:56:45 ezk Exp $
+ * $Id: umount_osf.c,v 1.12 2005/07/20 03:32:30 ezk Exp $
  *
  */
 
@@ -53,7 +53,7 @@
 
 
 int
-umount_fs(char *fs_name, const char *mnttabname, int on_autofs)
+umount_fs(char *fs_name, const char *mnttabname, int unmount_flags)
 {
   int error;
 
@@ -78,6 +78,20 @@ eintr:
     dlog("%s: unmount: %m", fs_name);
     goto eintr;
 
+#ifdef MNT2_GEN_OPT_FORCE
+  case EBUSY:
+  case EIO:
+  case ESTALE:
+    /* caller determines if forced unmounts should be used */
+    if (unmount_flags & AMU_UMOUNT_FORCE) {
+      if ((error = umount(mntdir, MNT2_GEN_OPT_FORCE)) < 0)
+       error = errno;
+      else
+        return error;
+    }
+    /* fallthrough */
+#endif /* MNT2_GEN_OPT_FORCE */
+
   default:
     dlog("%s: unmount: %m", fs_name);
     break;
index e8e4edbe1904f926adfc1108bd13e4cf22114c71..e8fcb8c3eb4dd39a8d4a85bf96be176a99c4b65b 100644 (file)
@@ -55,7 +55,7 @@ AH_BOTTOM([
 dnl
 dnl AC_CONFIG_AUX_DIR(m4)
 AC_PREREQ(2.52)
-AC_REVISION($Revision: 1.103 $)
+AC_REVISION($Revision: 1.104 $)
 AC_COPYRIGHT([Copyright (c) 1997-2005 Erez Zadok])
 dnl find out system type
 AC_MSG_NOTICE(*** SYSTEM TYPES ***)
@@ -1063,6 +1063,8 @@ AMU_CHECK_MNT2_GEN_OPTS(  \
        bind            \
        cache           \
        data            \
+       detach          \
+       force           \
        fss             \
        grpid           \
        ignore          \
index f1e64cc25c96645088d7615a57e3ddfeb4542a66..db3f9aa042a86e43b8f6ae29a6c61af6675f0cd3 100644 (file)
@@ -38,7 +38,7 @@
 @c
 @c      %W% (Berkeley) %G%
 @c
-@c $Id: am-utils.texi,v 1.102 2005/05/03 03:14:31 ezk Exp $
+@c $Id: am-utils.texi,v 1.103 2005/07/20 03:32:30 ezk Exp $
 @c
 @setfilename am-utils.info
 
@@ -4277,6 +4277,7 @@ The following parameters are applicable to the @samp{[global]} section only.
 * dismount_interval Parameter::
 * domain_strip Parameter::
 * exec_map_timeout Parameter::
+* forced_unmounts Parameter::
 * full_os Parameter::
 * fully_qualified_hosts Parameter::
 * hesiod_base Parameter::
@@ -4423,7 +4424,7 @@ the same maps (as you may have hosts whose domain-stripped name is
 identical).
 
 @c ----------------------------------------------------------------
-@node exec_map_timeout Parameter, full_os Parameter, domain_strip Parameter, Global Parameters
+@node exec_map_timeout Parameter, forced_unmounts Parameter, domain_strip Parameter, Global Parameters
 @comment  node-name,  next,  previous,  up
 @subsection @t{exec_map_timeout} Parameter
 @cindex exec_map_timeout Parameter
@@ -4437,7 +4438,40 @@ is queried, @i{Amd} is essentially waiting and is thus not responding
 to any other queries.  @xref{Executable maps}.
 
 @c ----------------------------------------------------------------
-@node full_os Parameter, fully_qualified_hosts Parameter, exec_map_timeout Parameter, Global Parameters
+@node forced_unmounts Parameter, full_os Parameter, exec_map_timeout Parameter, Global Parameters
+@comment  node-name,  next,  previous,  up
+@subsection @t{forced_unmounts} Parameter
+@cindex forced_unmounts Parameter
+
+(type=boolean, default=@samp{no}).
+Sometimes, mount points are hung due to unrecoverable conditions, such
+as when NFS servers migrate, change their IP address, are down
+permanently, or due to hardware failures, and more.  In this case,
+attempting to unmount an existing mount point, or even just to
+@b{stat}(2) it, results in one of three fatal errors: EIO, ESTALE, or
+EBUSY.  At that point, @i{Amd} can do little to recover that hung
+point (in fact, the OS cannot automatically recover either).  For that
+reason, some OSs support special kinds of forced unmounts, which must
+be used very carefully: they will force an ummount immediately (or
+lazily on Linux), which could result in application data loss.
+However, that may be the only way to recover the entire host (without
+rebooting).  Once a hung mount point is forced out, @i{Amd} can then
+re-mount a replacement one (if available), bringing a mostly-hung
+system back to operation and avoiding a potentially costly reboot.
+
+If the @samp{forced_unmounts} option is set to @samp{yes}, and the
+client OS supports forced or lazy unmounts, then @i{Amd} will attempt
+to use them if it gets any of the three serious error conditions
+listed above.  Note that @i{Amd} will force the unmount of mount
+points that returned EBUSY only for @samp{type:=toplvl} mounts
+(@xref{Top-level Filesystem}): that is, @i{Amd}'s own mount points.
+This is useful to recover from a hung @i{Amd}.
+
+If this option is set to @samp{no} (the default), then @i{Amd} will
+not attempt this special recovery procedure.
+
+@c ----------------------------------------------------------------
+@node full_os Parameter, fully_qualified_hosts Parameter, forced_unmounts Parameter, Global Parameters
 @comment  node-name,  next,  previous,  up
 @subsection @t{full_os} Parameter
 @cindex full_os Parameter
@@ -4941,7 +4975,7 @@ the @b{statfs}(2) system call).
 @subsection @t{unmount_on_exit} Parameter
 @cindex unmount_on_exit Parameter
 
-(type=boolean), default=@samp{no}).  If @samp{yes}, then @i{Amd} will attempt
+(type=boolean, default=@samp{no}).  If @samp{yes}, then @i{Amd} will attempt
 to unmount all file systems which it knows about.  Normally it leaves
 all (esp. NFS) mounted file systems intact.  Note that @i{Amd} does not
 know about file systems mounted before it starts up, unless the
index 571aac4f114abb595710582eb1dee7f2a08c0854..97b82e1ece0b2c8d02e74a44acfc198492ae6806 100644 (file)
@@ -37,7 +37,7 @@
  * SUCH DAMAGE.
  *
  *
- * $Id: am_utils.h,v 1.66 2005/07/07 23:34:23 ezk Exp $
+ * $Id: am_utils.h,v 1.67 2005/07/20 03:32:31 ezk Exp $
  *
  */
 
  * Systems which have the mount table in a file need to read it before
  * they can perform an unmount() system call.
  */
-#define UMOUNT_FS(dir, mtb_name, on_autofs)    umount_fs(dir, mtb_name, on_autofs)
-
+#define UMOUNT_FS(dir, mtb_name, unmount_flags)        umount_fs(dir, mtb_name, unmount_flags)
 /* imported via $srcdir/conf/umount/umount_*.c */
-extern int umount_fs(char *mntdir, const char *mnttabname, int on_autofs);
+extern int umount_fs(char *mntdir, const char *mnttabname, int unmount_flags);
+/* unmount-related flags (special handling of autofs, forced/lazy, etc.) */
+#define AMU_UMOUNT_FORCE        0x1
+#define AMU_UMOUNT_DETACH       0x2
+#define AMU_UMOUNT_AUTOFS       0x4
 
 /*
  * The following values can be tuned...
index 210f799abcbd741853d712fe19e752d64dc1e880..f2f3df52e67f978a7b34544818a52e25784725b5 100644 (file)
@@ -412,6 +412,12 @@ AH_TEMPLATE([MNT2_GEN_OPT_CACHE],
 AH_TEMPLATE([MNT2_GEN_OPT_DATA],
 [6-argument mount])
 
+AH_TEMPLATE([MNT2_GEN_OPT_DETACH],
+[Use a lazy unmount (detach)])
+
+AH_TEMPLATE([MNT2_GEN_OPT_FORCE],
+[Use a forced unmount])
+
 AH_TEMPLATE([MNT2_GEN_OPT_FSS],
 [old (4-argument) mount (compatibility)])
 
index 5ece23ac7bb226b3827e9cc9b756ca82502985ef..cc43fa0f81f2a3f5d1ad2dbf31ac6621378319ea 100644 (file)
@@ -14,6 +14,7 @@ pid_file =                    /dev/stdout | /var/run/amd.pid
 # (amd -r)
 restart_mounts =               no | yes
 unmount_on_exit =              no | yes
+forced_unmounts =              no | yes
 # (amd -a)
 auto_dir =                     /a
 # duration in seconds that a looked up name remain cached (amd -c)
index e0654f7f9806dd2f4231c81d0af1da1de62a02c3..141c5a062cff06af7ea92aaa4c4ee8b9b4e9101b 100644 (file)
@@ -38,7 +38,7 @@
 .\"
 .\"    %W% (Berkeley) %G%
 .\"
-.\" $Id: amd.conf.5,v 1.37 2005/04/17 03:05:54 ezk Exp $
+.\" $Id: amd.conf.5,v 1.38 2005/07/20 03:32:31 ezk Exp $
 .\"
 .TH AMD.CONF 5 "7 August 1997"
 .SH NAME
@@ -280,6 +280,21 @@ because during the time that the executable map program is queried,
 .I Amd
 is essentially waiting and is thus not responding to any other queries.
 
+.TP
+.BR forced_unmounts " (boolean, default=no)"
+If set to "yes," and the client OS supports forced or lazy unmounts, then
+.I Amd
+will attempt to use them if it gets any of three serious error conditions
+when trying to unmount an existing mount point or mount on top of one: EIO,
+ESTALE, or EBUSY.
+
+This could be useful to recover from serious conditions such as hardware
+failure of mounted disks, or NFS servers which are down permanently, were
+migrated, or changed their IP address.  Only "type:=toplvl" mounts hung with
+EBUSY are forcibly unmounted using this option, which is useful to recover
+from a hung
+.IR Amd ).
+
 .TP
 .BR full_os " (string, default to compiled in value)"
 The full name of the operating system, along with its version.  Allows you