Esempio n. 1
0
/*
 * s5_alloc_block:
 * Allocate a new disk-block off the block free list and return it.
 * param *fs: the pointer to the file system object
 * return: the block number, or negative number if no space
 */
static int
s5_alloc_block(s5fs_t *fs)
{
    dbg(DBG_S5FS, "{\n");
    KASSERT(fs != NULL);

    lock_s5(fs);
    s5_super_t* super = fs->s5f_super;
    pframe_t* next_free_block = NULL;
    int ret = 0;
    int block_number = 0;

    if (super->s5s_nfree == 0) /* no free pages */
    {
        int ret = pframe_get( S5FS_TO_VMOBJ(fs),
                              super->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1],
                              &next_free_block);

        if (ret < 0 || next_free_block == NULL)
        {
            /* No more free blocks */

            unlock_s5(fs);
            dbg(DBG_S5FS, "}(error code returned)\n");
            return -ENOSPC;
        }
        else
        {
            block_number = super->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1];
            /* copy the next free block into the super block */
            memcpy((void*)(super->s5s_free_blocks), next_free_block->pf_addr,
                   S5_NBLKS_PER_FNODE * sizeof(uint32_t));

            memset(next_free_block->pf_addr, 0, S5_BLOCK_SIZE);

            pframe_dirty(next_free_block);
            pframe_clean(next_free_block);
            pframe_free(next_free_block);
            /* now full */
            super->s5s_nfree = S5_NBLKS_PER_FNODE-1;

            s5_dirty_super(fs);
            unlock_s5(fs);
            dbg(DBG_S5FS, "}\n");
            return block_number;
        }
    }
    else /* there is some free pages */
    {
        block_number = super->s5s_free_blocks[super->s5s_nfree - 1];
        super->s5s_nfree--;
        s5_dirty_super(fs);
        unlock_s5(fs);
        dbg(DBG_S5FS, "}\n");
        return block_number;
    }
}
Esempio n. 2
0
/*
 * s5_free_block
 * Given a filesystem and a block number, frees the given block in the
 * filesystem.
 *
 * This function may potentially block.
 * param *fs: the pointer to the file system
 * param blockno: the block number
 */
static void
s5_free_block(s5fs_t *fs, int blockno)
{
    s5_super_t *s = fs->s5f_super;

    lock_s5(fs);

    KASSERT(S5_NBLKS_PER_FNODE > s->s5s_nfree);

    if ((S5_NBLKS_PER_FNODE - 1) == s->s5s_nfree)
    {
        /* get the pframe where we will store the free block nums */
        pframe_t *prev_free_blocks = NULL;
        KASSERT(fs->s5f_bdev);
        pframe_get(&fs->s5f_bdev->bd_mmobj, blockno, &prev_free_blocks);
        KASSERT(prev_free_blocks->pf_addr);

        /* copy from the superblock to the new block on disk */
        memcpy(prev_free_blocks->pf_addr, (void *)(s->s5s_free_blocks),
               S5_NBLKS_PER_FNODE * sizeof(int));
        pframe_dirty(prev_free_blocks);

        /* reset s->s5s_nfree and s->s5s_free_blocks */
        s->s5s_nfree = 0;
        s->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1] = blockno;
    }
    else
    {
        s->s5s_free_blocks[s->s5s_nfree++] = blockno;
    }

    s5_dirty_super(fs);
    unlock_s5(fs);
}
Esempio n. 3
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. 4
0
/*
 * Allocate a new disk-block off the block free list and return it. If
 * there are no free blocks, return -ENOSPC.
 *
 * This will not initialize the contents of an allocated block; these
 * contents are undefined.
 *
 * If the super block's s5s_nfree is 0, you need to refill 
 * s5s_free_blocks and reset s5s_nfree.  You need to read the contents 
 * of this page using the pframe system in order to obtain the next set of
 * free block numbers.
 *
 * Don't forget to dirty the appropriate blocks!
 *
 * You'll probably want to use lock_s5(), unlock_s5(), pframe_get(),
 * and s5_dirty_super()
 */
static int
s5_alloc_block(s5fs_t *fs)
{
    dbg_print("s5_alloc_block: Entering Function\n");
    /* get the super block frame */
    s5_super_t* superblock = fs->s5f_super;
    int block_return;
    lock_s5(fs);

    if(((int)superblock->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1] == -1) 
        && (superblock->s5s_nfree == 0))
    {
        dbg_print("s5_alloc_block: No free blocks, returning error");
        unlock_s5(fs);
        return -ENOSPC;
    }
    
    if(superblock->s5s_nfree == 0)
    {
        dbg_print("s5_alloc_block: Out of free blocks, getting more!\n");
        struct mmobj* fs_vmobj = S5FS_TO_VMOBJ(fs);
    
        int next_block = superblock->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1];

        pframe_t* pf;
        pframe_get(fs_vmobj,next_block,&pf);
        pframe_pin(pf);

        memcpy(((char*)superblock->s5s_free_blocks),pf->pf_addr,S5_NBLKS_PER_FNODE * sizeof(uint32_t));
        superblock->s5s_nfree = S5_NBLKS_PER_FNODE - 1;

        block_return = next_block;

        pframe_unpin(pf);
    }
    else
    {
        /* Frre blocks are available */
        dbg_print("s5_alloc_block: Free block available\n");
        superblock->s5s_nfree--;
        block_return = superblock->s5s_free_blocks[superblock->s5s_nfree];
    }

    s5_dirty_super(fs);
    unlock_s5(fs);
    dbg_print("s5_alloc_block: Exiting Function\n");
    return block_return;

        /* NOT_YET_IMPLEMENTED("S5FS: s5_alloc_block");
        * return -1;
        */
}
Esempio n. 5
0
/*
 * Allocate a new disk-block off the block free list and return it. If
 * there are no free blocks, return -ENOSPC.
 *
 * This will not initialize the contents of an allocated block; these
 * contents are undefined.
 *
 * If the super block's s5s_nfree is 0, you need to refill 
 * s5s_free_blocks and reset s5s_nfree.  You need to read the contents 
 * of this page using the pframe system in order to obtain the next set of
 * free block numbers.
 *
 * Don't forget to dirty the appropriate blocks!
 *
 * You'll probably want to use lock_s5(), unlock_s5(), pframe_get(),
 * and s5_dirty_super()
 */
static int
s5_alloc_block(s5fs_t *fs)
{
    s5_super_t *s = fs->s5f_super;

    lock_s5(fs);

    KASSERT(S5_NBLKS_PER_FNODE > s->s5s_nfree);

    int free_block_num;

    if (s->s5s_nfree == 0){
        free_block_num = s->s5s_free_blocks[S5_NBLKS_PER_FNODE - 1];

        if (free_block_num == -1){
            unlock_s5(fs);
            return -ENOSPC;
        }

        /* get the pframe from which we'll replenish our list of free block nums */
        pframe_t *next_free_blocks;
        KASSERT(fs->s5f_bdev);
        int get_res = pframe_get(&fs->s5f_bdev->bd_mmobj, free_block_num,
                &next_free_blocks);

        if (get_res < 0){
            dbg(DBG_S5FS, "error in pframe_get\n");
            unlock_s5(fs);
            return get_res;
        }

        memcpy((void *)(s->s5s_free_blocks), next_free_blocks->pf_addr, 
                S5_NBLKS_PER_FNODE * sizeof(int));

        s->s5s_nfree = S5_NBLKS_PER_FNODE - 1;
    } else {
        free_block_num = s->s5s_free_blocks[--s->s5s_nfree];
    }

    s5_dirty_super(fs);

    unlock_s5(fs);

    return free_block_num;
}
Esempio n. 6
0
/*
 * s5_free_inode:
 * Free an inode by freeing its disk blocks and putting it back on the
 * inode free list.
 * param *vnode: the pointer to the vnode object
 */
void
s5_free_inode(vnode_t *vnode)
{
    uint32_t i = 0;
    s5_inode_t *inode = VNODE_TO_S5INODE(vnode);
    s5fs_t *fs = VNODE_TO_S5FS(vnode);

    KASSERT((S5_TYPE_DATA == inode->s5_type)
            || (S5_TYPE_DIR == inode->s5_type)
            || (S5_TYPE_CHR == inode->s5_type)
            || (S5_TYPE_BLK == inode->s5_type));

    /* free any direct blocks */
    for (i = 0; i < S5_NDIRECT_BLOCKS; ++i)
    {
        if (inode->s5_direct_blocks[i])
        {
            dprintf("freeing block %d\n", inode->s5_direct_blocks[i]);
            s5_free_block(fs, inode->s5_direct_blocks[i]);

            s5_dirty_inode(fs, inode);
            inode->s5_direct_blocks[i] = 0;
        }
    }

    if (((S5_TYPE_DATA == inode->s5_type)
            || (S5_TYPE_DIR == inode->s5_type))
            && inode->s5_indirect_block)
    {
        pframe_t *ibp;
        uint32_t *b;

        pframe_get(S5FS_TO_VMOBJ(fs),
                   (unsigned)inode->s5_indirect_block,
                   &ibp);
        KASSERT(ibp
                && "because never fails for block_device "
                "vm_objects");
        pframe_pin(ibp);

        b = (uint32_t *)(ibp->pf_addr);
        for (i = 0; i < S5_NIDIRECT_BLOCKS; ++i)
        {
            KASSERT(b[i] != inode->s5_indirect_block);
            if (b[i])
                s5_free_block(fs, b[i]);
        }

        pframe_unpin(ibp);

        s5_free_block(fs, inode->s5_indirect_block);
    }

    inode->s5_indirect_block = 0;
    inode->s5_type           = S5_TYPE_FREE;

    s5_dirty_inode(fs, inode);

    lock_s5(fs);
    inode->s5_next_free           = fs->s5f_super->s5s_free_inode;
    fs->s5f_super->s5s_free_inode = inode->s5_number;
    unlock_s5(fs);

    s5_dirty_inode(fs, inode);
    s5_dirty_super(fs);
}