xref: /original-bsd/usr.sbin/amd/amd/mntfs.c (revision 36940495)
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 
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));
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));
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));
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 
203 mntfs *new_mntfs()
204 {
205 	return alloc_mntfs(&efs_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
206 }
207 
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 
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 
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 
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));
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