Ejemplo n.º 1
0
/* allocated an indirect block for a vnode who's indirect block is currently sparse */
static int alloc_indirect_block(vnode_t *v){

    /* an array of 0's that we'll use to quickly create blocks of zeros */
    static int zero_array[BLOCK_SIZE] = {};

    s5_inode_t *inode = VNODE_TO_S5INODE(v);

    KASSERT(inode->s5_indirect_block == 0);

    /* first, get an indirect block */
    int indirect_block = s5_alloc_block(VNODE_TO_S5FS(v));

    if (indirect_block == -ENOSPC){
        dbg(DBG_S5FS, "couldn't alloc a new block\n");
        return -ENOSPC;
    }

    KASSERT(indirect_block > 0 && "forgot to handle an error case");

    /* then, zero it */
    pframe_t *ind_page;
    mmobj_t *mmo = S5FS_TO_VMOBJ(VNODE_TO_S5FS(v));

    int get_res = pframe_get(mmo, indirect_block, &ind_page);

    if (get_res < 0){
        return get_res;
    }

    memcpy(ind_page->pf_addr, zero_array, BLOCK_SIZE);

    int dirty_res = pframe_dirty(ind_page);

    if (dirty_res < 0){
        return dirty_res;
    }

    /* finally, set this block to be the indirect block of the inode */
    inode->s5_indirect_block = indirect_block;
    s5_dirty_inode(VNODE_TO_S5FS(v), inode);

    return 0;
}
Ejemplo n.º 2
0
/*
 * s5_seek_to_block:
 * Return the disk-block number for the given seek pointer (aka file
 * position).
 * param vnode: pointer to vnode
 * param seekptr: seek offset
 * alloc: allocate new page or not
 * return: the block number, or negative number on failure
 */
int
s5_seek_to_block(vnode_t *vnode, off_t seekptr, int alloc)
{
    KASSERT(vnode != 0);
    KASSERT(alloc == 1 || alloc == 0);
    KASSERT(seekptr >= 0);

    s5_inode_t* inode = VNODE_TO_S5INODE(vnode);

    uint32_t block_number = S5_DATA_BLOCK(seekptr);

    /* check if the block_number is valid */
    if (block_number >= S5_NIDIRECT_BLOCKS + S5_NDIRECT_BLOCKS)
    {
        return -1;
    }
    if (block_number < S5_NDIRECT_BLOCKS)
    {
        /* sparse block */
        if (inode->s5_direct_blocks[block_number] == 0)
        {
            /* alloc is zero, simply return */
            if (alloc == 0)
            {
                return 0;
            }
            else
            {
                /* alloc a new disk block */
                int block_num = s5_alloc_block(VNODE_TO_S5FS(vnode));
                if (block_num < 0)
                {
                    /* error */
                    return block_num;
                }
                else
                {
                    /* add the new block to inode */
                    inode->s5_direct_blocks[block_number] = block_num;
                    /* dirty the inode */
                    s5_dirty_inode((VNODE_TO_S5FS(vnode)), inode);
                    return block_num;
                }
            }
        }
        else /* already there*/
        {
            return inode->s5_direct_blocks[block_number];
        }
    }
    else
    {
        /* indirect blocks */
        /* if the indirect block is zero, alloc it firstly */
        pframe_t* page = NULL;

        if (inode->s5_indirect_block == 0)
        {
            int block_num = 0;
            if ((block_num = s5_alloc_block(FS_TO_S5FS(vnode->vn_fs))) < 0)
            {
                return block_num;
            }
            else
            {
                int ret = pframe_get(S5FS_TO_VMOBJ(FS_TO_S5FS(vnode->vn_fs)),
                                     block_num, &page);
                if (ret < 0 || page == NULL)
                {
                    return ret;
                }
                else
                {
                    pframe_pin(page);
                    memset(page->pf_addr, 0, S5_BLOCK_SIZE);
                    pframe_dirty(page);
                    pframe_unpin(page);
                    inode->s5_indirect_block = block_num;
                    s5_dirty_inode(FS_TO_S5FS(vnode->vn_fs), inode);
                }
            }
        }
        else
        {
            int ret = pframe_get(S5FS_TO_VMOBJ(FS_TO_S5FS(vnode->vn_fs)),
                                 inode->s5_indirect_block, &page);
            if (ret < 0 || page == NULL)
                return ret;
        }

        KASSERT(page != NULL);

        pframe_pin(page);
        int off = block_number - S5_NDIRECT_BLOCKS;
        int32_t* addr = ((int32_t*)page->pf_addr) + off;
        pframe_unpin(page);

        if (*addr == 0)
        {
            if (alloc == 0)
            {
                return 0;
            }
            else
            {
                int block_num = s5_alloc_block(VNODE_TO_S5FS(vnode));
                if (block_num < 0)
                {
                    return block_num;
                }
                else
                {
                    pframe_pin(page);
                    *addr = block_num;
                    pframe_dirty(page);
                    pframe_unpin(page);
                    return block_num;
                }
            }
        }
        else
        {
            /* already there, return */
            return *addr;
        }
    }
}
Ejemplo n.º 3
0
/*
 * Return the disk-block number for the given seek pointer (aka file
 * position).
 *
 * If the seek pointer refers to a sparse block, and alloc is false,
 * then return 0. If the seek pointer refers to a sparse block, and
 * alloc is true, then allocate a new disk block (and make the inode
 * point to it) and return it.
 *
 * Be sure to handle indirect blocks!
 *
 * If there is an error, return -errno.
 *
 * You probably want to use pframe_get, pframe_pin, pframe_unpin, pframe_dirty.
 */
int
s5_seek_to_block(vnode_t *vnode, off_t seekptr, int alloc)
{
    int block_index = S5_DATA_BLOCK(seekptr);

    if ((unsigned) block_index >= S5_MAX_FILE_BLOCKS){
        dbg(DBG_S5FS, "file too large");
        return -EFBIG;
    }

    if (seekptr > vnode->vn_len && !alloc){
        return 0;
    }

    s5_inode_t *inode = VNODE_TO_S5INODE(vnode);

    uint32_t block_num;

    if (block_index >= S5_NDIRECT_BLOCKS){
        pframe_t *ind_page;

        mmobj_t *mmo = S5FS_TO_VMOBJ(VNODE_TO_S5FS(vnode));

        if (inode->s5_indirect_block == 0){
            if (!alloc){
                return 0;
            }

            int alloc_res = alloc_indirect_block(vnode);
            if (alloc_res < 0){
                dbg(DBG_S5FS, "error allocating indirect block\n");
                return alloc_res;
            }
        }

        if (pframe_get(mmo, inode->s5_indirect_block, &ind_page) < 0){
            panic("an indirect block is messed up\n");
        }

        block_num = ((uint32_t *) ind_page->pf_addr)[block_index - S5_NDIRECT_BLOCKS];

        /* case where we've found a sparse block and need to allocate*/
        if (block_num == 0 && alloc){

            pframe_pin(ind_page);
            int block_num = s5_alloc_block(VNODE_TO_S5FS(vnode));
            pframe_unpin(ind_page);

            if (block_num == -ENOSPC){
                dbg(DBG_S5FS, "couldn't alloc a new block\n");
                return -ENOSPC;
            }

            KASSERT(block_num > 0 && "forgot to handle an error case");

            ((uint32_t *) ind_page->pf_addr)[block_index - S5_NDIRECT_BLOCKS] = block_num;

            int dirty_res = pframe_dirty(ind_page);

            if (dirty_res < 0){
                return dirty_res;
            }

        }

    } else {
        block_num = inode->s5_direct_blocks[block_index];

        /* case where we've found a sparse block and need to allocate*/
        if (block_num == 0 && alloc){
            int block_num = s5_alloc_block(VNODE_TO_S5FS(vnode));

            if (block_num == -ENOSPC){
                dbg(DBG_S5FS, "couldn't alloc a new block\n");
                return -ENOSPC;
            }

            KASSERT(block_num > 0 && "forgot to handle an error case");

            inode->s5_direct_blocks[block_index] = block_num;
            s5_dirty_inode(VNODE_TO_S5FS(vnode), inode);
        }
    }

    return block_num;
}
Ejemplo n.º 4
0
/*
 * Return the disk-block number for the given seek pointer (aka file
 * position).
 *
 * If the seek pointer refers to a sparse block, and alloc is false,
 * then return 0. If the seek pointer refers to a sparse block, and
 * alloc is true, then allocate a new disk block (and make the inode
 * point to it) and return it.
 *
 * Be sure to handle indirect blocks!
 *
 * If there is an error, return -errno.
 *
 * You probably want to use pframe_get, pframe_pin, pframe_unpin, pframe_dirty.
 */
int
s5_seek_to_block(vnode_t *vnode, off_t seekptr, int alloc)
{
    /* CASE     BLOCK TYPE      ALLOC       Direct Sparse       Indirect Sparse         WAT DO?
    *    1          (BLOCK > Total Blocks)                                              Return Error
    *    2      DIRECT          FALSE       TRUE                N/A                     return block from s5_direct_blocks
    *    3      DIRECT          TRUE        TRUE                N/A                     allocate new block and point inode (also memcpy)
    *    4      DIRECT          TRUE        FALSE               N/A                     return block from s5_direct_blocks
    *    5      INDIRECT        FALSE       TRUE                TRUE                    return 0
    *    7      INDIRECT        FALSE       FALSE               FALSE                   Find block we want
    *    8      INDIRECT        TRUE        FALSE               FALSE                   Find block we want
    *    9      INDIRECT        TRUE        TRUE                FALSE                   allocate new block, memcpy to 0, set data address in indirect
    
    *    *      INDIRECT        TRUE        N/A                 TRUE                    allocate new block, pframe_get on inode->indirect_block
    */
    dbg_print("s5_seek_to_block: Entering Function, seekptr: %i, alloc: %i\n",seekptr,alloc);
    s5fs_t* vnode_s5fs = VNODE_TO_S5FS(vnode);
    s5_inode_t* vnode_inode = VNODE_TO_S5INODE(vnode);
    struct mmobj* vnode_vmobj = S5FS_TO_VMOBJ(vnode_s5fs);
    uint32_t data_block = S5_DATA_BLOCK(seekptr);
    
    pframe_t* pf;
    dbg_print("s5_seek_to_block: a\n");
    if(data_block > S5_MAX_FILE_BLOCKS)
    {
        /* Case 1 */
        dbg_print("s5_seek_to_block: Case 1\n");
        return 0;
    }

    if(data_block < S5_NDIRECT_BLOCKS)
    {
        dbg_print("s5_seek_to_block: b\n");
        /* Direct Block */
        if(!alloc)
        {
            /* ALLOC FALSE */
            /* CASE 2 */
            dbg_print("s5_seek_to_block: c\n");
            dbg_print("s5_seek_to_block: Case 2\n");
            return vnode_inode->s5_direct_blocks[data_block];
        }
        else
        {
            /* ALLOC TRUE */
            dbg_print("s5_seek_to_block: d\n");
            if(vnode_inode->s5_direct_blocks[data_block] == 0)
            {
                /* Sparse Block */
                /* CASE 3 */
                dbg_print("s5_seek_to_block: e\n");
                pframe_get(vnode_vmobj,data_block,&pf);
                pframe_pin(pf);

                int block_alloc = s5_alloc_block(vnode_s5fs);
                dbg_print("s5_seek_to_block: f\n");
                if(block_alloc == -ENOSPC)
                {
                    /* Allocation Failure */
                    dbg_print("s5_seek_to_block: g\n");
                    pframe_unpin(pf);
                    dbg_print("s5_seek_to_block: Allocation Failure #1\n");
                    return -ENOSPC;
                }
                else
                {
                    /* Success in Allocation, Connect Inode and Dirty */
                    dbg_print("s5_seek_to_block: h\n");
                    vnode_inode->s5_direct_blocks[data_block] = block_alloc;
                    /* memset(pf->pf_addr, 0, PAGE_SIZE); */
                    pframe_dirty(pf);
                    s5_dirty_inode(vnode_s5fs,vnode_inode);
                    pframe_unpin(pf);
                    dbg_print("s5_seek_to_block: Case 3\n");
                    return block_alloc;
                }
            }
            else
            {
                /* Not Sparse Block */

                /* CASE 4 */
                dbg_print("s5_seek_to_block: Case 4\n");
                return vnode_inode->s5_direct_blocks[data_block];
            }
        }
    }
    else
    {
        /* Indirect Block */
        dbg_print("s5_seek_to_block: i\n");
        if(!alloc)
        {
            /* ALLOC FALSE */
            dbg_print("s5_seek_to_block: j\n");
            if(vnode_inode->s5_indirect_block == 0)
            {
                /* Sparse Block */
                /* CASE 5 */
                dbg_print("s5_seek_to_block: Case 5\n");
                return 0;
            }
            else
            {
                /* Not Sparse Block */
                /* CASE 7 */
                dbg_print("s5_seek_to_block: Case 7\n");
                return vnode_inode->s5_direct_blocks[data_block - S5_NDIRECT_BLOCKS];
            }
        }
        else
        {
            /* ALLOC TRUE */
            dbg_print("s5_seek_to_block: k\n");
            if(vnode_inode->s5_indirect_block == 0)
            {
                /* Sparse Block */
                /* CASE 5 */
                dbg_print("s5_seek_to_block: l\n");
                int indirect_alloc = s5_alloc_block(vnode_s5fs);
            
                if(indirect_alloc == -ENOSPC)
                {
                    /* Allocation Failure */
                    dbg_print("s5_seek_to_block: Allocation Failure #2\n");
                    return -ENOSPC;
                }

                /* Success in Allocation, Connect Inode and Dirty */  
                dbg_print("s5_seek_to_block: m\n");       
                pframe_get(vnode_vmobj,vnode_inode->s5_indirect_block,&pf);
                pframe_pin(pf);

                /* memset(pf->pf_addr, 0, PAGE_SIZE); */
                vnode_inode->s5_indirect_block = indirect_alloc;

                pframe_dirty(pf);
                s5_dirty_inode(vnode_s5fs,vnode_inode);
                dbg_print("s5_seek_to_block: n\n");
            }
            else
            {
                /* Not Sparse Block */
                dbg_print("s5_seek_to_block: o\n");
                pframe_get(vnode_vmobj,vnode_inode->s5_indirect_block,&pf);
                pframe_pin(pf);
            }

            dbg_print("s5_seek_to_block: p\n");
            uint32_t indirect_map = data_block - S5_NDIRECT_BLOCKS;
            uint32_t* block_array = (uint32_t*)pf->pf_addr;
            int direct_index = block_array[indirect_map];
            if(direct_index == 0)
            {
                dbg_print("s5_seek_to_block: q\n");
                direct_index = s5_alloc_block(vnode_s5fs);
                if(direct_index == -ENOSPC)
                {
                    /* Allocation Failure */
                    dbg_print("s5_seek_to_block: Allocation Failure #3\n");
                    return -ENOSPC;
                }

            }
            dbg_print("s5_seek_to_block: rn");
            block_array[indirect_map] = direct_index;
            pframe_dirty(pf);
            pframe_unpin(pf);

            dbg_print("s5_seek_to_block: Case 6\n");
            return direct_index;
        }
    }

        /* NOT_YET_IMPLEMENTED("S5FS: s5_seek_to_block");
        * return -1;
        */
}