/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- vnode_init
- vnode_cleanup
- vnode_incref
- vnode_decref
- vnode_incopen
- vnode_decopen
- vnode_check
1 /*
2 * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3 * The President and Fellows of Harvard College.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30 /*
31 * Basic vnode support functions.
32 */
33 #include <types.h>
34 #include <kern/errno.h>
35 #include <lib.h>
36 #include <synch.h>
37 #include <vfs.h>
38 #include <vnode.h>
39
40 /*
41 * Initialize an abstract vnode.
42 * Invoked by VOP_INIT.
43 */
44 int
45 vnode_init(struct vnode *vn, const struct vnode_ops *ops,
46 struct fs *fs, void *fsdata)
47 {
48 KASSERT(vn!=NULL);
49 KASSERT(ops!=NULL);
50
51 vn->vn_ops = ops;
52 vn->vn_refcount = 1;
53 vn->vn_opencount = 0;
54 vn->vn_fs = fs;
55 vn->vn_data = fsdata;
56 return 0;
57 }
58
59 /*
60 * Destroy an abstract vnode.
61 * Invoked by VOP_CLEANUP.
62 */
63 void
64 vnode_cleanup(struct vnode *vn)
65 {
66 KASSERT(vn->vn_refcount==1);
67 KASSERT(vn->vn_opencount==0);
68
69 vn->vn_ops = NULL;
70 vn->vn_refcount = 0;
71 vn->vn_opencount = 0;
72 vn->vn_fs = NULL;
73 vn->vn_data = NULL;
74 }
75
76
77 /*
78 * Increment refcount.
79 * Called by VOP_INCREF.
80 */
81 void
82 vnode_incref(struct vnode *vn)
83 {
84 KASSERT(vn != NULL);
85
86 vfs_biglock_acquire();
87
88 vn->vn_refcount++;
89
90 vfs_biglock_release();
91 }
92
93 /*
94 * Decrement refcount.
95 * Called by VOP_DECREF.
96 * Calls VOP_RECLAIM if the refcount hits zero.
97 */
98 void
99 vnode_decref(struct vnode *vn)
100 {
101 int result;
102
103 KASSERT(vn != NULL);
104
105 vfs_biglock_acquire();
106
107 KASSERT(vn->vn_refcount>0);
108 if (vn->vn_refcount>1) {
109 vn->vn_refcount--;
110 }
111 else {
112 result = VOP_RECLAIM(vn);
113 if (result != 0 && result != EBUSY) {
114 // XXX: lame.
115 kprintf("vfs: Warning: VOP_RECLAIM: %s\n",
116 strerror(result));
117 }
118 }
119
120 vfs_biglock_release();
121 }
122
123 /*
124 * Increment the open count.
125 * Called by VOP_INCOPEN.
126 */
127 void
128 vnode_incopen(struct vnode *vn)
129 {
130 KASSERT(vn != NULL);
131
132 vfs_biglock_acquire();
133 vn->vn_opencount++;
134 vfs_biglock_release();
135 }
136
137 /*
138 * Decrement the open count.
139 * Called by VOP_DECOPEN.
140 */
141 void
142 vnode_decopen(struct vnode *vn)
143 {
144 int result;
145
146 KASSERT(vn != NULL);
147
148 vfs_biglock_acquire();
149
150 KASSERT(vn->vn_opencount>0);
151 vn->vn_opencount--;
152
153 if (vn->vn_opencount > 0) {
154 vfs_biglock_release();
155 return;
156 }
157
158 result = VOP_CLOSE(vn);
159 if (result) {
160 // XXX: also lame.
161 // The FS should do what it can to make sure this code
162 // doesn't get reached...
163 kprintf("vfs: Warning: VOP_CLOSE: %s\n", strerror(result));
164 }
165
166 vfs_biglock_release();
167 }
168
169 /*
170 * Check for various things being valid.
171 * Called before all VOP_* calls.
172 */
173 void
174 vnode_check(struct vnode *v, const char *opstr)
175 {
176 vfs_biglock_acquire();
177
178 if (v == NULL) {
179 panic("vnode_check: vop_%s: null vnode\n", opstr);
180 }
181 if (v == (void *)0xdeadbeef) {
182 panic("vnode_check: vop_%s: deadbeef vnode\n", opstr);
183 }
184
185 if (v->vn_ops == NULL) {
186 panic("vnode_check: vop_%s: null ops pointer\n", opstr);
187 }
188 if (v->vn_ops == (void *)0xdeadbeef) {
189 panic("vnode_check: vop_%s: deadbeef ops pointer\n", opstr);
190 }
191
192 if (v->vn_ops->vop_magic != VOP_MAGIC) {
193 panic("vnode_check: vop_%s: ops with bad magic number %lx\n",
194 opstr, v->vn_ops->vop_magic);
195 }
196
197 // Device vnodes have null fs pointers.
198 //if (v->vn_fs == NULL) {
199 // panic("vnode_check: vop_%s: null fs pointer\n", opstr);
200 //}
201 if (v->vn_fs == (void *)0xdeadbeef) {
202 panic("vnode_check: vop_%s: deadbeef fs pointer\n", opstr);
203 }
204
205 if (v->vn_refcount < 0) {
206 panic("vnode_check: vop_%s: negative refcount %d\n", opstr,
207 v->vn_refcount);
208 }
209 else if (v->vn_refcount == 0 && strcmp(opstr, "reclaim")) {
210 panic("vnode_check: vop_%s: zero refcount\n", opstr);
211 }
212 else if (v->vn_refcount > 0x100000) {
213 kprintf("vnode_check: vop_%s: warning: large refcount %d\n",
214 opstr, v->vn_refcount);
215 }
216
217 if (v->vn_opencount < 0) {
218 panic("vnode_check: vop_%s: negative opencount %d\n", opstr,
219 v->vn_opencount);
220 }
221 else if (v->vn_opencount > 0x100000) {
222 kprintf("vnode_check: vop_%s: warning: large opencount %d\n",
223 opstr, v->vn_opencount);
224 }
225
226 vfs_biglock_release();
227 }