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

Annotation of prex/usr/server/fs/vfs/vfs_vnode.c, Revision 1.1

1.1     ! nbrk        1: /*
        !             2:  * Copyright (c) 2005-2008, 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 the mount point and path name.
        !            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:  * vn_lock() will increment the reference count of vnode.
        !           103:  */
        !           104: vnode_t
        !           105: vn_lookup(mount_t mp, char *path)
        !           106: {
        !           107:        list_t head, n;
        !           108:        vnode_t vp;
        !           109:
        !           110:        VNODE_LOCK();
        !           111:        head = &vnode_table[vn_hash(mp, path)];
        !           112:        for (n = list_first(head); n != head; n = list_next(n)) {
        !           113:                vp = list_entry(n, struct vnode, v_link);
        !           114:                if (vp->v_mount == mp &&
        !           115:                    !strncmp(vp->v_path, path, PATH_MAX)) {
        !           116:                        vp->v_refcnt++;
        !           117:                        VNODE_UNLOCK();
        !           118:                        mutex_lock(&vp->v_lock);
        !           119:                        vp->v_nrlocks++;
        !           120:                        return vp;
        !           121:                }
        !           122:        }
        !           123:        VNODE_UNLOCK();
        !           124:        return NULL;            /* not found */
        !           125: }
        !           126:
        !           127: /*
        !           128:  * Lock vnode
        !           129:  */
        !           130: void
        !           131: vn_lock(vnode_t vp)
        !           132: {
        !           133:        ASSERT(vp);
        !           134:        ASSERT(vp->v_refcnt > 0);
        !           135:
        !           136:        mutex_lock(&vp->v_lock);
        !           137:        vp->v_nrlocks++;
        !           138:        DPRINTF(VFSDB_VNODE, ("vn_lock:   %s\n", vp->v_path));
        !           139: }
        !           140:
        !           141: /*
        !           142:  * Unlock vnode
        !           143:  */
        !           144: void
        !           145: vn_unlock(vnode_t vp)
        !           146: {
        !           147:        ASSERT(vp);
        !           148:        ASSERT(vp->v_refcnt > 0);
        !           149:        ASSERT(vp->v_nrlocks > 0);
        !           150:
        !           151:        DPRINTF(VFSDB_VNODE, ("vn_unlock: %s\n", vp->v_path));
        !           152:        vp->v_nrlocks--;
        !           153:        mutex_unlock(&vp->v_lock);
        !           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:        DPRINTF(VFSDB_VNODE, ("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_refcnt = 1;
        !           178:        vp->v_op = mp->m_op->vfs_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_refcnt > 0);
        !           211:        DPRINTF(VFSDB_VNODE, ("vput: ref=%d %s\n", vp->v_refcnt,
        !           212:                              vp->v_path));
        !           213:
        !           214:        vp->v_refcnt--;
        !           215:        if (vp->v_refcnt > 0) {
        !           216:                vn_unlock(vp);
        !           217:                return;
        !           218:        }
        !           219:        VNODE_LOCK();
        !           220:        list_remove(&vp->v_link);
        !           221:        VNODE_UNLOCK();
        !           222:
        !           223:        /*
        !           224:         * Deallocate fs specific vnode data
        !           225:         */
        !           226:        VOP_INACTIVE(vp);
        !           227:        vfs_unbusy(vp->v_mount);
        !           228:        vp->v_nrlocks--;
        !           229:        ASSERT(vp->v_nrlocks == 0);
        !           230:        mutex_unlock(&vp->v_lock);
        !           231:        mutex_destroy(&vp->v_lock);
        !           232:        free(vp->v_path);
        !           233:        free(vp);
        !           234: }
        !           235:
        !           236: /*
        !           237:  * Increment the reference count on an active vnode.
        !           238:  */
        !           239: void
        !           240: vref(vnode_t vp)
        !           241: {
        !           242:        ASSERT(vp);
        !           243:        ASSERT(vp->v_refcnt > 0);       /* Need vget */
        !           244:
        !           245:        VNODE_LOCK();
        !           246:        DPRINTF(VFSDB_VNODE, ("vref: ref=%d %s\n", vp->v_refcnt,
        !           247:                              vp->v_path));
        !           248:        vp->v_refcnt++;
        !           249:        VNODE_UNLOCK();
        !           250: }
        !           251:
        !           252: /*
        !           253:  * Decrement the reference count of unlocked vnode.
        !           254:  * Any code in the system which is using vnode should call vrele()
        !           255:  * when it is finished with the vnode.
        !           256:  * If count drops to zero, call inactive routine and return to freelist.
        !           257:  */
        !           258: void
        !           259: vrele(vnode_t vp)
        !           260: {
        !           261:        ASSERT(vp);
        !           262:        ASSERT(vp->v_nrlocks == 0);
        !           263:        ASSERT(vp->v_refcnt > 0);
        !           264:
        !           265:        VNODE_LOCK();
        !           266:        DPRINTF(VFSDB_VNODE, ("vrele: ref=%d %s\n", vp->v_refcnt,
        !           267:                              vp->v_path));
        !           268:        vp->v_refcnt--;
        !           269:        if (vp->v_refcnt > 0) {
        !           270:                VNODE_UNLOCK();
        !           271:                return;
        !           272:        }
        !           273:        list_remove(&vp->v_link);
        !           274:        VNODE_UNLOCK();
        !           275:
        !           276:        /*
        !           277:         * Deallocate fs specific vnode data
        !           278:         */
        !           279:        VOP_INACTIVE(vp);
        !           280:        vfs_unbusy(vp->v_mount);
        !           281:        mutex_destroy(&vp->v_lock);
        !           282:        free(vp->v_path);
        !           283:        free(vp);
        !           284: }
        !           285:
        !           286: /*
        !           287:  * vgone() is called when unlocked vnode is no longer valid.
        !           288:  */
        !           289: void
        !           290: vgone(vnode_t vp)
        !           291: {
        !           292:        ASSERT(vp->v_nrlocks == 0);
        !           293:
        !           294:        VNODE_LOCK();
        !           295:        DPRINTF(VFSDB_VNODE, ("vgone: %s\n", vp->v_path));
        !           296:        list_remove(&vp->v_link);
        !           297:        vfs_unbusy(vp->v_mount);
        !           298:        mutex_destroy(&vp->v_lock);
        !           299:        free(vp->v_path);
        !           300:        free(vp);
        !           301:        VNODE_UNLOCK();
        !           302: }
        !           303:
        !           304: /*
        !           305:  * Return reference count.
        !           306:  */
        !           307: int
        !           308: vcount(vnode_t vp)
        !           309: {
        !           310:        int count;
        !           311:
        !           312:        vn_lock(vp);
        !           313:        count = vp->v_refcnt;
        !           314:        vn_unlock(vp);
        !           315:        return count;
        !           316: }
        !           317:
        !           318: /*
        !           319:  * Remove all vnode in the vnode table for unmount.
        !           320:  */
        !           321: void
        !           322: vflush(mount_t mp)
        !           323: {
        !           324:        int i;
        !           325:        list_t head, n;
        !           326:        vnode_t vp;
        !           327:
        !           328:        VNODE_LOCK();
        !           329:        for (i = 0; i < VNODE_BUCKETS; i++) {
        !           330:                head = &vnode_table[i];
        !           331:                for (n = list_first(head); n != head; n = list_next(n)) {
        !           332:                        vp = list_entry(n, struct vnode, v_link);
        !           333:                        if (vp->v_mount == mp) {
        !           334:                                /* XXX: */
        !           335:                        }
        !           336:                }
        !           337:        }
        !           338:        VNODE_UNLOCK();
        !           339: }
        !           340:
        !           341: int
        !           342: vn_stat(vnode_t vp, struct stat *st)
        !           343: {
        !           344:        mode_t mode;
        !           345:
        !           346:        memset(st, 0, sizeof(struct stat));
        !           347:
        !           348:        st->st_ino = (ino_t)vp;
        !           349:        st->st_size = vp->v_size;
        !           350:        mode = vp->v_mode;
        !           351:        switch (vp->v_type) {
        !           352:        case VREG:
        !           353:                mode |= S_IFREG;
        !           354:                break;
        !           355:        case VDIR:
        !           356:                mode |= S_IFDIR;
        !           357:                break;
        !           358:        case VBLK:
        !           359:                mode |= S_IFBLK;
        !           360:                break;
        !           361:        case VCHR:
        !           362:                mode |= S_IFCHR;
        !           363:                break;
        !           364:        case VLNK:
        !           365:                mode |= S_IFLNK;
        !           366:                break;
        !           367:        case VSOCK:
        !           368:                mode |= S_IFSOCK;
        !           369:                break;
        !           370:        case VFIFO:
        !           371:                mode |= S_IFIFO;
        !           372:                break;
        !           373:        default:
        !           374:                return EBADF;
        !           375:        };
        !           376:        st->st_mode = mode;
        !           377:        st->st_blksize = BSIZE;
        !           378:        st->st_blocks = vp->v_size / S_BLKSIZE;
        !           379:        st->st_uid = 0;
        !           380:        st->st_gid = 0;
        !           381:        if (vp->v_type == VCHR || vp->v_type == VBLK)
        !           382:                st->st_rdev = (dev_t)vp->v_data;
        !           383:
        !           384:        return 0;
        !           385: }
        !           386:
        !           387: #ifdef DEBUG
        !           388: /*
        !           389:  * Dump all all vnode.
        !           390:  */
        !           391: void
        !           392: vnode_dump(void)
        !           393: {
        !           394:        int i;
        !           395:        list_t head, n;
        !           396:        vnode_t vp;
        !           397:        mount_t mp;
        !           398:        char type[][6] = { "VNON ", "VREG ", "VDIR ", "VBLK ", "VCHR ",
        !           399:                           "VLNK ", "VSOCK", "VFIFO" };
        !           400:
        !           401:        VNODE_LOCK();
        !           402:        dprintf("Dump vnode\n");
        !           403:        dprintf(" vnode    mount    type  refcnt blkno    path\n");
        !           404:        dprintf(" -------- -------- ----- ------ -------- ------------------------------\n");
        !           405:
        !           406:        for (i = 0; i < VNODE_BUCKETS; i++) {
        !           407:                head = &vnode_table[i];
        !           408:                for (n = list_first(head); n != head; n = list_next(n)) {
        !           409:                        vp = list_entry(n, struct vnode, v_link);
        !           410:                        mp = vp->v_mount;
        !           411:
        !           412:                        dprintf(" %08x %08x %s %6d %8d %s%s\n", (u_int)vp,
        !           413:                                (u_int)mp, type[vp->v_type], vp->v_refcnt,
        !           414:                                (u_int)vp->v_blkno,
        !           415:                                (strlen(mp->m_path) == 1) ? "\0" : mp->m_path,
        !           416:                                vp->v_path);
        !           417:                }
        !           418:        }
        !           419:        dprintf("\n");
        !           420:        VNODE_UNLOCK();
        !           421: }
        !           422: #endif
        !           423:
        !           424: int
        !           425: vop_nullop(void)
        !           426: {
        !           427:
        !           428:        return 0;
        !           429: }
        !           430:
        !           431: int
        !           432: vop_einval(void)
        !           433: {
        !           434:
        !           435:        return EINVAL;
        !           436: }
        !           437:
        !           438: void
        !           439: vnode_init(void)
        !           440: {
        !           441:        int i;
        !           442:
        !           443:        for (i = 0; i < VNODE_BUCKETS; i++)
        !           444:                list_init(&vnode_table[i]);
        !           445: }

CVSweb