1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 /*
31  * University Copyright- Copyright (c) 1982, 1986, 1988
32  * The Regents of the University of California
33  * All Rights Reserved
34  *
35  * University Acknowledgment- Portions of this document are derived from
36  * software developed by the University of California, Berkeley, and its
37  * contributors.
38  */
39 
40 
41 #pragma ident	"%Z%%M%	%I%	%E% SMI"
42 
43 #include <sys/types.h>
44 #include <sys/t_lock.h>
45 #include <sys/param.h>
46 #include <sys/buf.h>
47 #include <sys/cmn_err.h>
48 #include <sys/debug.h>
49 #include <sys/errno.h>
50 #include <sys/vfs.h>
51 #include <sys/swap.h>
52 #include <sys/vnode.h>
53 #include <sys/cred.h>
54 #include <sys/fs/snode.h>
55 #include <sys/thread.h>
56 
57 #include <fs/fs_subr.h>
58 
59 /*
60  * This is the loadable module wrapper.
61  */
62 #include <sys/modctl.h>
63 
64 static vfsdef_t vfw = {
65 	VFSDEF_VERSION,
66 	"specfs",
67 	specinit,
68 	0,
69 	NULL
70 };
71 
72 extern struct mod_ops mod_fsops;
73 
74 /*
75  * Module linkage information for the kernel.
76  */
77 static struct modlfs modlfs = {
78 	&mod_fsops, "filesystem for specfs", &vfw
79 };
80 
81 static struct modlinkage modlinkage = {
82 	MODREV_1, (void *)&modlfs, NULL
83 };
84 
85 int
86 _init(void)
87 {
88 	return (mod_install(&modlinkage));
89 }
90 
91 int
92 _info(struct modinfo *modinfop)
93 {
94 	return (mod_info(&modlinkage, modinfop));
95 }
96 
97 /*
98  * N.B.
99  * No _fini routine. This module cannot be unloaded once loaded.
100  * The NO_UNLOAD_STUB in modstub.s must change if this module ever
101  * is modififed to become unloadable.
102  */
103 
104 kmutex_t spec_syncbusy;		/* initialized in specinit() */
105 
106 /*
107  * Run though all the snodes and force write-back
108  * of all dirty pages on the block devices.
109  */
110 /*ARGSUSED*/
111 int
112 spec_sync(struct vfs *vfsp,
113 	short	flag,
114 	struct cred *cr)
115 {
116 	struct snode *sync_list;
117 	register struct snode **spp, *sp, *spnext;
118 	register struct vnode *vp;
119 
120 	if (mutex_tryenter(&spec_syncbusy) == 0)
121 		return (0);
122 
123 	if (flag & SYNC_ATTR) {
124 		mutex_exit(&spec_syncbusy);
125 		return (0);
126 	}
127 	mutex_enter(&stable_lock);
128 	sync_list = NULL;
129 	/*
130 	 * Find all the snodes that are dirty and add them to the sync_list
131 	 */
132 	for (spp = stable; spp < &stable[STABLESIZE]; spp++) {
133 		for (sp = *spp; sp != NULL; sp = sp->s_next) {
134 			vp = STOV(sp);
135 			/*
136 			 * Don't bother sync'ing a vp if it's
137 			 * part of a virtual swap device.
138 			 */
139 			if (IS_SWAPVP(vp))
140 				continue;
141 
142 			if (vp->v_type == VBLK && vn_has_cached_data(vp)) {
143 				/*
144 				 * Prevent vp from going away before we
145 				 * we get a chance to do a VOP_PUTPAGE
146 				 * via sync_list processing
147 				 */
148 				VN_HOLD(vp);
149 				sp->s_list = sync_list;
150 				sync_list = sp;
151 			}
152 		}
153 	}
154 	mutex_exit(&stable_lock);
155 	/*
156 	 * Now write out all the snodes we marked asynchronously.
157 	 */
158 	for (sp = sync_list; sp != NULL; sp = spnext) {
159 		spnext = sp->s_list;
160 		vp = STOV(sp);
161 		(void) VOP_PUTPAGE(vp, (offset_t)0, (uint_t)0, B_ASYNC, cr);
162 		VN_RELE(vp);		/* Release our hold on vnode */
163 	}
164 	mutex_exit(&spec_syncbusy);
165 	return (0);
166 }
167