Merge from vendor branch GDB:
[dragonfly.git] / contrib / amd / amd / mntfs.c
1 /*
2  * Copyright (c) 1997-1999 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  *      %W% (Berkeley) %G%
40  *
41  * $Id: mntfs.c,v 1.2 1999/01/10 21:53:47 ezk Exp $
42  *
43  */
44
45 #ifdef HAVE_CONFIG_H
46 # include <config.h>
47 #endif /* HAVE_CONFIG_H */
48 #include <am_defs.h>
49 #include <amd.h>
50
51 qelem mfhead = {&mfhead, &mfhead};
52
53 int mntfs_allocated;
54
55
56 mntfs *
57 dup_mntfs(mntfs *mf)
58 {
59   if (mf->mf_refc == 0) {
60     if (mf->mf_cid)
61       untimeout(mf->mf_cid);
62     mf->mf_cid = 0;
63   }
64   mf->mf_refc++;
65
66   return mf;
67 }
68
69
70 static void
71 init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
72 {
73   mf->mf_ops = ops;
74   mf->mf_fo = mo;
75   mf->mf_mount = strdup(mp);
76   mf->mf_info = strdup(info);
77   mf->mf_auto = strdup(auto_opts);
78   mf->mf_mopts = strdup(mopts);
79   mf->mf_remopts = strdup(remopts);
80   mf->mf_refc = 1;
81   mf->mf_flags = 0;
82   mf->mf_error = -1;
83   mf->mf_cid = 0;
84   mf->mf_private = 0;
85   mf->mf_prfree = 0;
86
87   if (ops->ffserver)
88     mf->mf_server = (*ops->ffserver) (mf);
89   else
90     mf->mf_server = 0;
91 }
92
93
94 static mntfs *
95 alloc_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
96 {
97   mntfs *mf = ALLOC(struct mntfs);
98
99   init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts);
100   ins_que(&mf->mf_q, &mfhead);
101   mntfs_allocated++;
102
103   return mf;
104 }
105
106
107 mntfs *
108 find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
109 {
110   mntfs *mf;
111
112 #ifdef DEBUG
113   dlog("Locating mntfs reference to %s", mp);
114 #endif /* DEBUG */
115
116   ITER(mf, mntfs, &mfhead) {
117     if (STREQ(mf->mf_mount, mp)) {
118       /*
119        * Handle cases where error ops are involved
120        */
121       if (ops == &amfs_error_ops) {
122         /*
123          * If the existing ops are not amfs_error_ops
124          * then continue...
125          */
126         if (mf->mf_ops != &amfs_error_ops)
127           continue;
128         else
129           return dup_mntfs(mf);
130       } else {                  /* ops != &amfs_error_ops */
131         /*
132          * If the existing ops are amfs_error_ops
133          * then continue...
134          */
135         if (mf->mf_ops == &amfs_error_ops)
136           continue;
137       }
138
139       if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
140         /*
141          * Restart a previously mounted filesystem.
142          */
143         mntfs *mf2 = alloc_mntfs(&amfs_inherit_ops, mo, mp, info, auto_opts, mopts, remopts);
144 #ifdef DEBUG
145         dlog("Restarting filesystem %s", mf->mf_mount);
146 #endif /* DEBUG */
147
148         /*
149          * Remember who we are restarting
150          */
151         mf2->mf_private = (voidp) dup_mntfs(mf);
152         mf2->mf_prfree = free_mntfs;
153         return mf2;
154       }
155
156       mf->mf_fo = mo;
157       if (!(mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))) {
158         fserver *fs;
159         mf->mf_flags &= ~MFF_ERROR;
160         mf->mf_error = -1;
161         mf->mf_auto = strealloc(mf->mf_auto, auto_opts);
162         mf->mf_mopts = strealloc(mf->mf_mopts, mopts);
163         mf->mf_remopts = strealloc(mf->mf_remopts, remopts);
164         mf->mf_info = strealloc(mf->mf_info, info);
165
166         if (mf->mf_private && mf->mf_prfree) {
167           (*mf->mf_prfree) (mf->mf_private);
168           mf->mf_private = 0;
169         }
170
171         fs = ops->ffserver ? (*ops->ffserver) (mf) : (fserver *) NULL;
172         if (mf->mf_server)
173           free_srvr(mf->mf_server);
174         mf->mf_server = fs;
175       }
176       return dup_mntfs(mf);
177     }
178   }
179
180   return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
181 }
182
183
184 mntfs *
185 new_mntfs(void)
186 {
187   return alloc_mntfs(&amfs_error_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
188 }
189
190
191 static void
192 uninit_mntfs(mntfs *mf, int rmd)
193 {
194   if (mf->mf_auto)
195     XFREE(mf->mf_auto);
196   if (mf->mf_mopts)
197     XFREE(mf->mf_mopts);
198   if (mf->mf_remopts)
199     XFREE(mf->mf_remopts);
200   if (mf->mf_info)
201     XFREE(mf->mf_info);
202   if (mf->mf_private && mf->mf_prfree)
203     (*mf->mf_prfree) (mf->mf_private);
204
205   /*
206    * Clean up any directories that were made
207    */
208   if (rmd && (mf->mf_flags & MFF_MKMNT))
209     rmdirs(mf->mf_mount);
210   /* free mf_mount _AFTER_ removing the directories */
211   if (mf->mf_mount)
212     XFREE(mf->mf_mount);
213
214   /*
215    * Clean up the file server
216    */
217   if (mf->mf_server)
218     free_srvr(mf->mf_server);
219
220   /*
221    * Don't do a callback on this mount
222    */
223   if (mf->mf_cid) {
224     untimeout(mf->mf_cid);
225     mf->mf_cid = 0;
226   }
227 }
228
229
230 static void
231 discard_mntfs(voidp v)
232 {
233   mntfs *mf = v;
234
235   rem_que(&mf->mf_q);
236
237   /*
238    * Free memory
239    */
240   uninit_mntfs(mf, TRUE);
241   XFREE(mf);
242
243   --mntfs_allocated;
244 }
245
246
247 void
248 flush_mntfs(void)
249 {
250   mntfs *mf;
251
252   mf = AM_FIRST(mntfs, &mfhead);
253   while (mf != HEAD(mntfs, &mfhead)) {
254     mntfs *mf2 = mf;
255     mf = NEXT(mntfs, mf);
256     if (mf2->mf_refc == 0 && mf2->mf_cid)
257       discard_mntfs(mf2);
258   }
259 }
260
261
262 void
263 free_mntfs(voidp v)
264 {
265   mntfs *mf = v;
266
267   if (--mf->mf_refc == 0) {
268     if (mf->mf_flags & MFF_MOUNTED) {
269       int quoted;
270       mf->mf_flags &= ~MFF_MOUNTED;
271
272       /*
273        * Record for posterity
274        */
275       quoted = strchr(mf->mf_info, ' ') != 0;   /* cheap */
276       plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s",
277            quoted ? "\"" : "",
278            mf->mf_info,
279            quoted ? "\"" : "",
280            mf->mf_error ? "discard" : "unmount",
281            mf->mf_ops->fs_type, mf->mf_mount);
282     }
283
284     if (mf->mf_ops->fs_flags & FS_DISCARD) {
285 #ifdef DEBUG
286       dlog("Immediately discarding mntfs for %s", mf->mf_mount);
287 #endif /* DEBUG */
288       discard_mntfs(mf);
289
290     } else {
291
292 #ifdef DEBUG
293       if (mf->mf_flags & MFF_RESTART) {
294         dlog("Discarding remount hook for %s", mf->mf_mount);
295       } else {
296         dlog("Discarding last mntfs reference to %s fstype %s",
297              mf->mf_mount, mf->mf_ops->fs_type);
298       }
299       if (mf->mf_flags & (MFF_MOUNTED | MFF_MOUNTING | MFF_UNMOUNTING))
300         dlog("mntfs reference for %s still active", mf->mf_mount);
301 #endif /* DEBUG */
302       mf->mf_cid = timeout(ALLOWED_MOUNT_TIME, discard_mntfs, (voidp) mf);
303     }
304   }
305 }
306
307
308 mntfs *
309 realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts)
310 {
311   mntfs *mf2;
312
313   if (mf->mf_refc == 1 && mf->mf_ops == &amfs_inherit_ops && STREQ(mf->mf_mount, mp)) {
314     /*
315      * If we are inheriting then just return
316      * the same node...
317      */
318     return mf;
319   }
320
321   /*
322    * Re-use the existing mntfs if it is mounted.
323    * This traps a race in nfsx.
324    */
325   if (mf->mf_ops != &amfs_error_ops &&
326       (mf->mf_flags & MFF_MOUNTED) &&
327       !FSRV_ISDOWN(mf->mf_server)) {
328     mf->mf_fo = mo;
329     return mf;
330   }
331
332   mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
333   free_mntfs(mf);
334   return mf2;
335 }