1 /* This file contains the routines related to vnodes.
2 * The entry points are:
4 * get_vnode - increase counter and get details of an inode
5 * get_free_vnode - get a pointer to a free vnode obj
6 * find_vnode - find a vnode according to the FS endpoint and the inode num.
7 * dup_vnode - duplicate vnode (i.e. increase counter)
8 * put_vnode - drop vnode (i.e. decrease counter)
16 #include <minix/vfsif.h>
18 /* Is vnode pointer reasonable? */
19 #define SANEVP(v) ((((v) >= &vnode[0] && (v) < &vnode[NR_VNODES])))
21 #define BADVP(v, f, l) printf("%s:%d: bad vp 0x%x\n", f, l, v)
23 /* vp check that returns 0 for use in check_vrefs() */
24 #define CHECKVN(v) if(!SANEVP(v)) { \
25 BADVP(v, __FILE__, __LINE__); \
29 /* vp check that panics */
30 #define ASSERTVP(v) if(!SANEVP(v)) { \
31 BADVP(v, __FILE__, __LINE__); panic("bad vp"); }
33 /*===========================================================================*
35 *===========================================================================*/
36 PUBLIC
struct vnode
*get_free_vnode()
38 /* Find a free vnode slot in the vnode table (it's not actually allocated) */
41 for (vp
= &vnode
[0]; vp
< &vnode
[NR_VNODES
]; ++vp
) {
42 if (vp
->v_ref_count
== 0) {
48 vp
->v_mapinode_nr
= 0;
58 /*===========================================================================*
60 *===========================================================================*/
61 PUBLIC
struct vnode
*find_vnode(int fs_e
, int numb
)
63 /* Find a specified (FS endpoint and inode number) vnode in the
67 for (vp
= &vnode
[0]; vp
< &vnode
[NR_VNODES
]; ++vp
)
68 if (vp
->v_ref_count
> 0 && vp
->v_inode_nr
== numb
&& vp
->v_fs_e
== fs_e
)
75 /*===========================================================================*
77 *===========================================================================*/
78 PUBLIC
void dup_vnode(struct vnode
*vp
)
80 /* dup_vnode() is called to increment the vnode and therefore the
81 * referred inode's counter.
88 /*===========================================================================*
90 *===========================================================================*/
91 PUBLIC
void put_vnode(struct vnode
*vp
)
93 /* Decrease vnode's usage counter and decrease inode's usage counter in the
94 * corresponding FS process. Decreasing the fs_count each time we decrease the
95 * ref count would lead to poor performance. Instead, only decrease fs_count
96 * when the ref count hits zero. However, this could lead to fs_count to wrap.
97 * To prevent this, we drop the counter to 1 when the counter hits 256.
98 * We maintain fs_count as a sanity check to make sure VFS and the FS are in
103 if (vp
->v_ref_count
> 1) {
104 /* Decrease counter */
106 if (vp
->v_fs_count
> 256)
107 vnode_clean_refs(vp
);
112 /* A vnode that's not in use can't be put. */
113 if (vp
->v_ref_count
<= 0) {
114 printf("put_vnode: bad v_ref_count %d\n", vp
->v_ref_count
);
115 panic("put_vnode failed");
118 /* fs_count should indicate that the file is in use. */
119 if (vp
->v_fs_count
<= 0) {
120 printf("put_vnode: bad v_fs_count %d\n", vp
->v_fs_count
);
121 panic("put_vnode failed");
124 /* Tell FS we don't need this inode to be open anymore. */
125 req_putnode(vp
->v_fs_e
, vp
->v_inode_nr
, vp
->v_fs_count
);
127 /* This inode could've been mapped. If so, tell PFS to close it as well. */
128 if(vp
->v_mapfs_e
!= 0 && vp
->v_mapinode_nr
!= vp
->v_inode_nr
&&
129 vp
->v_mapfs_e
!= vp
->v_fs_e
) {
130 req_putnode(vp
->v_mapfs_e
, vp
->v_mapinode_nr
, vp
->v_mapfs_count
);
135 vp
->v_pipe
= NO_PIPE
;
138 vp
->v_mapinode_nr
= 0;
139 vp
->v_mapfs_count
= 0;
143 /*===========================================================================*
145 *===========================================================================*/
146 PUBLIC
void vnode_clean_refs(struct vnode
*vp
)
148 /* Tell the underlying FS to drop all reference but one. */
150 if (vp
== NIL_VNODE
) return;
151 if (vp
->v_fs_count
<= 1) return; /* Nothing to do */
153 /* Drop all references except one */
154 req_putnode(vp
->v_fs_e
, vp
->v_inode_nr
, vp
->v_fs_count
- 1);
159 #define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; }
162 /*===========================================================================*
164 *===========================================================================*/
165 PUBLIC
int check_vrefs()
168 int ispipe_flag
, ispipe_mode
;
174 /* Clear v_ref_check */
175 for (vp
= &vnode
[0]; vp
< &vnode
[NR_VNODES
]; ++vp
)
178 /* Count reference for processes */
179 for (rfp
=&fproc
[0]; rfp
< &fproc
[NR_PROCS
]; rfp
++) {
180 if (rfp
->fp_pid
== PID_FREE
)
182 if(rfp
->fp_rd
) REFVP(rfp
->fp_rd
);
183 if(rfp
->fp_wd
) REFVP(rfp
->fp_wd
);
186 /* Count references from filedescriptors */
187 for (f
= &filp
[0]; f
< &filp
[NR_FILPS
]; f
++)
189 if (f
->filp_count
== 0)
194 /* Count references to mount points */
195 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; ++vmp
)
197 if (vmp
->m_dev
== NO_DEV
)
199 REFVP(vmp
->m_root_node
);
200 if(vmp
->m_mounted_on
)
201 REFVP(vmp
->m_mounted_on
);
204 /* Check references */
206 for (vp
= &vnode
[0]; vp
< &vnode
[NR_VNODES
]; ++vp
)
208 if (vp
->v_ref_count
!= vp
->v_ref_check
)
211 "Bad reference count for inode %d on device 0x%x: found %d, listed %d\n",
212 vp
->v_inode_nr
, vp
->v_dev
, vp
->v_ref_check
,
214 printf("last marked at %s, %d\n",
215 vp
->v_file
, vp
->v_line
);
219 /* Also check v_pipe */
220 if (vp
->v_ref_count
!= 0)
222 ispipe_flag
= (vp
->v_pipe
== I_PIPE
);
223 ispipe_mode
= ((vp
->v_mode
& I_TYPE
) == I_NAMED_PIPE
);
224 if (ispipe_flag
!= ispipe_mode
)
227 "Bad v_pipe for inode %d on device 0x%x: found %d, mode 0%o\n",
228 vp
->v_inode_nr
, vp
->v_dev
, vp
->v_pipe
,
230 printf("last marked at %s, %d\n",
231 vp
->v_file
, vp
->v_line
);