os161-1.99
 All Data Structures
vnode.c
00001 /*
00002  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 /*
00031  * Basic vnode support functions.
00032  */
00033 #include <types.h>
00034 #include <kern/errno.h>
00035 #include <lib.h>
00036 #include <synch.h>
00037 #include <vfs.h>
00038 #include <vnode.h>
00039 
00040 /*
00041  * Initialize an abstract vnode.
00042  * Invoked by VOP_INIT.
00043  */
00044 int
00045 vnode_init(struct vnode *vn, const struct vnode_ops *ops,
00046            struct fs *fs, void *fsdata)
00047 {
00048         KASSERT(vn!=NULL);
00049         KASSERT(ops!=NULL);
00050 
00051         vn->vn_ops = ops;
00052         vn->vn_refcount = 1;
00053         vn->vn_opencount = 0;
00054         vn->vn_fs = fs;
00055         vn->vn_data = fsdata;
00056         return 0;
00057 }
00058 
00059 /*
00060  * Destroy an abstract vnode.
00061  * Invoked by VOP_CLEANUP.
00062  */
00063 void
00064 vnode_cleanup(struct vnode *vn)
00065 {
00066         KASSERT(vn->vn_refcount==1);
00067         KASSERT(vn->vn_opencount==0);
00068 
00069         vn->vn_ops = NULL;
00070         vn->vn_refcount = 0;
00071         vn->vn_opencount = 0;
00072         vn->vn_fs = NULL;
00073         vn->vn_data = NULL;
00074 }
00075 
00076 
00077 /*
00078  * Increment refcount.
00079  * Called by VOP_INCREF.
00080  */
00081 void
00082 vnode_incref(struct vnode *vn)
00083 {
00084         KASSERT(vn != NULL);
00085 
00086         vfs_biglock_acquire();
00087 
00088         vn->vn_refcount++;
00089 
00090         vfs_biglock_release();
00091 }
00092 
00093 /*
00094  * Decrement refcount.
00095  * Called by VOP_DECREF.
00096  * Calls VOP_RECLAIM if the refcount hits zero.
00097  */
00098 void
00099 vnode_decref(struct vnode *vn)
00100 {
00101         int result;
00102 
00103         KASSERT(vn != NULL);
00104 
00105         vfs_biglock_acquire();
00106 
00107         KASSERT(vn->vn_refcount>0);
00108         if (vn->vn_refcount>1) {
00109                 vn->vn_refcount--;
00110         }
00111         else {
00112                 result = VOP_RECLAIM(vn);
00113                 if (result != 0 && result != EBUSY) {
00114                         // XXX: lame.
00115                         kprintf("vfs: Warning: VOP_RECLAIM: %s\n",
00116                                 strerror(result));
00117                 }
00118         }
00119 
00120         vfs_biglock_release();
00121 }
00122 
00123 /*
00124  * Increment the open count.
00125  * Called by VOP_INCOPEN.
00126  */
00127 void
00128 vnode_incopen(struct vnode *vn)
00129 {
00130         KASSERT(vn != NULL);
00131 
00132         vfs_biglock_acquire();
00133         vn->vn_opencount++;
00134         vfs_biglock_release();
00135 }
00136 
00137 /*
00138  * Decrement the open count.
00139  * Called by VOP_DECOPEN.
00140  */
00141 void
00142 vnode_decopen(struct vnode *vn)
00143 {
00144         int result;
00145 
00146         KASSERT(vn != NULL);
00147 
00148         vfs_biglock_acquire();
00149 
00150         KASSERT(vn->vn_opencount>0);
00151         vn->vn_opencount--;
00152 
00153         if (vn->vn_opencount > 0) {
00154                 vfs_biglock_release();
00155                 return;
00156         }
00157 
00158         result = VOP_CLOSE(vn);
00159         if (result) {
00160                 // XXX: also lame.
00161                 // The FS should do what it can to make sure this code
00162                 // doesn't get reached...
00163                 kprintf("vfs: Warning: VOP_CLOSE: %s\n", strerror(result));
00164         }
00165 
00166         vfs_biglock_release();
00167 }
00168 
00169 /*
00170  * Check for various things being valid.
00171  * Called before all VOP_* calls.
00172  */
00173 void
00174 vnode_check(struct vnode *v, const char *opstr)
00175 {
00176         vfs_biglock_acquire();
00177 
00178         if (v == NULL) {
00179                 panic("vnode_check: vop_%s: null vnode\n", opstr);
00180         }
00181         if (v == (void *)0xdeadbeef) {
00182                 panic("vnode_check: vop_%s: deadbeef vnode\n", opstr);
00183         }
00184 
00185         if (v->vn_ops == NULL) {
00186                 panic("vnode_check: vop_%s: null ops pointer\n", opstr);
00187         }
00188         if (v->vn_ops == (void *)0xdeadbeef) {
00189                 panic("vnode_check: vop_%s: deadbeef ops pointer\n", opstr);
00190         }
00191 
00192         if (v->vn_ops->vop_magic != VOP_MAGIC) {
00193                 panic("vnode_check: vop_%s: ops with bad magic number %lx\n", 
00194                       opstr, v->vn_ops->vop_magic);
00195         }
00196 
00197         // Device vnodes have null fs pointers.
00198         //if (v->vn_fs == NULL) {
00199         //      panic("vnode_check: vop_%s: null fs pointer\n", opstr);
00200         //}
00201         if (v->vn_fs == (void *)0xdeadbeef) {
00202                 panic("vnode_check: vop_%s: deadbeef fs pointer\n", opstr);
00203         }
00204 
00205         if (v->vn_refcount < 0) {
00206                 panic("vnode_check: vop_%s: negative refcount %d\n", opstr,
00207                       v->vn_refcount);
00208         }
00209         else if (v->vn_refcount == 0 && strcmp(opstr, "reclaim")) {
00210                 panic("vnode_check: vop_%s: zero refcount\n", opstr);
00211         }
00212         else if (v->vn_refcount > 0x100000) {
00213                 kprintf("vnode_check: vop_%s: warning: large refcount %d\n", 
00214                         opstr, v->vn_refcount);
00215         }
00216 
00217         if (v->vn_opencount < 0) {
00218                 panic("vnode_check: vop_%s: negative opencount %d\n", opstr,
00219                       v->vn_opencount);
00220         }
00221         else if (v->vn_opencount > 0x100000) {
00222                 kprintf("vnode_check: vop_%s: warning: large opencount %d\n", 
00223                         opstr, v->vn_opencount);
00224         }
00225 
00226         vfs_biglock_release();
00227 }
 All Data Structures