[BACK]Return to vfs_vnode.c CVS log [TXT][DIR] Up to [local] / prex-old / usr / server / fs / vfs

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