root/kern/vfs/vnode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vnode_init
  2. vnode_cleanup
  3. vnode_incref
  4. vnode_decref
  5. vnode_incopen
  6. vnode_decopen
  7. 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 }

/* [<][>][^][v][top][bottom][index][help] */