Beispiel #1
0
/*
 * Initializes the file system manager.
 */
PUBLIC void fs_init(void)
{
	binit();
	inode_init();
	superblock_init();
	
	/* Sanity check. */
	CHKSIZE(sizeof(struct d_dirent), sizeof(struct dirent));

	rootdev = superblock_read(ROOT_DEV);
	
	/* Failed to read root super block. */
	if (rootdev == NULL)
		kpanic("failed to mount root file system");
		
	superblock_unlock(rootdev);
	
	root = inode_get(ROOT_DEV, 1);
	
	/* Failed to read root inode. */
	if (root == NULL)
		kpanic("failed to read root inode");
	
	kprintf("fs: root file system mounted");
	
	/* Hand craft idle process. */
	IDLE->pwd = root;
	IDLE->root = root;
	root->count += 2;
	
	inode_unlock(root);
}
Beispiel #2
0
/**
 * @brief Create an indirect block.
 *
 * @details Creates a indirect block and saves in @param dest.
 *
 * @param dest Destination buffer, It is the corresponding disk block to be changed.
 * @param ip File to use.
 * @param offset Offset to be calculated the block.
 * @param creat If 1, creates an block, otherwise, just return this value.
 *
 * @returns If successful, the block number created / obtained, otherwise BLOCK_NULL is 
 *          returned.
 *
 * @note @p ip must be locked.
 */
PUBLIC block_t create_indirect_block
(struct buffer *dest, struct inode *ip, off_t offset, int create)
{
	block_t phys; /* Physical block number. */

	if (((block_t *)buffer_data(dest))[offset] == BLOCK_NULL && create)
	{
		/* Allocate an block. */
		superblock_lock(ip->sb);
		phys = block_alloc(ip->sb);
		superblock_unlock(ip->sb);

		if (phys != BLOCK_NULL)
		{
			((block_t *)buffer_data(dest))[offset] = phys;
			buffer_dirty(dest, 1);
			inode_touch(ip);
			brelse(dest);
			return (phys);
		}
		else
		{
			brelse(dest);
			return (phys);
		}
	}
	else
	{
		brelse(dest);
		return ((block_t *)buffer_data(dest))[offset];
	}
}
Beispiel #3
0
/**
 * @brief Create an direct block.
 *
 * @details Creates a direct block and saves in @param dest.
 *
 * @param ip File to use.
 * @param offset Offset to be calculated the block.
 * @param creat If 1, creates an block, otherwise, just return this value.
 *
 * @returns If successful, the block number created/obtained, otherwise BLOCK_NULL is 
 *          returned.
 *
 * @note @p ip must be locked.
 */
PUBLIC block_t create_direct_block(struct inode *ip, off_t offset, int create)
{
	block_t phys; /* Physical block number. */

	if (ip->blocks[offset] == BLOCK_NULL && create)
	{
		/* Allocate an block. */
		superblock_lock(ip->sb);
		phys = block_alloc(ip->sb);
		superblock_unlock(ip->sb);

		if (phys != BLOCK_NULL)
		{
			ip->blocks[offset] = phys;
			inode_touch(ip);
			return (phys);
		}
		else
			return (phys);
	}
	else
		return (ip->blocks[offset]);
}
Beispiel #4
0
/**
 * @brief Maps a file byte offset in a disk block number.
 * 
 * @details Maps the offset @p off in the file pointed to by @p ip in a disk
 *          block number. If @p create is not zero and such file by offset is
 *          invalid, the file is expanded accordingly to make it valid.
 * 
 * @param ip     File to use
 * @param off    File byte offset.
 * @param create Create offset?
 * 
 * @returns Upon successful completion, the disk block number that is associated
 *          with the file byte offset is returned. Upon failure, #BLOCK_NULL is
 *          returned instead.
 * 
 * @note @p ip must be locked.
 */
PUBLIC block_t block_map(struct inode *ip, off_t off, int create)
{
	block_t phys;       /* Physical block number.    */
	block_t logic;      /* Logical block number.     */
	struct buffer *buf; /* Underlying buffer.        */
	unsigned tmp;       /* Logical block number tmp. */
	
	logic = off/BLOCK_SIZE;
	
	/* File offset too big. */
	if (off >= ip->sb->max_size)
	{
		curr_proc->errno = -EFBIG;
		return (BLOCK_NULL);
	}
	
	/* 
	 * Create blocks that are
	 * in a valid offset.
	 */
	if (off < ip->size)
		create = 1;
	
	/* Direct block. */
	if (logic < NR_ZONES_DIRECT)
	{
		/* Create direct block. */
		if (ip->blocks[logic] == BLOCK_NULL && create)
		{
			superblock_lock(ip->sb);
			phys = block_alloc(ip->sb);
			superblock_unlock(ip->sb);
			
			if (phys != BLOCK_NULL)
			{
				ip->blocks[logic] = phys;
				inode_touch(ip);
			}
		}
		
		return (ip->blocks[logic]);
	}
	
	logic -= NR_ZONES_DIRECT;
	
	/* Single indirect block. */
	if (logic < NR_SINGLE)
	{
		/* Create single indirect block. */
		if (ip->blocks[ZONE_SINGLE] == BLOCK_NULL && create)
		{
			superblock_lock(ip->sb);
			phys = block_alloc(ip->sb);
			superblock_unlock(ip->sb);
			
			if (phys != BLOCK_NULL)
			{
				ip->blocks[ZONE_SINGLE] = phys;
				inode_touch(ip);
			}
		}
		
		/* We cannot go any further. */
		if ((phys = ip->blocks[ZONE_SINGLE]) == BLOCK_NULL)
			return (BLOCK_NULL);
	
		buf = bread(ip->dev, phys);
		
		/* Create direct block. */
		if (((block_t *)buffer_data(buf))[logic] == BLOCK_NULL && create)
		{
			superblock_lock(ip->sb);
			phys = block_alloc(ip->sb);
			superblock_unlock(ip->sb);
			
			if (phys != BLOCK_NULL)
			{
				((block_t *)buffer_data(buf))[logic] = phys;
				buffer_dirty(buf, 1);
				inode_touch(ip);
			}
		}
		
		brelse(buf);
		
		return (((block_t *)buffer_data(buf))[logic]);
	}
	
	logic = off - REMAINING_OFFSET;
	
	/* Double indirect block. */
	tmp = logic / BLOCK_SIZE;
	if (tmp < NR_DOUBLE)
	{
		size_t logicSingle = logic / (NR_SINGLE * BLOCK_SIZE);
		size_t logicDouble = logic / BLOCK_SIZE;
		
		/* Create single, double and/or direct block. */
		if ( (phys = create_direct_block(ip,ZONE_DOUBLE,create)) != BLOCK_NULL)
		{
			buf = bread(ip->dev, phys);
			if ( (phys = create_indirect_block(buf,ip,logicSingle,create)) 
				!= BLOCK_NULL)
			{
				buf = bread(ip->dev, phys);
				if ( (phys = create_indirect_block(buf,ip,logicDouble,create)) 
					!= BLOCK_NULL)
					return (phys);
				else
					return (BLOCK_NULL);
			}
			else
				return (BLOCK_NULL);
		}
		else
			return (BLOCK_NULL);
	}

	/* Triple indirect zone. */
	kpanic("triple indirect zones not supported");
	
	return (BLOCK_NULL);
}