Exemplo n.º 1
0
/*
 * Create a new filesystem object and hand back its vnode.
 */
static
int
sfs_makeobj(struct sfs_fs *sfs, int type, struct sfs_vnode **ret)
{
	u_int32_t ino;
	int result;

	/*
	 * First, get an inode. (Each inode is a block, and the inode 
	 * number is the block number, so just get a block.)
	 */

	result = sfs_balloc(sfs, &ino);
	if (result) {
		return result;
	}

	/*
	 * Now load a vnode for it.
	 */

	return sfs_loadvnode(sfs, ino, type, ret);
}
Exemplo n.º 2
0
/*
 * Look up the disk block number (from 0 up to the number of blocks on
 * the disk) given a file and the logical block number within that
 * file. If DOALLOC is set, and no such block exists, one will be
 * allocated.
 */
static
int
sfs_bmap(struct sfs_vnode *sv, u_int32_t fileblock, int doalloc,
	    u_int32_t *diskblock)
{
	/*
	 * I/O buffer for handling indirect blocks.
	 *
	 * Note: in real life (and when you've done the fs assignment)
	 * you would get space from the disk buffer cache for this,
	 * not use a static area.
	 */
	static u_int32_t idbuf[SFS_DBPERIDB];

	struct sfs_fs *sfs = sv->sv_v.vn_fs->fs_data;
	u_int32_t block;
	u_int32_t idblock;
	u_int32_t idnum, idoff;
	int result;

	assert(sizeof(idbuf)==SFS_BLOCKSIZE);

	/*
	 * If the block we want is one of the direct blocks...
	 */
	if (fileblock < SFS_NDIRECT) {
		/*
		 * Get the block number
		 */
		block = sv->sv_i.sfi_direct[fileblock];

		/*
		 * Do we need to allocate?
		 */
		if (block==0 && doalloc) {
			result = sfs_balloc(sfs, &block);
			if (result) {
				return result;
			}

			/* Remember what we allocated; mark inode dirty */
			sv->sv_i.sfi_direct[fileblock] = block;
			sv->sv_dirty = 1;
		}

		/*
		 * Hand back the block
		 */
		if (block != 0 && !sfs_bused(sfs, block)) {
			panic("sfs: Data block %u (block %u of file %u) "
			      "marked free\n", block, fileblock, sv->sv_ino);
		}
		*diskblock = block;
		return 0;
	}

	/*
	 * It's not a direct block; it must be in the indirect block.
	 * Subtract off the number of direct blocks, so FILEBLOCK is
	 * now the offset into the indirect block space.
	 */

	fileblock -= SFS_NDIRECT;

	/* Get the indirect block number and offset w/i that indirect block */
	idnum = fileblock / SFS_DBPERIDB;
	idoff = fileblock % SFS_DBPERIDB;

	/*
	 * We only have one indirect block. If the offset we were asked for
	 * is too large, we can't handle it, so fail.
	 */
	if (idnum > 0) {
		return EINVAL;
	}

	/* 
	 * Probably need to synchronize the stuff below. Maybe not though
	 * since no two threads can be writing to the same file at the same
	 * time (this is protected with file locks in the VFS layer).
	 */

	/* Get the disk block number of the indirect block. */
	idblock = sv->sv_i.sfi_indirect;

	if (idblock==0 && !doalloc) {
		/*
		 * There's no indirect block allocated. We weren't
		 * asked to allocate anything, so pretend the indirect
		 * block was filled with all zeros.
		 */
		*diskblock = 0;
		return 0;
	}
	else if (idblock==0) {
		/*
		 * There's no indirect block allocated, but we need to
		 * allocate a block whose number needs to be stored in
		 * the indirect block. Thus, we need to allocate an
		 * indirect block.
		 */
		result = sfs_balloc(sfs, &idblock);
		if (result) {
			return result;
		}

		/* Remember the block we just allocated */
		sv->sv_i.sfi_indirect = idblock;

		/* Mark the inode dirty */
		sv->sv_dirty = 1;

		/* Clear the indirect block buffer */
		bzero(idbuf, sizeof(idbuf));
	}
	else {
		/*
		 * We already have an indirect block allocated; load it.
		 */
		result = sfs_rblock(sfs, idbuf, idblock);
		if (result) {
			return result;
		}
	}

	/* Get the block out of the indirect block buffer */
	block = idbuf[idoff];

	/* If there's no block there, allocate one */
	if (block==0 && doalloc) {
		result = sfs_balloc(sfs, &block);
		if (result) {
			return result;
		}

		/* Remember the block we allocated */
		idbuf[idoff] = block;

		/* The indirect block is now dirty; write it back */
		result = sfs_wblock(sfs, idbuf, idblock);
		if (result) {
			return result;
		}
	}

	/* Hand back the result and return. */
	if (block != 0 && !sfs_bused(sfs, block)) {
		panic("sfs: Data block %u (block %u of file %u) marked free\n",
		      block, fileblock, sv->sv_ino);
	}
	*diskblock = block;
	return 0;
}
Exemplo n.º 3
0
/*
 * Look up the disk block number (from 0 up to the number of blocks on
 * the disk) given a file and the logical block number within that
 * file. If DOALLOC is set, and no such block exists, one will be
 * allocated.
 */
static
int
sfs_bmap(struct sfs_vnode *sv, u_int32_t fileblock, int doalloc,
	    u_int32_t *diskblock)
{
	/*
	 * I/O buffer for handling indirect blocks.
	 *
	 * Note: in real life (and when you've done the fs assignment)
	 * you would get space from the disk buffer cache for this,
	 * not use a static area.
	 */
	static u_int32_t blockbuf[SFS_DBPERIDB];		// I/O blockbuffer
	struct sfs_fs *sfs = sv->sv_v.vn_fs->fs_data;
	u_int32_t block;								// used to store datablock
	u_int32_t idblock;								// stores indirect/double id/triple id blocks (not datablocks)
	u_int32_t idnum;
	int result;
	u_int32_t idblevel = 0;							// indirect block level (1=indirect,2=double,3=triple)
	u_int32_t blockno;								// the blocknumber to load (offset into indirect space)


	/*
	 * **********************************************************************
	 * Two helpfunctions for assignment 3 goes here. I keep this internal
	 * to keep things a bit simpler for this assignment. Otherwise I would
	 * have made this as external functions equal to bfree, balloc etc...
	 * **********************************************************************
	 */


	/*
	 * loadbuffer: load "block" into the block buffer "blockbuf"
	 * if level == 0 we also update inode indirect/doub.ind./trip.ind pointers
	 * This function should only be called if "doalloc" is set
	 */
	int loadbuffer(u_int32_t block, u_int32_t level){
		if (block==0) {
			/*
			 * There's no indirect block allocated, but we need to
			 * allocate a block whose number needs to be stored in
			 * the indirect block. Thus, we need to allocate an
			 * indirect block.
			 */
			result = sfs_balloc(sfs, &block);
			if (result)
				return result;

			/* keep track of the number of blocks */
			sv->sv_i.sfi_blocks++;
			
			/* Remember the block we just allocated */
			if (level == 0){
				if (idblevel==1)
					sv->sv_i.sfi_indirect = block;
				else if (idblevel==2)
					sv->sv_i.sfi_doubleindirect = block;
				else if (idblevel==3)
					sv->sv_i.sfi_tripleindirect = block;
			}
			/* update global idblock */
			idblock = block;
			
			/* Mark the inode dirty */
			sv->sv_dirty = 1;
	
			/* Clear the block buffer */
			bzero(blockbuf, sizeof(blockbuf));
		}
		else {
			/*
			 * We already have an indirect block allocated; load it.
			 */
			result = sfs_rblock(sfs, blockbuf, block);
			if (result)
				return result;
		}
		return 0;
	}

	/*
	 * get_block: the function fetches a block out of
	 * the buffer and into "block", it might allocate a new
	 * if block is empty
	 */
	int get_block(u_int32_t blockno){

		/* get block from buffer */
		block = blockbuf[blockno];

		/* If there's no block there, allocate one */
		if (block==0 && doalloc) {

			result = sfs_balloc(sfs, &block);
			if (result) {
				return result;
			}
	
			/* increase blockcounter */
			sv->sv_i.sfi_blocks++;
	
			/* Remember the block we allocated */
			blockbuf[blockno] = block;

			/* The indirect block is now dirty; write it back */
			result = sfs_wblock(sfs, blockbuf, idblock);
			if (result)
				return result;
		}
		return 0;
	}