Am-Utils Cross Reference
am-utils/amd/amfs_toplvl.c

source navigation ]
diff markup ]
identifier search ]
freetext search ]
file search ]
 
Version: 6.0.1 ] [ 6.0.2 ] [ 6.0.3 ] [ 6.0.4 ] [ 6.0.5 ] [ 6.0.6 ] [ 6.0.7 ] [ 6.0.8 ] [ 6.0.9 ] [ 6.0.10 ] [ 6.1 ] [ 6.1.1 ]

  1 /*
  2  * Copyright (c) 1997-2005 Erez Zadok
  3  * Copyright (c) 1990 Jan-Simon Pendry
  4  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
  5  * Copyright (c) 1990 The Regents of the University of California.
  6  * All rights reserved.
  7  *
  8  * This code is derived from software contributed to Berkeley by
  9  * Jan-Simon Pendry at Imperial College, London.
 10  *
 11  * Redistribution and use in source and binary forms, with or without
 12  * modification, are permitted provided that the following conditions
 13  * are met:
 14  * 1. Redistributions of source code must retain the above copyright
 15  *    notice, this list of conditions and the following disclaimer.
 16  * 2. Redistributions in binary form must reproduce the above copyright
 17  *    notice, this list of conditions and the following disclaimer in the
 18  *    documentation and/or other materials provided with the distribution.
 19  * 3. All advertising materials mentioning features or use of this software
 20  *    must display the following acknowledgment:
 21  *      This product includes software developed by the University of
 22  *      California, Berkeley and its contributors.
 23  * 4. Neither the name of the University nor the names of its contributors
 24  *    may be used to endorse or promote products derived from this software
 25  *    without specific prior written permission.
 26  *
 27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 37  * SUCH DAMAGE.
 38  *
 39  *
 40  * File: am-utils/amd/amfs_toplvl.c
 41  *
 42  */
 43 
 44 /*
 45  * Top-level file system
 46  */
 47 
 48 #ifdef HAVE_CONFIG_H
 49 # include <config.h>
 50 #endif /* HAVE_CONFIG_H */
 51 #include <am_defs.h>
 52 #include <amd.h>
 53 
 54 /****************************************************************************
 55  *** FORWARD DEFINITIONS                                                  ***
 56  ****************************************************************************/
 57 static int amfs_toplvl_init(mntfs *mf);
 58 
 59 /****************************************************************************
 60  *** OPS STRUCTURES                                                       ***
 61  ****************************************************************************/
 62 am_ops amfs_toplvl_ops =
 63 {
 64   "toplvl",
 65   amfs_generic_match,
 66   amfs_toplvl_init,             /* amfs_toplvl_init */
 67   amfs_toplvl_mount,
 68   amfs_toplvl_umount,
 69   amfs_generic_lookup_child,
 70   amfs_generic_mount_child,
 71   amfs_generic_readdir,
 72   0,                            /* amfs_toplvl_readlink */
 73   amfs_generic_mounted,
 74   0,                            /* amfs_toplvl_umounted */
 75   amfs_generic_find_srvr,
 76   0,                            /* amfs_toplvl_get_wchan */
 77   FS_MKMNT | FS_NOTIMEOUT | FS_BACKGROUND |
 78           FS_AMQINFO | FS_DIRECTORY, /* nfs_fs_flags */
 79 #ifdef HAVE_FS_AUTOFS
 80   AUTOFS_TOPLVL_FS_FLAGS,
 81 #endif /* HAVE_FS_AUTOFS */
 82 };
 83 
 84 
 85 /****************************************************************************
 86  *** FUNCTIONS                                                             ***
 87  ****************************************************************************/
 88 
 89 static void
 90 set_auto_attrcache_timeout(char *preopts, char *opts)
 91 {
 92 
 93 #ifdef MNTTAB_OPT_NOAC
 94   /*
 95    * Don't cache attributes - they are changing under the kernel's feet.
 96    * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
 97    * filehandles to getattr unless we disable attribute caching on the
 98    * automount points.
 99    */
100   if (gopt.auto_attrcache == 0) {
101     sprintf(preopts, ",%s", MNTTAB_OPT_NOAC);
102     strcat(opts, preopts);
103   }
104 #endif /* MNTTAB_OPT_NOAC */
105 
106   /*
107    * XXX: note that setting these to 0 in the past resulted in an error on
108    * some systems, which is why it's better to use "noac" if possible.  For
109    * now, we're setting everything possible, but if this will cause trouble,
110    * then we'll have to condition the remainder of this on OPT_NOAC.
111    */
112 #ifdef MNTTAB_OPT_ACTIMEO
113   sprintf(preopts, ",%s=%d", MNTTAB_OPT_ACTIMEO, gopt.auto_attrcache);
114   strcat(opts, preopts);
115 #else /* MNTTAB_OPT_ACTIMEO */
116 # ifdef MNTTAB_OPT_ACDIRMIN
117   sprintf(preopts, ",%s=%d", MNTTAB_OPT_ACTDIRMIN, gopt.auto_attrcache);
118   strcat(opts, preopts);
119 # endif /* MNTTAB_OPT_ACDIRMIN */
120 # ifdef MNTTAB_OPT_ACDIRMAX
121   sprintf(preopts, ",%s=%d", MNTTAB_OPT_ACTDIRMAX, gopt.auto_attrcache);
122   strcat(opts, preopts);
123 # endif /* MNTTAB_OPT_ACDIRMAX */
124 # ifdef MNTTAB_OPT_ACREGMIN
125   sprintf(preopts, ",%s=%d", MNTTAB_OPT_ACTREGMIN, gopt.auto_attrcache);
126   strcat(opts, preopts);
127 # endif /* MNTTAB_OPT_ACREGMIN */
128 # ifdef MNTTAB_OPT_ACREGMAX
129   sprintf(preopts, ",%s=%d", MNTTAB_OPT_ACTREGMAX, gopt.auto_attrcache);
130   strcat(opts, preopts);
131 # endif /* MNTTAB_OPT_ACREGMAX */
132 #endif /* MNTTAB_OPT_ACTIMEO */
133 }
134 
135 
136 /*
137  * Initialize a top-level mount.  In our case, if the user asked for
138  * forced_unmounts, and the OS supports it, then we try forced/lazy unmounts
139  * on any previous toplvl mounts.  This is useful if a previous Amd died and
140  * left behind toplvl mount points (this Amd will clean them up).
141  *
142  * WARNING: Don't use forced/lazy unmounts if you have another valid Amd
143  * running, because this code WILL force those valid toplvl mount points to
144  * be detached as well!
145  */
146 static int
147 amfs_toplvl_init(mntfs *mf)
148 {
149   int error = 0;
150 
151 #if defined(MNT2_GEN_OPT_FORCE) || defined(MNT2_GEN_OPT_DETACH)
152   if (gopt.flags & CFM_FORCED_UNMOUNTS) {
153     plog(XLOG_INFO, "amfs_toplvl_init: trying forced/lazy unmount of %s",
154          mf->mf_mount);
155     error = umount2_fs(mf->mf_mount, AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH);
156     if (error)
157       plog(XLOG_INFO, "amfs_toplvl_init: forced/lazy unmount failed: %m");
158     else
159       dlog("amfs_toplvl_init: forced/lazy unmount succeeded");
160   }
161 #endif /* MNT2_GEN_OPT_FORCE || MNT2_GEN_OPT_DETACH */
162   return error;
163 }
164 
165 
166 /*
167  * Mount the top-level
168  */
169 int
170 amfs_toplvl_mount(am_node *mp, mntfs *mf)
171 {
172   struct stat stb;
173   char opts[256], preopts[256];
174   int error;
175 
176   /*
177    * Mounting the automounter.
178    * Make sure the mount directory exists, construct
179    * the mount options and call the mount_amfs_toplvl routine.
180    */
181 
182   if (stat(mp->am_path, &stb) < 0) {
183     return errno;
184   } else if ((stb.st_mode & S_IFMT) != S_IFDIR) {
185     plog(XLOG_WARNING, "%s is not a directory", mp->am_path);
186     return ENOTDIR;
187   }
188 
189   /*
190    * Construct some mount options:
191    *
192    * Tack on magic map=<mapname> option in mtab to emulate
193    * SunOS automounter behavior.
194    */
195 
196 #ifdef HAVE_FS_AUTOFS
197   if (mf->mf_flags & MFF_IS_AUTOFS) {
198     autofs_get_opts(opts, mp->am_autofs_fh);
199   } else
200 #endif /* HAVE_FS_AUTOFS */
201   {
202     preopts[0] = '\0';
203 #ifdef MNTTAB_OPT_INTR
204     strcat(preopts, MNTTAB_OPT_INTR);
205     strcat(preopts, ",");
206 #endif /* MNTTAB_OPT_INTR */
207 #ifdef MNTTAB_OPT_IGNORE
208     strcat(preopts, MNTTAB_OPT_IGNORE);
209     strcat(preopts, ",");
210 #endif /* MNTTAB_OPT_IGNORE */
211 #ifdef WANT_TIMEO_AND_RETRANS_ON_TOPLVL
212     sprintf(opts, "%s%s,%s=%d,%s=%d,%s=%d,%s,map=%s",
213 #else /* WANT_TIMEO_AND_RETRANS_ON_TOPLVL */
214     sprintf(opts, "%s%s,%s=%d,%s,map=%s",
215 #endif /* WANT_TIMEO_AND_RETRANS_ON_TOPLVL */
216             preopts,
217             MNTTAB_OPT_RW,
218             MNTTAB_OPT_PORT, nfs_port,
219 #ifdef WANT_TIMEO_AND_RETRANS_ON_TOPLVL
220             /* note: TIMEO+RETRANS for toplvl are only "udp" currently */
221             MNTTAB_OPT_TIMEO, gopt.amfs_auto_timeo[AMU_TYPE_UDP],
222             MNTTAB_OPT_RETRANS, gopt.amfs_auto_retrans[AMU_TYPE_UDP],
223 #endif /* WANT_TIMEO_AND_RETRANS_ON_TOPLVL */
224             mf->mf_ops->fs_type, mf->mf_info);
225 #ifdef MNTTAB_OPT_NOAC
226     if (gopt.auto_attrcache == 0) {
227       strcat(opts, ",");
228       strcat(opts, MNTTAB_OPT_NOAC);
229     } else
230 #endif /* MNTTAB_OPT_NOAC */
231       set_auto_attrcache_timeout(preopts, opts);
232   }
233 
234   /* now do the mount */
235   error = amfs_mount(mp, mf, opts);
236   if (error) {
237     errno = error;
238     plog(XLOG_FATAL, "amfs_toplvl_mount: amfs_mount failed: %m");
239     return error;
240   }
241   return 0;
242 }
243 
244 
245 /*
246  * Unmount a top-level automount node
247  */
248 int
249 amfs_toplvl_umount(am_node *mp, mntfs *mf)
250 {
251   struct stat stb;
252   int unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
253   int error;
254   int count = 0;                /* how many times did we try to unmount? */
255 
256 again:
257   /*
258    * The lstat is needed if this mount is type=direct.
259    * When that happens, the kernel cache gets confused
260    * between the underlying type (dir) and the mounted
261    * type (link) and so needs to be re-synced before
262    * the unmount.  This is all because the unmount system
263    * call follows links and so can't actually unmount
264    * a link (stupid!).  It was noted that doing an ls -ld
265    * of the mount point to see why things were not working
266    * actually fixed the problem - so simulate an ls -ld here.
267    */
268   if (lstat(mp->am_path, &stb) < 0) {
269     error = errno;
270     dlog("lstat(%s): %m", mp->am_path);
271     goto out;
272   }
273   if ((stb.st_mode & S_IFMT) != S_IFDIR) {
274     plog(XLOG_ERROR, "amfs_toplvl_umount: %s is not a directory, aborting.", mp->am_path);
275     error = ENOTDIR;
276     goto out;
277   }
278 
279   error = UMOUNT_FS(mp->am_path, mnttab_file_name, unmount_flags);
280   if (error == EBUSY) {
281 #ifdef HAVE_FS_AUTOFS
282     /*
283      * autofs mounts are "in place", so it is possible
284      * that we can't just unmount our mount points and go away.
285      * If that's the case, just give up.
286      */
287     if (mf->mf_flags & MFF_IS_AUTOFS)
288       return error;
289 #endif /* HAVE_FS_AUTOFS */
290     plog(XLOG_WARNING, "amfs_toplvl_unmount retrying %s in 1s", mp->am_path);
291     count++;
292     sleep(1);
293     /*
294      * If user wants forced/lazy unmount semantics, then set those flags,
295      * but only after we've tried normal lstat/umount a few times --
296      * otherwise forced unmounts may hang this very same Amd (by preventing
297      * it from achieving a clean unmount).
298      */
299     if (gopt.flags & CFM_FORCED_UNMOUNTS) {
300       if (count == 5) {         /* after 5 seconds, try MNT_FORCE */
301         dlog("enabling forced unmounts for toplvl node %s", mp->am_path);
302         unmount_flags |= AMU_UMOUNT_FORCE;
303       }
304       if (count == 10) {        /* after 10 seconds, try MNT_DETACH */
305         dlog("enabling detached unmounts for toplvl node %s", mp->am_path);
306         unmount_flags |= AMU_UMOUNT_DETACH;
307       }
308     }
309     goto again;
310   }
311 out:
312   return error;
313 }
314 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
This page is hosted at the Filesystems and Storage Lab at Stony Brook.