Ejemplo n.º 1
0
void ext2_free_block(struct nas *nas, uint32_t bit_returned) {
	/* Return a block by turning off its bitmap bit. */
	int group;		/* group number of bit_returned */
	int bit;		/* bit_returned number within its group */
	struct ext2_gd *gd;
	struct ext2_file_info *fi;
	struct ext2_fs_info *fsi;

	fi = nas->fi->privdata;
	fsi = nas->fs->fsi;

	if (bit_returned >= fsi->e2sb.s_blocks_count ||
		bit_returned < fsi->e2sb.s_first_data_block) {
		return;
	}

	/* At first search group, to which bit_returned belongs to
	* and figure out in what word bit is stored.
	*/
	group = (bit_returned - fsi->e2sb.s_first_data_block) / fsi->e2sb.s_blocks_per_group;
	bit = (bit_returned - fsi->e2sb.s_first_data_block) % fsi->e2sb.s_blocks_per_group;

	gd = ext2_get_group_desc(group, fsi);

	/* We might be buggy (No way! :P), so check if we deallocate
	* data block, but not control (system) block.
	* This should never happen.
	*/
	if (bit_returned == gd->inode_bitmap || bit_returned == gd->block_bitmap
		|| (bit_returned >= gd->inode_table
		&& bit_returned < (gd->inode_table + fsi->s_itb_per_group))) {
		return;
	}

	ext2_read_sector(nas, (char *) fi->f_buf, 1, gd->block_bitmap);
	if (ext2_unsetbit(b_bitmap(fi->f_buf), bit)) {
		return; /*Tried to free unused block*/
	}
	ext2_write_sector(nas, (char *) fi->f_buf, 1, gd->block_bitmap);


	fsi->e2sb.s_free_blocks_count++;
	ext2_write_sblock(nas);
	gd->free_blocks_count++;
	ext2_write_gdblock(nas);

	if (bit_returned < fsi->s_bsearch) {
		fsi->s_bsearch = bit_returned;
	}
}
Ejemplo n.º 2
0
static int ext3fs_mount(void *dev, void *dir) {
	struct fs_driver *drv;
	struct ext2fs_dinode *dip = sysmalloc(sizeof(struct ext2fs_dinode));
	char buf[SECTOR_SIZE * 2];
	struct ext2_fs_info *fsi;
	int inode_sector, ret, rsize;
	struct node *dev_node = dev;
	struct nas *dir_nas = ((struct node *)dir)->nas;
	journal_t *jp = NULL;
	ext3_journal_specific_t *ext3_spec;
	journal_fs_specific_t spec = {
			.bmap = ext3_journal_bmap,
			.commit = ext3_journal_commit,
			.update = ext3_journal_update,
			.trans_freespace = ext3_journal_trans_freespace
	};

	if (NULL == (drv = fs_driver_find_drv(EXT2_NAME))) {
		return -1;
	}

	if ((ret = drv->fsop->mount(dev, dir)) < 0) {
		return ret;
	}

	if (NULL == (ext3_spec = objalloc(&ext3_journal_cache))) {
		return -1;
	}

	spec.data = ext3_spec;

	if (NULL == (jp = journal_create(&spec))) {
		objfree(&ext3_journal_cache, ext3_spec);
		return -1;
	}

	/* Getting first block for inode number EXT3_JOURNAL_SUPERBLOCK_INODE */
	dir_nas = ((struct node *)dir)->nas;
	fsi = dir_nas->fs->fsi;

	inode_sector = ino_to_fsba(fsi, EXT3_JOURNAL_SUPERBLOCK_INODE);

	rsize = ext2_read_sector(dir_nas, buf, 1, inode_sector);
	if (rsize * fsi->s_block_size != fsi->s_block_size) {
		return -EIO;
	}

	/* set pointer to inode struct in read buffer */
	memcpy(dip, (buf
			+ EXT2_DINODE_SIZE(fsi) * ino_to_fsbo(fsi, EXT3_JOURNAL_SUPERBLOCK_INODE)),
			sizeof(struct ext2fs_dinode));

	/* XXX Hack to use ext2 functions */
	dir_nas->fs->drv = &ext3fs_driver;
	ext3_spec->ext3_journal_inode = dip;
	if (0 > ext3_journal_load(jp, (struct block_dev *) dev_node->nas->fi->privdata,
			fsbtodb(fsi, dip->i_block[0]))) {
		return -EIO;
	}
	/*
	 * FIXME Now journal supports block size only equal to filesystem block size
	 * It is not critical but not flexible enough
	 */
	assert(jp->j_blocksize == fsi->s_block_size);
	fsi->journal = jp;

	return 0;
}
Ejemplo n.º 3
0
static uint32_t ext2_alloc_block_bit(struct nas *nas, uint32_t goal) { /* try to allocate near this block */
	uint32_t block;	/* allocated block */
	int word;			/* word in block bitmap */
	uint32_t bit;
	int group;
	char update_bsearch = 0;
	int i;
	struct ext2_gd *gd;

	struct ext2_file_info *fi;
	struct ext2_fs_info *fsi;

	fi = nas->fi->privdata;
	fsi = nas->fs->fsi;

	block = NO_BLOCK;
	bit = -1;

	if (goal >= fsi->e2sb.s_blocks_count ||
		(goal < fsi->e2sb.s_first_data_block && goal != 0)) {
		goal = fsi->s_bsearch;
	}

	if (goal <= fsi->s_bsearch) {
		/* No reason to search in a place with no free blocks */
		goal = fsi->s_bsearch;
		update_bsearch = DIRTY;
	}

	/* Figure out where to start the bit search. */
	word = ((goal - fsi->e2sb.s_first_data_block) %
			fsi->e2sb.s_blocks_per_group) / FS_BITCHUNK_BITS;

	/* Try to allocate block at any group starting from the goal's group.
	* First time goal's group is checked from the word=goal, after all
	* groups checked, it's checked again from word=0, that's why "i <=".
	*/
	group = (goal - fsi->e2sb.s_first_data_block) / fsi->e2sb.s_blocks_per_group;
	for (i = 0; i <= fsi->s_groups_count; i++, group++) {

		if (group >= fsi->s_groups_count) {
			group = 0;
		}
		gd = ext2_get_group_desc(group, fsi);
		if (gd->free_blocks_count == 0) {
			word = 0;
			continue;
		}

		ext2_read_sector(nas, fi->f_buf, 1, gd->block_bitmap);

		bit = ext2_setbit(b_bitmap(fi->f_buf), fsi->e2sb.s_blocks_per_group, word);
		if (-1 == bit) {
			if (0 == word) {
				/* allocator failed to allocate a bit in bitmap	with free bits.*/
				return 0;
			} else {
				word = 0;
				continue;
			}
		}

		block = fsi->e2sb.s_first_data_block + group * fsi->e2sb.s_blocks_per_group + bit;
		if (ext2_check_block_number(block, fsi, gd)) {
			return 0;
		}

		ext2_write_sector(nas, fi->f_buf, 1, gd->block_bitmap);

		fsi->e2sb.s_free_blocks_count--;
		ext2_write_sblock(nas);
		gd->free_blocks_count--;
		ext2_write_gdblock(nas);

		if (update_bsearch && block != -1 && block != NO_BLOCK) {
			/* We searched from the beginning, update bsearch. */
			fsi->s_bsearch = block;
		}

		return block;
	}

	return block;
}