GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/amd/amd/mntfs.c Lines: 0 99 0.0 %
Date: 2016-12-06 Branches: 0 72 0.0 %

Line Branch Exec Source
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
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 * 3. Neither the name of the University nor the names of its contributors
19
 *    may be used to endorse or promote products derived from this software
20
 *    without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 */
34
35
#include "am.h"
36
37
extern qelem mfhead;
38
qelem mfhead = { &mfhead, &mfhead };
39
40
int mntfs_allocated;
41
42
#ifdef notdef
43
/*
44
 * This is the default attributes field which
45
 * is copied into every new node to be created.
46
 * The individual filesystem fs_init() routines
47
 * patch the copy to represent the particular
48
 * details for the relevant filesystem type
49
 */
50
static struct fattr gen_fattr = {
51
	NFDIR,				/* type */
52
	NFSMODE_DIR | 0555,		/* mode */
53
	2,				/* nlink */
54
	0,				/* uid */
55
	0,				/* gid */
56
	512,				/* size */
57
	4096,				/* blocksize */
58
	0,				/* rdev */
59
	1,				/* blocks */
60
	0,				/* fsid */
61
	0,				/* fileid */
62
	{ 0, 0 },			/* atime */
63
	{ 0, 0 },			/* mtime */
64
	{ 0, 0 },			/* ctime */
65
};
66
#endif /* notdef */
67
68
mntfs *
69
dup_mntfs(mntfs *mf)
70
{
71
	if (mf->mf_refc == 0) {
72
		if (mf->mf_cid)
73
			untimeout(mf->mf_cid);
74
		mf->mf_cid = 0;
75
#ifdef notdef
76
		mf->mf_error = -1;
77
		mf->mf_flags &= ~MFF_ERROR;
78
#endif
79
	}
80
	mf->mf_refc++;
81
	return mf;
82
}
83
84
static void
85
init_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp, char *info,
86
    char *auto_opts, char *mopts, char *remopts)
87
{
88
	mf->mf_ops = ops;
89
	mf->mf_fo = mo;
90
	mf->mf_mount = strdup(mp);
91
	mf->mf_info = strdup(info);
92
	mf->mf_auto = strdup(auto_opts);
93
	mf->mf_mopts = strdup(mopts);
94
	mf->mf_remopts = strdup(remopts);
95
	mf->mf_refc = 1;
96
	mf->mf_flags = 0;
97
	mf->mf_error = -1;
98
	mf->mf_cid = 0;
99
	mf->mf_private = 0;
100
	mf->mf_prfree = 0;
101
#ifdef notdef
102
	mf->mf_attr.status = NFS_OK;
103
	mf->mf_fattr = gen_fattr;
104
	mf->mf_fattr.fsid = 42;
105
	mf->mf_fattr.fileid = 0;
106
	mf->mf_fattr.atime.seconds = clocktime();
107
	mf->mf_fattr.atime.useconds = 0;
108
	mf->mf_fattr.mtime = mf->mf_fattr.ctime = mf->mf_fattr.atime;
109
#endif
110
111
	if (ops->ffserver)
112
		mf->mf_server = (*ops->ffserver)(mf);
113
	else
114
		mf->mf_server = 0;
115
}
116
117
static mntfs *
118
alloc_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info,
119
    char *auto_opts, char *mopts, char *remopts)
120
{
121
	mntfs *mf = ALLOC(mntfs);
122
	init_mntfs(mf, ops, mo, mp, info, auto_opts, mopts, remopts);
123
	ins_que(&mf->mf_q, &mfhead);
124
	mntfs_allocated++;
125
126
	return mf;
127
}
128
129
mntfs *
130
find_mntfs(am_ops *ops, am_opts *mo, char *mp, char *info,
131
    char *auto_opts, char *mopts, char *remopts)
132
{
133
	mntfs *mf;
134
135
#ifdef DEBUG
136
	dlog("Locating mntfs reference to %s", mp);
137
#endif /* DEBUG */
138
	ITER(mf, mntfs, &mfhead) {
139
		if (STREQ(mf->mf_mount, mp)) {
140
			/*
141
			 * Handle cases where error ops are involved
142
			 */
143
			if (ops == &efs_ops) {
144
				/*
145
				 * If the existing ops are not efs_ops
146
				 * then continue...
147
				 */
148
				if (mf->mf_ops != &efs_ops)
149
					continue;
150
			} else /* ops != &efs_ops */ {
151
				/*
152
				 * If the existing ops are efs_ops
153
				 * then continue...
154
				 */
155
				if (mf->mf_ops == &efs_ops)
156
					continue;
157
			}
158
159
			if ((mf->mf_flags & MFF_RESTART) && amd_state == Run) {
160
				/*
161
				 * Restart a previously mounted filesystem.
162
				 */
163
				mntfs *mf2 = alloc_mntfs(&ifs_ops, mo, mp, info, auto_opts, mopts, remopts);
164
#ifdef DEBUG
165
				dlog("Restarting filesystem %s", mf->mf_mount);
166
#endif /* DEBUG */
167
				/*
168
				 * Remember who we are restarting
169
				 */
170
				mf2->mf_private = dup_mntfs(mf);
171
				mf2->mf_prfree = free_mntfs;
172
				return mf2;
173
			}
174
			mf->mf_fo = mo;
175
			if (!(mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING))) {
176
				fserver *fs;
177
				mf->mf_flags &= ~MFF_ERROR;
178
				mf->mf_error = -1;
179
				mf->mf_auto = strealloc(mf->mf_auto, auto_opts);
180
				mf->mf_mopts = strealloc(mf->mf_mopts, mopts);
181
				mf->mf_remopts = strealloc(mf->mf_remopts, remopts);
182
				mf->mf_info = strealloc(mf->mf_info, info);
183
				if (mf->mf_private && mf->mf_prfree) {
184
					(*mf->mf_prfree)(mf->mf_private);
185
					mf->mf_private = 0;
186
				}
187
				fs = ops->ffserver ? (*ops->ffserver)(mf) : (fserver *) 0;
188
				if (mf->mf_server)
189
					free_srvr(mf->mf_server);
190
				mf->mf_server = fs;
191
			}
192
			return dup_mntfs(mf);
193
		}
194
	}
195
196
	return alloc_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
197
}
198
199
mntfs *
200
new_mntfs()
201
{
202
	return alloc_mntfs(&efs_ops, (am_opts *) 0, "//nil//", ".", "", "", "");
203
}
204
205
static void
206
uninit_mntfs(mntfs *mf, int rmd)
207
{
208
	free(mf->mf_auto);
209
	free(mf->mf_mopts);
210
	free(mf->mf_remopts);
211
	free(mf->mf_info);
212
	if (mf->mf_private && mf->mf_prfree)
213
		(*mf->mf_prfree)(mf->mf_private);
214
	/*
215
	 * Clean up any directories that were made
216
	 */
217
	if (rmd && (mf->mf_flags & MFF_MKMNT))
218
		rmdirs(mf->mf_mount);
219
	free(mf->mf_mount);
220
221
	/*
222
	 * Clean up the file server
223
	 */
224
	if (mf->mf_server)
225
		free_srvr(mf->mf_server);
226
227
	/*
228
	 * Don't do a callback on this mount
229
	 */
230
	if (mf->mf_cid) {
231
		untimeout(mf->mf_cid);
232
		mf->mf_cid = 0;
233
	}
234
}
235
236
static void
237
discard_mntfs(void *arg)
238
{
239
	mntfs *mf = arg;
240
241
	rem_que(&mf->mf_q);
242
	/*
243
	 * Free memory
244
	 */
245
	uninit_mntfs(mf, TRUE);
246
	free(mf);
247
248
	--mntfs_allocated;
249
}
250
251
void
252
flush_mntfs(void)
253
{
254
	mntfs *mf;
255
256
	mf = FIRST(mntfs, &mfhead);
257
	while (mf != HEAD(mntfs, &mfhead)) {
258
		mntfs *mf2 = mf;
259
		mf = NEXT(mntfs, mf);
260
		if (mf2->mf_refc == 0 && mf2->mf_cid)
261
			discard_mntfs(mf2);
262
	}
263
}
264
265
void
266
free_mntfs(void *arg)
267
{
268
	mntfs *mf = arg;
269
270
	if (--mf->mf_refc == 0) {
271
		if (mf->mf_flags & MFF_MOUNTED) {
272
			int quoted;
273
			mf->mf_flags &= ~MFF_MOUNTED;
274
275
			/*
276
			 * Record for posterity
277
			 */
278
			quoted = strchr(mf->mf_info, ' ') != 0;	/* cheap */
279
			plog(XLOG_INFO, "%s%s%s %sed fstype %s from %s",
280
				quoted ? "\"" : "",
281
				mf->mf_info,
282
				quoted ? "\"" : "",
283
				mf->mf_error ? "discard" : "unmount",
284
				mf->mf_ops->fs_type, mf->mf_mount);
285
		}
286
287
		if (mf->mf_ops->fs_flags & FS_DISCARD) {
288
#ifdef DEBUG
289
			dlog("Immediately discarding mntfs for %s", mf->mf_mount);
290
#endif /* DEBUG */
291
			discard_mntfs(mf);
292
		} else {
293
#ifdef DEBUG
294
			if (mf->mf_flags & MFF_RESTART) {
295
				dlog("Discarding remount hook for %s", mf->mf_mount);
296
			} else {
297
				dlog("Discarding last mntfs reference to %s fstype %s",
298
					mf->mf_mount, mf->mf_ops->fs_type);
299
			}
300
			if (mf->mf_flags & (MFF_MOUNTED|MFF_MOUNTING|MFF_UNMOUNTING))
301
				dlog("mntfs reference for %s still active", mf->mf_mount);
302
#endif /* DEBUG */
303
			mf->mf_cid = timeout(ALLOWED_MOUNT_TIME,
304
			    discard_mntfs, mf);
305
		}
306
	}
307
}
308
309
mntfs *
310
realloc_mntfs(mntfs *mf, am_ops *ops, am_opts *mo, char *mp,
311
    char *info, char *auto_opts, char *mopts, char *remopts)
312
{
313
	mntfs *mf2;
314
315
	if (mf->mf_refc == 1 && mf->mf_ops == &ifs_ops && STREQ(mf->mf_mount, mp)) {
316
		/*
317
		 * If we are inheriting then just return
318
		 * the same node...
319
		 */
320
		return mf;
321
	}
322
323
	/*
324
	 * Re-use the existing mntfs if it is mounted.
325
	 * This traps a race in nfsx.
326
	 */
327
	if (mf->mf_ops != &efs_ops &&
328
			(mf->mf_flags & MFF_MOUNTED) &&
329
			!FSRV_ISDOWN(mf->mf_server)) {
330
		mf->mf_fo = mo;
331
		return mf;
332
	}
333
334
	mf2 = find_mntfs(ops, mo, mp, info, auto_opts, mopts, remopts);
335
	free_mntfs(mf);
336
	return mf2;
337
}