⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vnode.c

📁 微内核软实时操作系统
💻 C
字号:
/* * Copyright (c) 2005-2007, Kohsuke Ohtani * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of any co-contributors  *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <prex/prex.h>#include <sys/list.h>#include <sys/vnode.h>#include <sys/mount.h>#include <limits.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <errno.h>#include "vfs.h"/* * vnode.c - vnode service *//* * Memo: * * Function   Ref count Lock * ---------- --------- ---------- * vn_lock     *        Lock * vn_unlock   *        Unlock * vget        1        Lock * vput       -1        Unlock * vref       +1        * * vrele      -1        * */#define VNODE_BUCKETS 32		/* Size of vnode hash table *//* * vnode table. * All active (opened) vnodes are stored on this hash table. * They can be accessed by its path name. */static struct list vnode_table[VNODE_BUCKETS];/* * Global lock to access all vnodes and vnode table. * If a vnode is already locked, there is no need to * lock this global lock to access internal data. */#if NR_FS_THREADS > 1static mutex_t vnode_lock = MUTEX_INITIALIZER;#define VNODE_LOCK()	mutex_lock(&vnode_lock)#define VNODE_UNLOCK()	mutex_unlock(&vnode_lock)#else#define VNODE_LOCK()#define VNODE_UNLOCK()#endif/* * Get the hash value from path name and mount point. */static u_int vn_hash(mount_t mp, char *path){	u_int val = 0;	if (path) {		while (*path)			val = ((val << 5) + val) + *path++;	}	return (val ^ (u_int) mp) & (VNODE_BUCKETS - 1);}/* * Returns locked vnode for specified mount point and path. */vnode_t vn_lookup(mount_t mp, char *path){	list_t head, n;	vnode_t vp;	VNODE_LOCK();	head = &vnode_table[vn_hash(mp, path)];	for (n = list_first(head); n != head; n = list_next(n)) {		vp = list_entry(n, struct vnode, v_link);		if (vp->v_mount == mp &&		    !strncmp(vp->v_path, path, PATH_MAX)) {			mutex_lock(&vp->v_lock);			VNODE_UNLOCK();			return vp;		}	}	VNODE_UNLOCK();	return NULL;		/* not found */}/* * Lock vnode */void vn_lock(vnode_t vp){	ASSERT(vp);	vn_printf("vn_lock:   %s\n", vp->v_path);	VNODE_LOCK();	mutex_lock(&vp->v_lock);	VNODE_UNLOCK();}/* * Unlock vnode */void vn_unlock(vnode_t vp){	ASSERT(vp);	vn_printf("vn_unlock: %s\n", vp->v_path);	VNODE_LOCK();	mutex_unlock(&vp->v_lock);	VNODE_UNLOCK();}/* * Allocate new vnode for specified path, and increment its reference count * and lock it. */vnode_t vget(mount_t mp, char *path){	vnode_t vp;	int err;	vn_printf("vget: %s\n", path);	if (!(vp = malloc(sizeof(struct vnode))))		return NULL;	memset(vp, 0, sizeof(struct vnode));	if (!(vp->v_path = malloc(strlen(path) + 1))) {		free(vp);		return NULL;	}	vp->v_mount = mp;	vp->v_count = 1;	vp->v_op = mp->m_op->vnops;	strcpy(vp->v_path, path);	mutex_init(&vp->v_lock);	/*	 * Request to allocate fs specific data for vnode.	 */	if ((err = VFS_VGET(mp, vp)) != 0) {		mutex_destroy(&vp->v_lock);		free(vp->v_path);		free(vp);		return NULL;	}	vfs_busy(vp->v_mount);	mutex_lock(&vp->v_lock);	VNODE_LOCK();	list_insert(&vnode_table[vn_hash(mp, path)], &vp->v_link);	VNODE_UNLOCK();	return vp;}/* * Unlock vnode and decrement its reference count. */void vput(vnode_t vp){	vn_printf("vput: count=%d %s\n", vp->v_count, vp->v_path);	vp->v_count--;	if (vp->v_count > 0) {		vn_unlock(vp);		return;	}	VNODE_LOCK();	list_remove(&vp->v_link);	VNODE_UNLOCK();	/*	 * Deallocate fs specific vnode data	 */	VOP_INACTIVE(vp);	vfs_unbusy(vp->v_mount);	mutex_destroy(&vp->v_lock);	free(vp->v_path);	free(vp);}/* * Increment the reference count on an active vnode. */void vref(vnode_t vp){	ASSERT(vp);	ASSERT(vp->v_count > 0);	/* Need vget */	vn_printf("vref: count=%d %s\n", vp->v_count, vp->v_path);	VNODE_LOCK();	vp->v_count++;	VNODE_UNLOCK();}/* * Decrement the reference count of unlocked vnode. */void vrele(vnode_t vp){	ASSERT(vp);	ASSERT(vp->v_count > 0);	vn_printf("vrele: count=%d %s\n", vp->v_count, vp->v_path);	VNODE_LOCK();	vp->v_count--;	if (vp->v_count > 0) {		VNODE_UNLOCK();		return;	}	list_remove(&vp->v_link);	VNODE_UNLOCK();	/*	 * Deallocate fs specific vnode data	 */	VOP_INACTIVE(vp);	vfs_unbusy(vp->v_mount);	mutex_destroy(&vp->v_lock);	free(vp->v_path);	free(vp);}/* * vgone() is called when vnode is no longer valid. */void vgone(vnode_t vp){	vn_printf("vgone: %s\n", vp->v_path);	VNODE_LOCK();	list_remove(&vp->v_link);	VNODE_UNLOCK();	vfs_unbusy(vp->v_mount);	mutex_destroy(&vp->v_lock);	free(vp->v_path);	free(vp);}/* * Return reference count. */int vcount(vnode_t vp){	int count;	vn_lock(vp);	count = vp->v_count;	vn_unlock(vp);	return count;}/* * Remove all vnode in the vnode table for unmount. */void vflush(mount_t mp){	int i;	list_t head, n;	vnode_t vp;	VNODE_LOCK();	for (i = 0; i < VNODE_BUCKETS; i++) {		head = &vnode_table[i];		for (n = list_first(head); n != head; n = list_next(n)) {			vp = list_entry(n, struct vnode, v_link);			if (vp->v_mount == mp) {				/* XXX: */			}		}	}	VNODE_UNLOCK();}#ifdef DEBUG/* * Dump all all vnode. */void vnode_dump(void){	int i;	list_t head, n;	vnode_t vp;	mount_t mp;	char type[][6] = { "VNON ", "VREG ", "VDIR ", "VBLK ", "VCHR ", 			   "VLNK ", "VSOCK", "VFIFO" };	VNODE_LOCK();	printf("Dump vnode\n");	printf(" vnode    mount    type  refcnt blkno    path\n");	printf(" -------- -------- ----- ------ -------- ------------------------------\n");	for (i = 0; i < VNODE_BUCKETS; i++) {		head = &vnode_table[i];		for (n = list_first(head); n != head; n = list_next(n)) {			vp = list_entry(n, struct vnode, v_link);			mp = vp->v_mount;			printf(" %08x %08x %s %6d %8d %s%s\n", (u_int)vp,			       (u_int)mp, type[vp->v_type], vp->v_count,			       (u_int)vp->v_blkno,			       (strlen(mp->m_path) == 1) ? "\0" : mp->m_path,			       vp->v_path);		}	}	printf("\n");	VNODE_UNLOCK();}#endifint vop_null(void){	return 0;}int vop_einval(void){	return EINVAL;}int vfs_null(void){	return 0;}void vnode_init(void){	int i;	for (i = 0; i < VNODE_BUCKETS; i++)		list_init(&vnode_table[i]);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -