/* * Function to create a vnode for a VFS device. */ struct vnode * dev_create_vnode(struct device *dev) { int result; struct vnode *v; v = kmalloc(sizeof(struct vnode)); if (v==NULL) { return NULL; } result = VOP_INIT(v, &dev_vnode_ops, NULL, dev); if (result != 0) { panic("While creating vnode for device: VOP_INIT: %s\n", strerror(result)); } return v; }
/* * Function to load a inode into memory as a vnode, or dig up one * that's already resident. */ static int sfs_loadvnode(struct sfs_fs *sfs, u_int32_t ino, int forcetype, struct sfs_vnode **ret) { struct sfs_vnode *sv; const struct vnode_ops *ops = NULL; int i, num; int result; lock_acquire(sfs->sfs_vnodes_lock); /* Look in the vnodes table */ num = array_getnum(sfs->sfs_vnodes); /* Linear search. Is this too slow? You decide. */ for (i=0; i<num; i++) { sv = array_getguy(sfs->sfs_vnodes, i); /* Every inode in memory must be in an allocated block */ if (!sfs_bused(sfs, sv->sv_ino)) { panic("sfs: Found inode %u in unallocated block\n", sv->sv_ino); } if (sv->sv_ino==ino) { /* Found */ /* May only be set when creating new objects */ assert(forcetype==SFS_TYPE_INVAL); VOP_INCREF(&sv->sv_v); lock_release(sfs->sfs_vnodes_lock); *ret = sv; return 0; } } /* Didn't have it loaded; load it */ sv = kmalloc(sizeof(struct sfs_vnode)); if (sv==NULL) { lock_release(sfs->sfs_vnodes_lock); return ENOMEM; } /* Must be in an allocated block */ if (!sfs_bused(sfs, ino)) { panic("sfs: Tried to load inode %u from unallocated block\n", ino); } /* Read the block the inode is in */ result = sfs_rblock(sfs, &sv->sv_i, ino); if (result) { kfree(sv); lock_release(sfs->sfs_vnodes_lock); return result; } /* Not dirty yet */ sv->sv_dirty = 0; /* * FORCETYPE is set if we're creating a new file, because the * block on disk will have been zeroed out and thus the type * recorded there will be SFS_TYPE_INVAL. */ if (forcetype != SFS_TYPE_INVAL) { assert(sv->sv_i.sfi_type == SFS_TYPE_INVAL); sv->sv_i.sfi_type = forcetype; sv->sv_dirty = 1; } /* * Choose the function table based on the object type. */ switch (sv->sv_i.sfi_type) { case SFS_TYPE_FILE: ops = &sfs_fileops; break; case SFS_TYPE_DIR: ops = &sfs_dirops; break; default: panic("sfs: loadvnode: Invalid inode type " "(inode %u, type %u)\n", ino, sv->sv_i.sfi_type); } /* Call the common vnode initializer */ result = VOP_INIT(&sv->sv_v, ops, &sfs->sfs_absfs, sv); if (result) { kfree(sv); lock_release(sfs->sfs_vnodes_lock); return result; } /* Set the other fields in our vnode structure */ sv->sv_ino = ino; /* Add it to our table */ result = array_add(sfs->sfs_vnodes, sv); if (result) { VOP_KILL(&sv->sv_v); kfree(sv); lock_release(sfs->sfs_vnodes_lock); return result; } lock_release(sfs->sfs_vnodes_lock); /* Hand it back */ *ret = sv; return 0; }
/* * Function to load a vnode into memory. */ static int emufs_loadvnode(struct emufs_fs *ef, uint32_t handle, int isdir, struct emufs_vnode **ret) { struct vnode *v; struct emufs_vnode *ev; unsigned i, num; int result; vfs_biglock_acquire(); lock_acquire(ef->ef_emu->e_lock); num = vnodearray_num(ef->ef_vnodes); for (i=0; i<num; i++) { v = vnodearray_get(ef->ef_vnodes, i); ev = v->vn_data; if (ev->ev_handle == handle) { /* Found */ VOP_INCREF(&ev->ev_v); lock_release(ef->ef_emu->e_lock); vfs_biglock_release(); *ret = ev; return 0; } } /* Didn't have one; create it */ ev = kmalloc(sizeof(struct emufs_vnode)); if (ev==NULL) { lock_release(ef->ef_emu->e_lock); return ENOMEM; } ev->ev_emu = ef->ef_emu; ev->ev_handle = handle; result = VOP_INIT(&ev->ev_v, isdir ? &emufs_dirops : &emufs_fileops, &ef->ef_fs, ev); if (result) { lock_release(ef->ef_emu->e_lock); vfs_biglock_release(); kfree(ev); return result; } result = vnodearray_add(ef->ef_vnodes, &ev->ev_v, NULL); if (result) { /* note: VOP_CLEANUP undoes VOP_INIT - it does not kfree */ VOP_CLEANUP(&ev->ev_v); lock_release(ef->ef_emu->e_lock); vfs_biglock_release(); kfree(ev); return result; } lock_release(ef->ef_emu->e_lock); vfs_biglock_release(); *ret = ev; return 0; }