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