1 /*-
2 * Copyright (c) 1990 Jan-Simon Pendry
3 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Jan-Simon Pendry at Imperial College, London.
9 *
10 * %sccs.include.redist.c%
11 *
12 * $Id: mntfs.c,v 5.2.2.1 1992/02/09 15:08:42 jsp beta $
13 */
14
15 #ifndef lint
16 static char sccsid[] = "@(#)mntfs.c 8.1 (Berkeley) 06/06/93";
17 #endif /* not lint */
18
19
20 #include "am.h"
21
22 extern qelem mfhead;
23 qelem mfhead = { &mfhead, &mfhead };
24
25 int mntfs_allocated;
26
27 #ifdef notdef
28 /*
29 * This is the default attributes field which
30 * is copied into every new node to be created.
31 * The individual filesystem fs_init() routines
32 * patch the copy to represent the particular
33 * details for the relevant filesystem type
34 */
35 static struct fattr gen_fattr = {
36 NFDIR, /* type */
37 NFSMODE_DIR | 0555, /* mode */
38 2, /* nlink */
39 0, /* uid */
40 0, /* gid */
41 512, /* size */
42 4096, /* blocksize */
43 0, /* rdev */
44 1, /* blocks */
45 0, /* fsid */
46 0, /* fileid */
47 { 0, 0 }, /* atime */
48 { 0, 0 }, /* mtime */
49 { 0, 0 }, /* ctime */
50 };
51 #endif /* notdef */
52
dup_mntfs(mf)53 mntfs *dup_mntfs(mf)
54 mntfs *mf;
55 {
56 if (mf->mf_refc == 0) {
57 if (mf->mf_cid)
58 untimeout(mf->mf_cid);
59 mf->mf_cid = 0;
60 #ifdef notdef
61 mf->mf_error = -1;
62 mf->mf_flags &= ~MFF_ERROR;
63 #endif
64 }
65 mf->mf_refc++;
66 return mf;
67 }
68
69 static void init_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
init_mntfs(mf,ops,mo,mp,info,auto_opts,mopts,remopts)70 static void init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts)
71 mntfs *mf;
72 am_ops *ops;
73 am_opts *mo;
74 char *mp;
75 char *info;
76 char *auto_opts;
77 char *mopts;
78 char *remopts;
79 {
80 mf->mf_ops = ops;
81 mf->mf_fo = mo;
82 mf->mf_mount = strdup(mp);
83 mf->mf_info = strdup(info);
84 mf->mf_auto = strdup(auto_opts);
85 mf->mf_mopts = strdup(mopts);
86 mf->mf_remopts = strdup(remopts);
87 mf->mf_refc = 1;
88 mf->mf_flags = 0;
89 mf->mf_error = -1;
90 mf->mf_cid = 0;
91 mf->mf_private = 0;
92 mf->mf_prfree = 0;
93 #ifdef notdef
94 mf->mf_attr.status = NFS_OK;
95 mf->mf_fattr = gen_fattr;
96 mf->mf_fattr.fsid = 42;
97 mf->mf_fattr.fileid = 0;
98 mf->mf_fattr.atime.seconds = clocktime();
99 mf->mf_fattr.atime.useconds = 0;
100 mf->mf_fattr.mtime = mf->mf_fattr.ctime = mf->mf_fattr.atime;
101 #endif
102
103 if (ops->ffserver)
104 mf->mf_server = (*ops->ffserver)(mf);
105 else
106 mf->mf_server = 0;
107 }
108
109 static mntfs *alloc_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
alloc_mntfs(ops,mo,mp,info,auto_opts,mopts,remopts)110 static mntfs *alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts)
111 am_ops *ops;
112 am_opts *mo;
113 char *mp;
114 char *info;
115 char *auto_opts;
116 char *mopts;
117 char *remopts;
118 {
119 mntfs *mf = ALLOC(mntfs);
120 init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts);
121 ins_que(&mf->mf_q, &mfhead);
122 mntfs_allocated++;
123
124 return mf;
125 }
126
127 mntfs *find_mntfs P((am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
find_mntfs(ops,mo,mp,info,auto_opts,mopts,remopts)128 mntfs *find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts)
129 am_ops *ops;
130 am_opts *mo;
131 char *mp;
132 char *info;
133 char *auto_opts;
134 char *mopts;
135 char *remopts;
136 {
137 mntfs *mf;
138
139 #ifdef DEBUG
140 dlog("Locating mntfs reference to %s", mp);
141 #endif /* DEBUG */
142 ITER(mf, mntfs, &mfhead) {
143 if (STREQ(mf->mf_mount, mp)) {
144 /*
145 * Handle cases where error ops are involved
146 */
147 if (ops == &efs_ops) {
148 /*
149 * If the existing ops are not efs_ops
150 * then continue...
151 */
152 if (mf->mf_ops != &efs_ops)
153 continue;
154 } else /* ops != &efs_ops */ {
155 /*
156 * If the existing ops are efs_ops
157 * then continue...
158 */
159 if (mf->mf_ops == &efs_ops)
160 continue;
161 }
162
163 if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
164 /*
165 * Restart a previously mounted filesystem.
166 */
167 mntfs *mf2 = alloc_mntfs(&ifs_ops, mo, mp, info, auto_opts, mopts, remopts);
168 #ifdef DEBUG
169 dlog("Restarting filesystem %s", mf->mf_mount);
170 #endif /* DEBUG */
171 /*
172 * Remember who we are restarting
173 */
174 mf2->mf_private = (voidp) dup_mntfs(mf);
175 mf2->mf_prfree = free_mntfs;
176 return mf2;
177 }
178 mf->mf_fo = mo;
179 if (!(mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING))) {
180 fserver *fs;
181 mf->mf_flags &= ~MFF_ERROR;
182 mf->mf_error = -1;
183 mf->mf_auto = strealloc(mf->mf_auto, auto_opts);
184 mf->mf_mopts = strealloc(mf->mf_mopts, mopts);
185 mf->mf_remopts = strealloc(mf->mf_remopts, remopts);
186 mf->mf_info = strealloc(mf->mf_info, info);
187 if (mf->mf_private && mf->mf_prfree) {
188 (*mf->mf_prfree)(mf->mf_private);
189 mf->mf_private = 0;
190 }
191 fs = ops->ffserver ? (*ops->ffserver)(mf) : (fserver *) 0;
192 if (mf->mf_server)
193 free_srvr(mf->mf_server);
194 mf->mf_server = fs;
195 }
196 return dup_mntfs(mf);
197 }
198 }
199
200 return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
201 }
202
new_mntfs()203 mntfs *new_mntfs()
204 {
205 return alloc_mntfs(&efs_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
206 }
207
uninit_mntfs(mf,rmd)208 static void uninit_mntfs(mf, rmd)
209 mntfs *mf;
210 int rmd;
211 {
212 if (mf->mf_mount) free((voidp) mf->mf_mount);
213 if (mf->mf_auto) free((voidp) mf->mf_auto);
214 if (mf->mf_mopts) free((voidp) mf->mf_mopts);
215 if (mf->mf_remopts) free((voidp) mf->mf_remopts);
216 if (mf->mf_info) free((voidp) mf->mf_info);
217 if (mf->mf_private && mf->mf_prfree)
218 (*mf->mf_prfree)(mf->mf_private);
219 /*
220 * Clean up any directories that were made
221 */
222 if (rmd && (mf->mf_flags & MFF_MKMNT))
223 rmdirs(mf->mf_mount);
224
225 /*
226 * Clean up the file server
227 */
228 if (mf->mf_server)
229 free_srvr(mf->mf_server);
230
231 /*
232 * Don't do a callback on this mount
233 */
234 if (mf->mf_cid) {
235 untimeout(mf->mf_cid);
236 mf->mf_cid = 0;
237 }
238 }
239
discard_mntfs(mf)240 static void discard_mntfs(mf)
241 mntfs *mf;
242 {
243 rem_que(&mf->mf_q);
244 /*
245 * Free memory
246 */
247 uninit_mntfs(mf, TRUE);
248 free((voidp) mf);
249
250 --mntfs_allocated;
251 }
252
flush_mntfs()253 void flush_mntfs()
254 {
255 mntfs *mf;
256
257 mf = FIRST(mntfs, &mfhead);
258 while (mf != HEAD(mntfs, &mfhead)) {
259 mntfs *mf2 = mf;
260 mf = NEXT(mntfs, mf);
261 if (mf2->mf_refc == 0 && mf2->mf_cid)
262 discard_mntfs(mf2);
263 }
264 }
265
free_mntfs(mf)266 void free_mntfs(mf)
267 mntfs *mf;
268 {
269 if (--mf->mf_refc == 0) {
270 if (mf->mf_flags & MFF_MOUNTED) {
271 int quoted;
272 mf->mf_flags &= ~MFF_MOUNTED;
273
274 /*
275 * Record for posterity
276 */
277 quoted = strchr(mf->mf_info, ' ') != 0; /* cheap */
278 plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s",
279 quoted ? "\"" : "",
280 mf->mf_info,
281 quoted ? "\"" : "",
282 mf->mf_error ? "discard" : "unmount",
283 mf->mf_ops->fs_type, mf->mf_mount);
284 }
285
286 if (mf->mf_ops->fs_flags & FS_DISCARD) {
287 #ifdef DEBUG
288 dlog("Immediately discarding mntfs for %s", mf->mf_mount);
289 #endif /* DEBUG */
290 discard_mntfs(mf);
291 } else {
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 mntfs *realloc_mntfs P((mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info, char *auto_opts, char *mopts, char *remopts));
realloc_mntfs(mf,ops,mo,mp,info,auto_opts,mopts,remopts)308 mntfs *realloc_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts)
309 mntfs *mf;
310 am_ops *ops;
311 am_opts *mo;
312 char *mp;
313 char *info;
314 char *auto_opts;
315 char *mopts;
316 char *remopts;
317 {
318 mntfs *mf2;
319 if (mf->mf_refc == 1 && mf->mf_ops == &ifs_ops && STREQ(mf->mf_mount, mp)) {
320 /*
321 * If we are inheriting then just return
322 * the same node...
323 */
324 return mf;
325 }
326
327 /*
328 * Re-use the existing mntfs if it is mounted.
329 * This traps a race in nfsx.
330 */
331 if (mf->mf_ops != &efs_ops &&
332 (mf->mf_flags & MFF_MOUNTED) &&
333 !FSRV_ISDOWN(mf->mf_server)) {
334 mf->mf_fo = mo;
335 return mf;
336 }
337
338 mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
339 free_mntfs(mf);
340 return mf2;
341 }
342