Esempio n. 1
0
/*
 * 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);
}
Esempio n. 2
0
/*
 * 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;
}
Esempio n. 3
0
/*
 * 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);
}
Esempio n. 4
0
/*
 * 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");
}
Esempio n. 5
0
/*
 * 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");
}