/* * See the comment in vfs.h for what is expected of this function. * * When this function returns, the inode refcount should be decremented. * * You probably want to use s5_free_inode() if there are no more links to * the inode, and dont forget to unpin the page */ static void s5fs_delete_vnode(vnode_t *vnode) { pframe_t *p; mmobj_t *fs_mmobj = S5FS_TO_VMOBJ(VNODE_TO_S5FS(vnode)); if (pframe_get(fs_mmobj, S5_INODE_BLOCK(vnode->vn_vno), &p)){ panic("pframe_get failed. What the hell do we do?\n"); } s5_inode_t *inode = ((s5_inode_t *) p->pf_addr) + S5_INODE_OFFSET(vnode->vn_vno); dbg(DBG_S5FS, "decrementing link count on inode %d from %d to %d\n", inode->s5_number, inode->s5_linkcount,inode->s5_linkcount - 1); inode->s5_linkcount--; if (inode->s5_linkcount == 0){ s5_free_inode(vnode); } else { s5_dirty_inode(VNODE_TO_S5FS(vnode), inode); } pframe_unpin(p); }
/* * s5_alloc_inode: * Creates a new inode from the free list and initializes its fields. * Uses S5_INODE_BLOCK to get the page from which to create the inode * * This function may block. * param *fs: the pointer to the file system * param type: the type of this new inode * param devid: device id * return: the inode number, or -1 for any errors */ int s5_alloc_inode(fs_t *fs, uint16_t type, devid_t devid) { s5fs_t *s5fs = FS_TO_S5FS(fs); pframe_t *inodep = NULL; s5_inode_t *inode = NULL; int ret = -1; KASSERT((S5_TYPE_DATA == type) || (S5_TYPE_DIR == type) || (S5_TYPE_CHR == type) || (S5_TYPE_BLK == type)); lock_s5(s5fs); if (s5fs->s5f_super->s5s_free_inode == (uint32_t) - 1) { unlock_s5(s5fs); return -ENOSPC; } pframe_get(&s5fs->s5f_bdev->bd_mmobj, S5_INODE_BLOCK(s5fs->s5f_super->s5s_free_inode), &inodep); KASSERT(inodep); inode = (s5_inode_t *)(inodep->pf_addr) + S5_INODE_OFFSET(s5fs->s5f_super->s5s_free_inode); KASSERT(inode->s5_number == s5fs->s5f_super->s5s_free_inode); ret = inode->s5_number; /* reset s5s_free_inode; remove the inode from the inode free list: */ s5fs->s5f_super->s5s_free_inode = inode->s5_next_free; pframe_pin(inodep); s5_dirty_super(s5fs); pframe_unpin(inodep); /* init the newly-allocated inode: */ inode->s5_size = 0; inode->s5_type = type; inode->s5_linkcount = 0; memset(inode->s5_direct_blocks, 0, S5_NDIRECT_BLOCKS * sizeof(int)); if ((S5_TYPE_CHR == type) || (S5_TYPE_BLK == type)) inode->s5_indirect_block = devid; else inode->s5_indirect_block = 0; s5_dirty_inode(s5fs, inode); unlock_s5(s5fs); return ret; }
/* * See the comment in vfs.h for what is expected of this function. * * When this function returns, the inode link count should be incremented. * Note that most UNIX filesystems don't do this, they have a separate * flag to indicate that the VFS is using a file. However, this is * simpler to implement. * * To get the inode you need to use pframe_get then use the pf_addr * and the S5_INODE_OFFSET(vnode) to get the inode * * Don't forget to update linkcounts and pin the page. * * Note that the devid is stored in the indirect_block in the case of * a char or block device * * Finally, the main idea is to do special initialization based on the * type of inode (i.e. regular, directory, char/block device, etc'). * */ static void s5fs_read_vnode(vnode_t *vnode) { pframe_t *p; mmobj_t *fs_mmobj = S5FS_TO_VMOBJ(VNODE_TO_S5FS(vnode)); if (pframe_get(fs_mmobj, S5_INODE_BLOCK(vnode->vn_vno), &p)){ panic("pframe_get failed. What the hell do we do?\n"); } pframe_pin(p); s5_inode_t *inode = ((s5_inode_t *) p->pf_addr) + S5_INODE_OFFSET(vnode->vn_vno); /* generic initializations */ vnode->vn_len = inode->s5_size; vnode->vn_i = (void *) inode; inode->s5_linkcount++; /* type-specific initializations */ KASSERT(inode->s5_type == S5_TYPE_DATA || inode->s5_type == S5_TYPE_DIR || inode->s5_type == S5_TYPE_CHR || inode->s5_type == S5_TYPE_BLK); switch (inode->s5_type){ case S5_TYPE_DATA: vnode->vn_ops = &s5fs_file_vops; vnode->vn_mode = S_IFREG; break; case S5_TYPE_DIR: vnode->vn_ops = &s5fs_dir_vops; vnode->vn_mode = S_IFDIR; break; case S5_TYPE_CHR: vnode->vn_mode = S_IFCHR; vnode->vn_devid = inode->s5_indirect_block; break; default: /* S5_TYPE_BLK */ vnode->vn_mode = S_IFBLK; vnode->vn_devid = inode->s5_indirect_block; } s5_dirty_inode(VNODE_TO_S5FS(vnode), inode); }
/* * s5fs_delete_vnode: * s5fs_delete_vnode is called by vput when the * specified vnode_t no longer needs to exist * param *vnode: the pointer to the vnode object */ static void s5fs_delete_vnode(vnode_t *vnode) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); KASSERT(vnode->vn_fs != NULL); /* Lock */ kmutex_lock(&vnode->vn_mutex); pframe_t* page = NULL; int ret = pframe_get(S5FS_TO_VMOBJ(FS_TO_S5FS(vnode->vn_fs)), S5_INODE_BLOCK(vnode->vn_vno), &page); KASSERT(ret == 0); KASSERT(page != NULL); s5_inode_t* inode = ((s5_inode_t*)page->pf_addr) + S5_INODE_OFFSET(vnode->vn_vno); inode->s5_linkcount--; s5_dirty_inode(VNODE_TO_S5FS(vnode), inode); KASSERT(VNODE_TO_S5INODE(vnode) == inode); KASSERT(inode->s5_linkcount >= 0); if (inode->s5_linkcount== 0) { s5_free_inode(vnode); } pframe_unpin(page); /* Unlock */ kmutex_unlock(&vnode->vn_mutex); dbg(DBG_S5FS, "}\n"); }
/* * s5fs_read_vnode: * s5fs_read_vnode will be passed a vnode_t*, which will have its vn_fs * and vn_vno fields initialized. * param *vnode: the pointer to the vnode object */ static void s5fs_read_vnode(vnode_t *vnode) { dbg(DBG_S5FS, "{\n"); KASSERT(vnode != NULL); KASSERT(vnode->vn_fs != NULL); kmutex_lock(&vnode->vn_mutex); pframe_t* page = NULL; int ret = pframe_get(S5FS_TO_VMOBJ(FS_TO_S5FS(vnode->vn_fs)), S5_INODE_BLOCK(vnode->vn_vno), &page); KASSERT(ret == 0); KASSERT(page != NULL); pframe_pin(page); s5_inode_t* inode = ((s5_inode_t*)page->pf_addr) + S5_INODE_OFFSET(vnode->vn_vno); inode->s5_linkcount++; s5_dirty_inode(VNODE_TO_S5FS(vnode), inode); vnode->vn_i = inode; vnode->vn_len = inode->s5_size; switch(inode->s5_type) { case S5_TYPE_DIR: { vnode->vn_mode = S_IFDIR; vnode->vn_ops = &s5fs_dir_vops; break; } case S5_TYPE_DATA: { vnode->vn_mode = S_IFREG; vnode->vn_ops = &s5fs_file_vops; break; } case S5_TYPE_CHR: { vnode->vn_mode = S_IFCHR; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_cdev = bytedev_lookup(vnode->vn_devid); break; } case S5_TYPE_BLK: { vnode->vn_mode = S_IFBLK; vnode->vn_ops = NULL; vnode->vn_devid = (devid_t)(inode->s5_indirect_block); vnode->vn_bdev = blockdev_lookup(vnode->vn_devid); break; } default: { panic("inode %d has unknown/invalid type %d!!\n", (int)vnode->vn_vno, (int)inode->s5_type); } } kmutex_unlock(&vnode->vn_mutex); dbg(DBG_S5FS, "}\n"); }