Exemple #1
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;
}
Exemple #2
0
int _write(t_ext2* ext2,int fd, const void *buf,u32 count)
{
	u32 i;	
	u32 first_inode_block;
	u32 first_data_offset;
	u32 last_inode_block;
	u32 last_data_offset;
	u32 inode_block;
	u32 lba;
	u32 indirect_lba;
	u32 indirect_old_lba;
	u32 sector_count;
	u32 byte_to_read;
	u32 byte_read;
	u32 byte_count;
	u32 load_block;
	u32 update_indirct_block;
	t_inode* inode;
	char* iob_data_block;
	char* iob_indirect_block;
	u32 update_indirect_block;
	u32 byte_written;
	u32 byte_to_write;

	iob_data_block=kmalloc(BLOCK_SIZE);
	iob_indirect_block=kmalloc(BLOCK_SIZE);
	kfillmem(iob_data_block,0,BLOCK_SIZE);
	kfillmem(iob_indirect_block,0,BLOCK_SIZE);

	update_indirect_block=FALSE;
	byte_written=0;
	inode=hashtable_get(((struct t_process_context*)system.process_info->current_process)->file_desc,fd);
	first_inode_block=inode->file_offset/BLOCK_SIZE;
	first_data_offset=inode->file_offset%BLOCK_SIZE;
	last_inode_block=(inode->file_offset+count)/BLOCK_SIZE;
	last_data_offset=(inode->file_offset+count)%BLOCK_SIZE;

	byte_to_write=count;

	if (last_inode_block>=12)
	{
		if (inode->i_block[12]==0)
		{
			inode->i_block[12]=alloc_indirect_block(ext2,inode);
		}
		else
		{
			sector_count=BLOCK_SIZE/SECTOR_SIZE;
			READ(sector_count,inode->i_block[12],iob_indirect_block);
		}
	}

	for (i=first_inode_block;i<=last_inode_block;i++)
	{
		if ((i==first_inode_block && first_data_offset!=0) || (i==last_inode_block && last_data_offset!=0))
		{
			load_block=1;
			if (i>12)
			{
				if (iob_indirect_block[i-12]==0)
				{
					iob_indirect_block[i-12]=alloc_block(ext2,inode,i);
					load_block=0;
					update_indirect_block=TRUE;
				}
				lba=iob_indirect_block[i-12];
			}
			else
			{
				if (inode->i_block[i]==0)
				{
					inode->i_block[i]=alloc_block(ext2,inode,i);
					load_block=0;
				}
				lba=inode->i_block[i];
			}
			if (load_block)
			{
				sector_count=BLOCK_SIZE/SECTOR_SIZE;
				_read_28_ata(sector_count,lba,iob_data_block);
				if (i==first_inode_block)
				{
					iob_data_block+=first_data_offset;
					byte_count=BLOCK_SIZE-first_data_offset;
					byte_to_write-=byte_count;
				}
				else if (i==last_inode_block)
				{
					byte_count=last_data_offset;
					byte_to_write-=byte_count;
				}	
			}
		}
		else
		{
			byte_count=BLOCK_SIZE;
			byte_to_write-=BLOCK_SIZE;		
			if (i>12)
			{
				if (iob_indirect_block[i-12]==0)
				{
					iob_indirect_block[i-12]=alloc_block(ext2,inode,i);
					update_indirect_block=TRUE;
				}
				lba=iob_indirect_block[i-12];
			}
			else
			{
				if (inode->i_block[i]==0)
				{
					inode->i_block[i]=alloc_block(ext2,inode,i);
				}
				lba=inode->i_block[i];
			}
			byte_count=BLOCK_SIZE;
			byte_to_write-=BLOCK_SIZE;
		}
		kmemcpy(iob_data_block,buf,byte_count);
		sector_count=BLOCK_SIZE/SECTOR_SIZE;
		WRITE(sector_count,lba,iob_data_block);
		inode->file_offset+=byte_count;
		buf+=byte_count;
		byte_written+=byte_count;
	}
	if (update_indirect_block)
	{
		WRITE(sector_count,inode->i_block[12],iob_indirect_block);
	}
	kfree(iob_data_block);
	kfree(iob_indirect_block);
	return byte_written;
}