Annotation of prex-old/usr/server/fs/vfs/vfs_vnode.c, Revision 1.1
1.1 ! nbrk 1: /*
! 2: * Copyright (c) 2005-2007, Kohsuke Ohtani
! 3: * All rights reserved.
! 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 author nor the names of any co-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 AUTHOR 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 AUTHOR 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: * vnode.c - vnode service
! 32: */
! 33:
! 34: #include <prex/prex.h>
! 35: #include <sys/list.h>
! 36: #include <sys/vnode.h>
! 37: #include <sys/mount.h>
! 38:
! 39: #include <limits.h>
! 40: #include <unistd.h>
! 41: #include <string.h>
! 42: #include <stdlib.h>
! 43: #include <stdio.h>
! 44: #include <errno.h>
! 45:
! 46: #include "vfs.h"
! 47:
! 48: /*
! 49: * Memo:
! 50: *
! 51: * Function Ref count Lock
! 52: * ---------- --------- ----------
! 53: * vn_lock * Lock
! 54: * vn_unlock * Unlock
! 55: * vget 1 Lock
! 56: * vput -1 Unlock
! 57: * vref +1 *
! 58: * vrele -1 *
! 59: */
! 60:
! 61: #define VNODE_BUCKETS 32 /* size of vnode hash table */
! 62:
! 63: /*
! 64: * vnode table.
! 65: * All active (opened) vnodes are stored on this hash table.
! 66: * They can be accessed by its path name.
! 67: */
! 68: static struct list vnode_table[VNODE_BUCKETS];
! 69:
! 70: /*
! 71: * Global lock to access all vnodes and vnode table.
! 72: * If a vnode is already locked, there is no need to
! 73: * lock this global lock to access internal data.
! 74: */
! 75: #if CONFIG_FS_THREADS > 1
! 76: static mutex_t vnode_lock = MUTEX_INITIALIZER;
! 77: #define VNODE_LOCK() mutex_lock(&vnode_lock)
! 78: #define VNODE_UNLOCK() mutex_unlock(&vnode_lock)
! 79: #else
! 80: #define VNODE_LOCK()
! 81: #define VNODE_UNLOCK()
! 82: #endif
! 83:
! 84:
! 85: /*
! 86: * Get the hash value from path name and mount point.
! 87: */
! 88: static u_int
! 89: vn_hash(mount_t mp, char *path)
! 90: {
! 91: u_int val = 0;
! 92:
! 93: if (path) {
! 94: while (*path)
! 95: val = ((val << 5) + val) + *path++;
! 96: }
! 97: return (val ^ (u_int) mp) & (VNODE_BUCKETS - 1);
! 98: }
! 99:
! 100: /*
! 101: * Returns locked vnode for specified mount point and path.
! 102: */
! 103: vnode_t
! 104: vn_lookup(mount_t mp, char *path)
! 105: {
! 106: list_t head, n;
! 107: vnode_t vp;
! 108:
! 109: VNODE_LOCK();
! 110: head = &vnode_table[vn_hash(mp, path)];
! 111: for (n = list_first(head); n != head; n = list_next(n)) {
! 112: vp = list_entry(n, struct vnode, v_link);
! 113: if (vp->v_mount == mp &&
! 114: !strncmp(vp->v_path, path, PATH_MAX)) {
! 115: mutex_lock(&vp->v_lock);
! 116: vp->v_nrlocks++;
! 117: VNODE_UNLOCK();
! 118: return vp;
! 119: }
! 120: }
! 121: VNODE_UNLOCK();
! 122: return NULL; /* not found */
! 123: }
! 124:
! 125: /*
! 126: * Lock vnode
! 127: */
! 128: void
! 129: vn_lock(vnode_t vp)
! 130: {
! 131: ASSERT(vp);
! 132:
! 133: VNODE_LOCK();
! 134: vn_printf("vn_lock: %s\n", vp->v_path);
! 135: mutex_lock(&vp->v_lock);
! 136: vp->v_nrlocks++;
! 137: VNODE_UNLOCK();
! 138: }
! 139:
! 140: /*
! 141: * Unlock vnode
! 142: */
! 143: void
! 144: vn_unlock(vnode_t vp)
! 145: {
! 146: ASSERT(vp);
! 147: ASSERT(vp->v_nrlocks > 0);
! 148:
! 149: VNODE_LOCK();
! 150: vn_printf("vn_unlock: %s\n", vp->v_path);
! 151: vp->v_nrlocks--;
! 152: mutex_unlock(&vp->v_lock);
! 153: VNODE_UNLOCK();
! 154: }
! 155:
! 156: /*
! 157: * Allocate new vnode for specified path.
! 158: * Increment its reference count and lock it.
! 159: */
! 160: vnode_t
! 161: vget(mount_t mp, char *path)
! 162: {
! 163: vnode_t vp;
! 164: int err;
! 165:
! 166: vn_printf("vget: %s\n", path);
! 167:
! 168: if (!(vp = malloc(sizeof(struct vnode))))
! 169: return NULL;
! 170: memset(vp, 0, sizeof(struct vnode));
! 171:
! 172: if (!(vp->v_path = malloc(strlen(path) + 1))) {
! 173: free(vp);
! 174: return NULL;
! 175: }
! 176: vp->v_mount = mp;
! 177: vp->v_refcount = 1;
! 178: vp->v_op = mp->m_op->vnops;
! 179: strcpy(vp->v_path, path);
! 180: mutex_init(&vp->v_lock);
! 181: vp->v_nrlocks = 0;
! 182:
! 183: /*
! 184: * Request to allocate fs specific data for vnode.
! 185: */
! 186: if ((err = VFS_VGET(mp, vp)) != 0) {
! 187: mutex_destroy(&vp->v_lock);
! 188: free(vp->v_path);
! 189: free(vp);
! 190: return NULL;
! 191: }
! 192: vfs_busy(vp->v_mount);
! 193: mutex_lock(&vp->v_lock);
! 194: vp->v_nrlocks++;
! 195:
! 196: VNODE_LOCK();
! 197: list_insert(&vnode_table[vn_hash(mp, path)], &vp->v_link);
! 198: VNODE_UNLOCK();
! 199: return vp;
! 200: }
! 201:
! 202: /*
! 203: * Unlock vnode and decrement its reference count.
! 204: */
! 205: void
! 206: vput(vnode_t vp)
! 207: {
! 208: ASSERT(vp);
! 209: ASSERT(vp->v_nrlocks > 0);
! 210: ASSERT(vp->v_refcount > 0);
! 211: vn_printf("vput: ref=%d %s\n", vp->v_refcount, vp->v_path);
! 212:
! 213: vp->v_refcount--;
! 214: if (vp->v_refcount > 0) {
! 215: vn_unlock(vp);
! 216: return;
! 217: }
! 218: VNODE_LOCK();
! 219: list_remove(&vp->v_link);
! 220: VNODE_UNLOCK();
! 221:
! 222: /*
! 223: * Deallocate fs specific vnode data
! 224: */
! 225: VOP_INACTIVE(vp);
! 226: vfs_unbusy(vp->v_mount);
! 227: vp->v_nrlocks--;
! 228: ASSERT(vp->v_nrlocks == 0);
! 229: mutex_unlock(&vp->v_lock);
! 230: mutex_destroy(&vp->v_lock);
! 231: free(vp->v_path);
! 232: free(vp);
! 233: }
! 234:
! 235: /*
! 236: * Increment the reference count on an active vnode.
! 237: */
! 238: void
! 239: vref(vnode_t vp)
! 240: {
! 241: ASSERT(vp);
! 242: ASSERT(vp->v_refcount > 0); /* Need vget */
! 243:
! 244: VNODE_LOCK();
! 245: vn_printf("vref: ref=%d %s\n", vp->v_refcount, vp->v_path);
! 246: vp->v_refcount++;
! 247: VNODE_UNLOCK();
! 248: }
! 249:
! 250: /*
! 251: * Decrement the reference count of unlocked vnode.
! 252: * Any code in the system which is using vnode should call vrele()
! 253: * when it is finished with the vnode.
! 254: * If count drops to zero, call inactive routine and return to freelist.
! 255: */
! 256: void
! 257: vrele(vnode_t vp)
! 258: {
! 259: ASSERT(vp);
! 260: ASSERT(vp->v_nrlocks == 0);
! 261: ASSERT(vp->v_refcount > 0);
! 262:
! 263: VNODE_LOCK();
! 264: vn_printf("vrele: ref=%d %s\n", vp->v_refcount, vp->v_path);
! 265: vp->v_refcount--;
! 266: if (vp->v_refcount > 0) {
! 267: VNODE_UNLOCK();
! 268: return;
! 269: }
! 270: list_remove(&vp->v_link);
! 271: VNODE_UNLOCK();
! 272:
! 273: /*
! 274: * Deallocate fs specific vnode data
! 275: */
! 276: VOP_INACTIVE(vp);
! 277: vfs_unbusy(vp->v_mount);
! 278: mutex_destroy(&vp->v_lock);
! 279: free(vp->v_path);
! 280: free(vp);
! 281: }
! 282:
! 283: /*
! 284: * vgone() is called when unlocked vnode is no longer valid.
! 285: */
! 286: void
! 287: vgone(vnode_t vp)
! 288: {
! 289: ASSERT(vp->v_nrlocks == 0);
! 290:
! 291: VNODE_LOCK();
! 292: vn_printf("vgone: %s\n", vp->v_path);
! 293: list_remove(&vp->v_link);
! 294: vfs_unbusy(vp->v_mount);
! 295: mutex_destroy(&vp->v_lock);
! 296: free(vp->v_path);
! 297: free(vp);
! 298: VNODE_UNLOCK();
! 299: }
! 300:
! 301: /*
! 302: * Return reference count.
! 303: */
! 304: int
! 305: vcount(vnode_t vp)
! 306: {
! 307: int count;
! 308:
! 309: vn_lock(vp);
! 310: count = vp->v_refcount;
! 311: vn_unlock(vp);
! 312: return count;
! 313: }
! 314:
! 315: /*
! 316: * Remove all vnode in the vnode table for unmount.
! 317: */
! 318: void
! 319: vflush(mount_t mp)
! 320: {
! 321: int i;
! 322: list_t head, n;
! 323: vnode_t vp;
! 324:
! 325: VNODE_LOCK();
! 326: for (i = 0; i < VNODE_BUCKETS; i++) {
! 327: head = &vnode_table[i];
! 328: for (n = list_first(head); n != head; n = list_next(n)) {
! 329: vp = list_entry(n, struct vnode, v_link);
! 330: if (vp->v_mount == mp) {
! 331: /* XXX: */
! 332: }
! 333: }
! 334: }
! 335: VNODE_UNLOCK();
! 336: }
! 337:
! 338: #ifdef DEBUG
! 339: /*
! 340: * Dump all all vnode.
! 341: */
! 342: void
! 343: vnode_dump(void)
! 344: {
! 345: int i;
! 346: list_t head, n;
! 347: vnode_t vp;
! 348: mount_t mp;
! 349: char type[][6] = { "VNON ", "VREG ", "VDIR ", "VBLK ", "VCHR ",
! 350: "VLNK ", "VSOCK", "VFIFO" };
! 351:
! 352: VNODE_LOCK();
! 353: printf("Dump vnode\n");
! 354: printf(" vnode mount type refcnt blkno path\n");
! 355: printf(" -------- -------- ----- ------ -------- ------------------------------\n");
! 356: for (i = 0; i < VNODE_BUCKETS; i++) {
! 357: head = &vnode_table[i];
! 358: for (n = list_first(head); n != head; n = list_next(n)) {
! 359: vp = list_entry(n, struct vnode, v_link);
! 360: mp = vp->v_mount;
! 361: printf(" %08x %08x %s %6d %8d %s%s\n", (u_int)vp,
! 362: (u_int)mp, type[vp->v_type], vp->v_refcount,
! 363: (u_int)vp->v_blkno,
! 364: (strlen(mp->m_path) == 1) ? "\0" : mp->m_path,
! 365: vp->v_path);
! 366: }
! 367: }
! 368: printf("\n");
! 369: VNODE_UNLOCK();
! 370: }
! 371: #endif
! 372:
! 373: int
! 374: vop_nullop(void)
! 375: {
! 376: return 0;
! 377: }
! 378:
! 379: int
! 380: vop_einval(void)
! 381: {
! 382: return EINVAL;
! 383: }
! 384:
! 385: void
! 386: vnode_init(void)
! 387: {
! 388: int i;
! 389:
! 390: for (i = 0; i < VNODE_BUCKETS; i++)
! 391: list_init(&vnode_table[i]);
! 392: }
CVSweb