예제 #1
0
static int find_group_other(struct super_block *sb, int parent_group)
{
	int ngroups = sb->u.ext2_sb.s_groups_count;
	struct ext2_group_desc *desc;
	struct buffer_head *bh;
	int group, i;

	/*
	 * Try to place the inode in its parent directory
	 */
	group = parent_group;
	desc = ext2_get_group_desc (sb, group, &bh);
	if (desc && le16_to_cpu(desc->bg_free_inodes_count))
		goto found;

	/*
	 * Use a quadratic hash to find a group with a
	 * free inode
	 */
	for (i = 1; i < ngroups; i <<= 1) {
		group += i;
		if (group >= ngroups)
			group -= ngroups;
		desc = ext2_get_group_desc (sb, group, &bh);
		if (desc && le16_to_cpu(desc->bg_free_inodes_count))
			goto found;
	}

	/*
	 * That failed: try linear search for a free inode
	 */
	group = parent_group + 1;
	for (i = 2; i < ngroups; i++) {
		if (++group >= ngroups)
			group = 0;
		desc = ext2_get_group_desc (sb, group, &bh);
		if (desc && le16_to_cpu(desc->bg_free_inodes_count))
			goto found;
	}

	return -1;

found:
	desc->bg_free_inodes_count =
		cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) - 1);
	mark_buffer_dirty(bh);
	return group;
}
예제 #2
0
파일: balloc.c 프로젝트: huangrui/Thunix
/* alloc a new block */
int ext2_alloc_block ( unsigned int goal)
{
        unsigned int block;
        unsigned int block_group;
        unsigned int bit;
        struct ext2_group_desc *desc;
        struct ext2_sb_info * sbi = EXT2_SBI();
        void *bitmap;

        block_group = ext2_get_group_num (goal, BLOCK);
        bit = ext2_get_group_offset (goal, BLOCK);
        
        bitmap = ext2_read_block_bitmap (block_group);
        block = ext2_grab_block (bitmap, bit);

        if ( !block)
                ext2_error ("no free blocks any more");

        desc = ext2_get_group_desc (block_group);
        desc->bg_free_blocks_count --;
        sbi->s_free_blocks_count --;
        ext2_set_bit (bitmap, block);

        return block;
}
예제 #3
0
static struct buffer_head *
read_block_bitmap(struct super_block *sb, unsigned int block_group)
{
	struct ext2_group_desc * desc;
	struct buffer_head * bh = NULL;
	ext2_fsblk_t bitmap_blk;

	desc = ext2_get_group_desc(sb, block_group, NULL);
	if (!desc)
		return NULL;
	bitmap_blk = le32_to_cpu(desc->bg_block_bitmap);
	bh = sb_getblk(sb, bitmap_blk);
	if (unlikely(!bh)) {
		ext2_error(sb, __func__,
			    "Cannot read block bitmap - "
			    "block_group = %d, block_bitmap = %u",
			    block_group, le32_to_cpu(desc->bg_block_bitmap));
		return NULL;
	}
	if (likely(bh_uptodate_or_lock(bh)))
		return bh;

	if (bh_submit_read(bh) < 0) {
		brelse(bh);
		ext2_error(sb, __func__,
			    "Cannot read block bitmap - "
			    "block_group = %d, block_bitmap = %u",
			    block_group, le32_to_cpu(desc->bg_block_bitmap));
		return NULL;
	}

	ext2_valid_block_bitmap(sb, desc, block_group, bh);
	return bh;
}
예제 #4
0
static int find_group_dir(struct super_block *sb, int parent_group)
{
	struct ext2_super_block * es = sb->u.ext2_sb.s_es;
	int ngroups = sb->u.ext2_sb.s_groups_count;
	int avefreei = le32_to_cpu(es->s_free_inodes_count) / ngroups;
	struct ext2_group_desc *desc, *best_desc = NULL;
	struct buffer_head *bh, *best_bh = NULL;
	int group, best_group = -1;

	for (group = 0; group < ngroups; group++) {
		desc = ext2_get_group_desc (sb, group, &bh);
		if (!desc || !desc->bg_free_inodes_count)
			continue;
		if (le16_to_cpu(desc->bg_free_inodes_count) < avefreei)
			continue;
		if (!best_desc || 
		    (le16_to_cpu(desc->bg_free_blocks_count) >
		     le16_to_cpu(best_desc->bg_free_blocks_count))) {
			best_group = group;
			best_desc = desc;
			best_bh = bh;
		}
	}
	if (!best_desc)
		return -1;
	best_desc->bg_free_inodes_count =
		cpu_to_le16(le16_to_cpu(best_desc->bg_free_inodes_count) - 1);
	best_desc->bg_used_dirs_count =
		cpu_to_le16(le16_to_cpu(best_desc->bg_used_dirs_count) + 1);
	mark_buffer_dirty(best_bh);
	return best_group;
}
예제 #5
0
/*
 * Read the inode allocation bitmap for a given block_group, reading
 * into the specified slot in the superblock's bitmap cache.
 *
 * Return >=0 on success or a -ve error code.
 */
static int read_inode_bitmap (struct super_block * sb,
			       unsigned long block_group,
			       unsigned int bitmap_nr)
{
	struct ext2_group_desc * gdp;
	struct buffer_head * bh = NULL;
	int retval = 0;

	gdp = ext2_get_group_desc (sb, block_group, NULL);
	if (!gdp) {
		retval = -EIO;
		goto error_out;
	}
	bh = bread (sb->s_dev, le32_to_cpu(gdp->bg_inode_bitmap), sb->s_blocksize);
	if (!bh) {
		ext2_error (sb, "read_inode_bitmap",
			    "Cannot read inode bitmap - "
			    "block_group = %lu, inode_bitmap = %lu",
			    block_group, (unsigned long) gdp->bg_inode_bitmap);
		retval = -EIO;
	}
	/*
	 * On IO error, just leave a zero in the superblock's block pointer for
	 * this group.  The IO will be retried next time.
	 */
error_out:
	sb->u.ext2_sb.s_inode_bitmap_number[bitmap_nr] = block_group;
	sb->u.ext2_sb.s_inode_bitmap[bitmap_nr] = bh;
	return retval;
}
예제 #6
0
unsigned long ext2_count_free_inodes (struct super_block * sb)
{
#ifdef EXT2FS_DEBUG
	struct ext2_super_block * es;
	unsigned long desc_count = 0, bitmap_count = 0;
	int i;

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
		struct ext2_group_desc *desc = ext2_get_group_desc (sb, i, NULL);
		struct buffer_head *bh;
		unsigned x;

		if (!desc)
			continue;
		desc_count += le16_to_cpu(desc->bg_free_inodes_count);
		bh = load_inode_bitmap (sb, i);
		if (IS_ERR(bh))
			continue;

		x = ext2_count_free (bh, EXT2_INODES_PER_GROUP(sb) / 8);
		printk ("group %d: stored = %d, counted = %lu\n",
			i, le16_to_cpu(desc->bg_free_inodes_count), x);
		bitmap_count += x;
	}
	printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
		le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
	unlock_super (sb);
	return desc_count;
#else
	return le32_to_cpu(sb->u.ext2_sb.s_es->s_free_inodes_count);
#endif
}
예제 #7
0
/* Called at mount-time, super-block is locked */
void ext2_check_inodes_bitmap (struct super_block * sb)
{
	struct ext2_super_block * es = sb->u.ext2_sb.s_es;
	unsigned long desc_count = 0, bitmap_count = 0;
	int i;

	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
		struct ext2_group_desc *desc = ext2_get_group_desc(sb, i, NULL);
		struct buffer_head *bh;
		unsigned x;

		if (!desc)
			continue;
		desc_count += le16_to_cpu(desc->bg_free_inodes_count);
		bh = load_inode_bitmap (sb, i);
		if (IS_ERR(bh))
			continue;
		
		x = ext2_count_free (bh, EXT2_INODES_PER_GROUP(sb) / 8);
		if (le16_to_cpu(desc->bg_free_inodes_count) != x)
			ext2_error (sb, "ext2_check_inodes_bitmap",
				    "Wrong free inodes count in group %d, "
				    "stored = %d, counted = %lu", i,
				    le16_to_cpu(desc->bg_free_inodes_count), x);
		bitmap_count += x;
	}
	if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count)
		ext2_error (sb, "ext2_check_inodes_bitmap",
			    "Wrong free inodes count in super block, "
			    "stored = %lu, counted = %lu",
			    (unsigned long)le32_to_cpu(es->s_free_inodes_count),
			    bitmap_count);
}
예제 #8
0
파일: ext2_utils.c 프로젝트: 3a9LL/panda
int ext2_get_inode(ext2_VOLUME* volume,
		    unsigned int ino, struct ext2_inode *inode)
{
	struct ext2_group_desc desc;
	unsigned int block;
	unsigned int group_id;
	unsigned int offset;
	struct ext2_inode *le_inode;
	int i;

	ino--;

	group_id = ino / EXT2_INODES_PER_GROUP(volume->super);
	ext2_get_group_desc(volume, group_id, &desc);

	ino %= EXT2_INODES_PER_GROUP(volume->super);

	block = desc.bg_inode_table;
	block += ino / (EXT2_BLOCK_SIZE(volume->super) /
			EXT2_INODE_SIZE(volume->super));
	ext2_read_block(volume, block);

	offset = ino % (EXT2_BLOCK_SIZE(volume->super) /
			EXT2_INODE_SIZE(volume->super));
	offset *= EXT2_INODE_SIZE(volume->super);

	le_inode = (struct ext2_inode *)(volume->buffer + offset);

	inode->i_mode = __le16_to_cpu(le_inode->i_mode);
	inode->i_uid = __le16_to_cpu(le_inode->i_uid);
	inode->i_size = __le32_to_cpu(le_inode->i_size);
	inode->i_atime = __le32_to_cpu(le_inode->i_atime);
	inode->i_ctime = __le32_to_cpu(le_inode->i_ctime);
	inode->i_mtime = __le32_to_cpu(le_inode->i_mtime);
	inode->i_dtime = __le32_to_cpu(le_inode->i_dtime);
	inode->i_gid = __le16_to_cpu(le_inode->i_gid);
	inode->i_links_count = __le16_to_cpu(le_inode->i_links_count);
	inode->i_blocks = __le32_to_cpu(le_inode->i_blocks);
	inode->i_flags = __le32_to_cpu(le_inode->i_flags);
	if (S_ISLNK(inode->i_mode)) {
		memcpy(inode->i_block, le_inode->i_block, EXT2_N_BLOCKS * 4);
	} else {
		for (i = 0; i < EXT2_N_BLOCKS; i++)
			inode->i_block[i] = __le32_to_cpu(le_inode->i_block[i]);
        }
	inode->i_generation = __le32_to_cpu(le_inode->i_generation);
	inode->i_file_acl = __le32_to_cpu(le_inode->i_file_acl);
	inode->i_dir_acl = __le32_to_cpu(le_inode->i_dir_acl);
	inode->i_faddr = __le32_to_cpu(le_inode->i_faddr);
	inode->osd2.linux2.l_i_frag = le_inode->osd2.linux2.l_i_frag;
	inode->osd2.linux2.l_i_fsize = le_inode->osd2.linux2.l_i_fsize;
	inode->osd2.linux2.l_i_uid_high =
			__le16_to_cpu(le_inode->osd2.linux2.l_i_uid_high);
	inode->osd2.linux2.l_i_gid_high =
			__le16_to_cpu(le_inode->osd2.linux2.l_i_gid_high);
	return 0;
}
예제 #9
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;
	}
}
예제 #10
0
static int ext2_check_descriptors(struct super_block *sb)
{
	int i;
	struct ext2_sb_info *sbi = EXT2_SB(sb);

	ext2_debug ("Checking group descriptors");

	for (i = 0; i < sbi->s_groups_count; i++) {
		struct ext2_group_desc *gdp = ext2_get_group_desc(sb, i, NULL);
		ext2_fsblk_t first_block = ext2_group_first_block_no(sb, i);
		ext2_fsblk_t last_block;

		if (i == sbi->s_groups_count - 1)
			last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1;
		else
			last_block = first_block +
				(EXT2_BLOCKS_PER_GROUP(sb) - 1);

		if (le32_to_cpu(gdp->bg_block_bitmap) < first_block ||
		    le32_to_cpu(gdp->bg_block_bitmap) > last_block)
		{
			ext2_error (sb, "ext2_check_descriptors",
				    "Block bitmap for group %d"
				    " not in group (block %lu)!",
				    i, (unsigned long) le32_to_cpu(gdp->bg_block_bitmap));
			return 0;
		}
		if (le32_to_cpu(gdp->bg_inode_bitmap) < first_block ||
		    le32_to_cpu(gdp->bg_inode_bitmap) > last_block)
		{
			ext2_error (sb, "ext2_check_descriptors",
				    "Inode bitmap for group %d"
				    " not in group (block %lu)!",
				    i, (unsigned long) le32_to_cpu(gdp->bg_inode_bitmap));
			return 0;
		}
		if (le32_to_cpu(gdp->bg_inode_table) < first_block ||
		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group - 1 >
		    last_block)
		{
			ext2_error (sb, "ext2_check_descriptors",
				    "Inode table for group %d"
				    " not in group (block %lu)!",
				    i, (unsigned long) le32_to_cpu(gdp->bg_inode_table));
			return 0;
		}
	}
	return 1;
}
예제 #11
0
파일: balloc.c 프로젝트: huangrui/Thunix
/*
 * Read the bitmap for a given block_group, reading into the specified 
 * slot in the superblock's bitmap cache.
 *
 */
void * ext2_read_block_bitmap(unsigned int block_group)
{
	struct ext2_group_desc * desc;
	void * bitmap = NULL;
	
	desc = ext2_get_group_desc (block_group);
	if (!desc)
		goto error_out;
	bitmap = (void *)(EXT2_BITMAP_BUFFER + (block_group << 1) * EXT2_BLOCK_SIZE);
	if (!bitmap)
		ext2_error ("read_block_bitmap",
			    "Cannot read block bitmap - "
			    "block_group = %d, block_bitmap = %u",
			    block_group, desc->bg_block_bitmap);
error_out:
	return bitmap;
}
예제 #12
0
/*
 * Read the inode allocation bitmap for a given block_group, reading
 * into the specified slot in the superblock's bitmap cache.
 *
 * Return buffer_head of bitmap on success or NULL.
 */
static struct buffer_head *read_inode_bitmap (struct super_block * sb,
					       unsigned long block_group)
{
	struct ext2_group_desc *desc;
	struct buffer_head *bh = NULL;

	desc = ext2_get_group_desc(sb, block_group, NULL);
	if (!desc)
		goto error_out;

	bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));
	if (!bh)
		ext2_error (sb, "read_inode_bitmap",
			    "Cannot read inode bitmap - "
			    "block_group = %lu, inode_bitmap = %lu",
			    block_group, (unsigned long) desc->bg_inode_bitmap);
error_out:
	return bh;
}
예제 #13
0
파일: balloc.c 프로젝트: huangrui/Thunix
/* free the goal block, clean it */
void ext2_free_block(unsigned int block)
{
	unsigned int block_group;
	unsigned int bit;
	struct ext2_group_desc *desc;
        struct ext2_sb_info * sbi = EXT2_SBI();
	void * bitmap;

	block_group = ext2_get_group_num (block, BLOCK);
	bit = ext2_get_group_offset (block, BLOCK);

	desc = ext2_get_group_desc (block_group);
	bitmap = ext2_read_block_bitmap (block_group);

	
	if ( !ext2_clear_bit(bitmap, bit) ) 
		ext2_error("bit %d (%d) alread cleard", bit, block_group);

	desc->bg_free_blocks_count ++;
	sbi->s_free_blocks_count ++;
}
예제 #14
0
void ext2_check_inodes_bitmap (struct super_block * sb)
{
	struct ext2_super_block * es;
	unsigned long desc_count, bitmap_count, x;
	int bitmap_nr;
	struct ext2_group_desc * gdp;
	int i;

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
	desc_count = 0;
	bitmap_count = 0;
	gdp = NULL;
	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
		gdp = ext2_get_group_desc (sb, i, NULL);
		if (!gdp)
			continue;
		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
		bitmap_nr = load_inode_bitmap (sb, i);
		if (bitmap_nr < 0)
			continue;
		
		x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
				     EXT2_INODES_PER_GROUP(sb) / 8);
		if (le16_to_cpu(gdp->bg_free_inodes_count) != x)
			ext2_error (sb, "ext2_check_inodes_bitmap",
				    "Wrong free inodes count in group %d, "
				    "stored = %d, counted = %lu", i,
				    le16_to_cpu(gdp->bg_free_inodes_count), x);
		bitmap_count += x;
	}
	if (le32_to_cpu(es->s_free_inodes_count) != bitmap_count)
		ext2_error (sb, "ext2_check_inodes_bitmap",
			    "Wrong free inodes count in super block, "
			    "stored = %lu, counted = %lu",
			    (unsigned long) le32_to_cpu(es->s_free_inodes_count),
			    bitmap_count);
	unlock_super (sb);
}
예제 #15
0
unsigned long ext2_count_free_inodes (struct super_block * sb)
{
#ifdef EXT2FS_DEBUG
	struct ext2_super_block * es;
	unsigned long desc_count, bitmap_count, x;
	int bitmap_nr;
	struct ext2_group_desc * gdp;
	int i;

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
	desc_count = 0;
	bitmap_count = 0;
	gdp = NULL;
	for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) {
		gdp = ext2_get_group_desc (sb, i, NULL);
		if (!gdp)
			continue;
		desc_count += le16_to_cpu(gdp->bg_free_inodes_count);
		bitmap_nr = load_inode_bitmap (sb, i);
		if (bitmap_nr < 0)
			continue;

		x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr],
				     EXT2_INODES_PER_GROUP(sb) / 8);
		printk ("group %d: stored = %d, counted = %lu\n",
			i, le16_to_cpu(gdp->bg_free_inodes_count), x);
		bitmap_count += x;
	}
	printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",
		le32_to_cpu(es->s_free_inodes_count), desc_count, bitmap_count);
	unlock_super (sb);
	return desc_count;
#else
	return le32_to_cpu(sb->u.ext2_sb.s_es->s_free_inodes_count);
#endif
}
예제 #16
0
static const struct ext2_inode *
ext2_get_inode(struct fs_info *fs, int inr)
{
    const struct ext2_group_desc *desc;
    const char *data;
    uint32_t inode_group, inode_offset;
    uint32_t block_num, block_off;

    inr--;
    inode_group  = inr / EXT2_INODES_PER_GROUP(fs);
    inode_offset = inr % EXT2_INODES_PER_GROUP(fs);
    desc = ext2_get_group_desc(fs, inode_group);
    if (!desc)
	return NULL;

    block_num = desc->bg_inode_table +
	inode_offset / EXT2_INODES_PER_BLOCK(fs);
    block_off = inode_offset % EXT2_INODES_PER_BLOCK(fs);

    data = get_cache(fs->fs_dev, block_num);

    return (const struct ext2_inode *)
	(data + block_off * EXT2_SB(fs)->s_inode_size);
}
예제 #17
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;
}
예제 #18
0
/*
 * NOTE! When we get the inode, we're the only people
 * that have access to it, and as such there are no
 * race conditions we have to worry about. The inode
 * is not on the hash-lists, and it cannot be reached
 * through the filesystem because the directory entry
 * has been deleted earlier.
 *
 * HOWEVER: we must make sure that we get no aliases,
 * which means that we have to call "clear_inode()"
 * _before_ we mark the inode not in use in the inode
 * bitmaps. Otherwise a newly created file might use
 * the same inode number (not actually the same pointer
 * though), and then we'd have two inodes sharing the
 * same inode number and space on the harddisk.
 */
void ext2_free_inode (struct inode * inode)
{
	struct super_block * sb = inode->i_sb;
	int is_directory;
	unsigned long ino;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	unsigned long block_group;
	unsigned long bit;
	int bitmap_nr;
	struct ext2_group_desc * gdp;
	struct ext2_super_block * es;

	if (!inode->i_dev) {
		printk ("ext2_free_inode: inode has no device\n");
		return;
	}
	if (inode->i_count > 1) {
		printk ("ext2_free_inode: inode has count=%d\n", inode->i_count);
		return;
	}
	if (inode->i_nlink) {
		printk ("ext2_free_inode: inode has nlink=%d\n",
			(int) inode->i_nlink);
		return;
	}
	if (!sb) {
		printk("ext2_free_inode: inode on nonexistent device\n");
		return;
	}

	ino = inode->i_ino;
	ext2_debug ("freeing inode %lu\n", ino);

	/*
	 * Note: we must free any quota before locking the superblock,
	 * as writing the quota to disk may need the lock as well.
	 */
	DQUOT_FREE_INODE(sb, inode);
	DQUOT_DROP(inode);

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
	if (ino < EXT2_FIRST_INO(sb) || 
	    ino > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "free_inode",
			    "reserved inode or nonexistent inode");
		goto error_return;
	}
	block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
	bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
	bitmap_nr = load_inode_bitmap (sb, block_group);
	if (bitmap_nr < 0)
		goto error_return;
	
	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];

	is_directory = S_ISDIR(inode->i_mode);

	/* Do this BEFORE marking the inode not in use */
	clear_inode (inode);

	/* Ok, now we can actually update the inode bitmaps.. */
	if (!ext2_clear_bit (bit, bh->b_data))
		ext2_warning (sb, "ext2_free_inode",
			      "bit already cleared for inode %lu", ino);
	else {
		gdp = ext2_get_group_desc (sb, block_group, &bh2);
		if (gdp) {
			gdp->bg_free_inodes_count =
				cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) + 1);
			if (is_directory)
				gdp->bg_used_dirs_count =
					cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) - 1);
		}
		mark_buffer_dirty(bh2, 1);
		es->s_free_inodes_count =
			cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
		mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
	}
	mark_buffer_dirty(bh, 1);
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}
	sb->s_dirt = 1;
error_return:
	unlock_super (sb);
}
예제 #19
0
/*
 * There are two policies for allocating an inode.  If the new inode is
 * a directory, then a forward search is made for a block group with both
 * free space and a low directory-to-inode ratio; if that fails, then of
 * the groups with above-average free space, that group with the fewest
 * directories already is chosen.
 *
 * For other inodes, search forward from the parent directory\'s block
 * group to find a free inode.
 */
struct inode * ext2_new_inode (const struct inode * dir, int mode, int * err)
{
	struct super_block * sb;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	int i, j, avefreei;
	struct inode * inode;
	int bitmap_nr;
	struct ext2_group_desc * gdp;
	struct ext2_group_desc * tmp;
	struct ext2_super_block * es;

	/* Cannot create files in a deleted directory */
	if (!dir || !dir->i_nlink) {
		*err = -EPERM;
		return NULL;
	}

	inode = get_empty_inode ();
	if (!inode) {
		*err = -ENOMEM;
		return NULL;
	}

	sb = dir->i_sb;
	inode->i_sb = sb;
	inode->i_flags = 0;
	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
repeat:
	gdp = NULL; i=0;
	
	*err = -ENOSPC;
	if (S_ISDIR(mode)) {
		avefreei = le32_to_cpu(es->s_free_inodes_count) /
			sb->u.ext2_sb.s_groups_count;
/* I am not yet convinced that this next bit is necessary.
		i = dir->u.ext2_i.i_block_group;
		for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
			tmp = ext2_get_group_desc (sb, i, &bh2);
			if (tmp &&
			    (le16_to_cpu(tmp->bg_used_dirs_count) << 8) < 
			     le16_to_cpu(tmp->bg_free_inodes_count)) {
				gdp = tmp;
				break;
			}
			else
			i = ++i % sb->u.ext2_sb.s_groups_count;
		}
*/
		if (!gdp) {
			for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) {
				tmp = ext2_get_group_desc (sb, j, &bh2);
				if (tmp &&
				    le16_to_cpu(tmp->bg_free_inodes_count) &&
				    le16_to_cpu(tmp->bg_free_inodes_count) >= avefreei) {
					if (!gdp || 
					    (le16_to_cpu(tmp->bg_free_blocks_count) >
					     le16_to_cpu(gdp->bg_free_blocks_count))) {
						i = j;
						gdp = tmp;
					}
				}
			}
		}
	}
	else 
	{
		/*
		 * Try to place the inode in its parent directory
		 */
		i = dir->u.ext2_i.i_block_group;
		tmp = ext2_get_group_desc (sb, i, &bh2);
		if (tmp && le16_to_cpu(tmp->bg_free_inodes_count))
			gdp = tmp;
		else
		{
			/*
			 * Use a quadratic hash to find a group with a
			 * free inode
			 */
			for (j = 1; j < sb->u.ext2_sb.s_groups_count; j <<= 1) {
				i += j;
				if (i >= sb->u.ext2_sb.s_groups_count)
					i -= sb->u.ext2_sb.s_groups_count;
				tmp = ext2_get_group_desc (sb, i, &bh2);
				if (tmp &&
				    le16_to_cpu(tmp->bg_free_inodes_count)) {
					gdp = tmp;
					break;
				}
			}
		}
		if (!gdp) {
			/*
			 * That failed: try linear search for a free inode
			 */
			i = dir->u.ext2_i.i_block_group + 1;
			for (j = 2; j < sb->u.ext2_sb.s_groups_count; j++) {
				if (++i >= sb->u.ext2_sb.s_groups_count)
					i = 0;
				tmp = ext2_get_group_desc (sb, i, &bh2);
				if (tmp &&
				    le16_to_cpu(tmp->bg_free_inodes_count)) {
					gdp = tmp;
					break;
				}
			}
		}
	}

	if (!gdp) {
		unlock_super (sb);
		iput(inode);
		return NULL;
	}
	bitmap_nr = load_inode_bitmap (sb, i);
	if (bitmap_nr < 0) {
		unlock_super (sb);
		iput(inode);
		*err = -EIO;
		return NULL;
	}

	bh = sb->u.ext2_sb.s_inode_bitmap[bitmap_nr];
	if ((j = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
				      EXT2_INODES_PER_GROUP(sb))) <
	    EXT2_INODES_PER_GROUP(sb)) {
		if (ext2_set_bit (j, bh->b_data)) {
			ext2_warning (sb, "ext2_new_inode",
				      "bit already set for inode %d", j);
			goto repeat;
		}
		mark_buffer_dirty(bh, 1);
		if (sb->s_flags & MS_SYNCHRONOUS) {
			ll_rw_block (WRITE, 1, &bh);
			wait_on_buffer (bh);
		}
	} else {
		if (le16_to_cpu(gdp->bg_free_inodes_count) != 0) {
			ext2_error (sb, "ext2_new_inode",
				    "Free inodes count corrupted in group %d",
				    i);
			unlock_super (sb);
			iput (inode);
			return NULL;
		}
		goto repeat;
	}
	j += i * EXT2_INODES_PER_GROUP(sb) + 1;
	if (j < EXT2_FIRST_INO(sb) || j > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "ext2_new_inode",
			    "reserved inode or inode > inodes count - "
			    "block_group = %d,inode=%d", i, j);
		unlock_super (sb);
		iput (inode);
		return NULL;
	}
	gdp->bg_free_inodes_count =
		cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);
	if (S_ISDIR(mode))
		gdp->bg_used_dirs_count =
			cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);
	mark_buffer_dirty(bh2, 1);
	es->s_free_inodes_count =
		cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
	mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
	sb->s_dirt = 1;
	inode->i_mode = mode;
	inode->i_sb = sb;
	inode->i_nlink = 1;
	inode->i_dev = sb->s_dev;
	inode->i_uid = current->fsuid;
	if (test_opt (sb, GRPID))
		inode->i_gid = dir->i_gid;
	else if (dir->i_mode & S_ISGID) {
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			mode |= S_ISGID;
	} else
		inode->i_gid = current->fsgid;

	inode->i_ino = j;
	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
	inode->i_blocks = 0;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	inode->u.ext2_i.i_new_inode = 1;
	inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags;
	if (S_ISLNK(mode))
		inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL | EXT2_APPEND_FL);
	inode->u.ext2_i.i_faddr = 0;
	inode->u.ext2_i.i_frag_no = 0;
	inode->u.ext2_i.i_frag_size = 0;
	inode->u.ext2_i.i_file_acl = 0;
	inode->u.ext2_i.i_dir_acl = 0;
	inode->u.ext2_i.i_dtime = 0;
	inode->u.ext2_i.i_block_group = i;
	inode->i_op = NULL;
	if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
		inode->i_flags |= MS_SYNCHRONOUS;
	insert_inode_hash(inode);
	mark_inode_dirty(inode);
	inc_inode_version (inode, gdp, mode);

	unlock_super (sb);
	if(DQUOT_ALLOC_INODE(sb, inode)) {
		sb->dq_op->drop(inode);
		inode->i_nlink = 0;
		iput(inode);
		*err = -EDQUOT;
		return NULL;
	}
	ext2_debug ("allocating inode %lu\n", inode->i_ino);

	*err = 0;
	return inode;
}
예제 #20
0
struct inode * ext2_new_inode (const struct inode * dir, int mode)
{
	struct super_block * sb;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	int group, i;
	ino_t ino;
	struct inode * inode;
	struct ext2_group_desc * desc;
	struct ext2_super_block * es;
	int err;

	sb = dir->i_sb;
	inode = new_inode(sb);
	if (!inode)
		return ERR_PTR(-ENOMEM);

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
repeat:
	if (S_ISDIR(mode))
		group = find_group_dir(sb, dir->u.ext2_i.i_block_group);
	else 
		group = find_group_other(sb, dir->u.ext2_i.i_block_group);

	err = -ENOSPC;
	if (group == -1)
		goto fail;

	err = -EIO;
	bh = load_inode_bitmap (sb, group);
	if (IS_ERR(bh))
		goto fail2;

	i = ext2_find_first_zero_bit ((unsigned long *) bh->b_data,
				      EXT2_INODES_PER_GROUP(sb));
	if (i >= EXT2_INODES_PER_GROUP(sb))
		goto bad_count;
	ext2_set_bit (i, bh->b_data);

	mark_buffer_dirty(bh);
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}

	ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1;
	if (ino < EXT2_FIRST_INO(sb) || ino > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "ext2_new_inode",
			    "reserved inode or inode > inodes count - "
			    "block_group = %d,inode=%ld", group, ino);
		err = -EIO;
		goto fail2;
	}

	es->s_free_inodes_count =
		cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) - 1);
	mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
	sb->s_dirt = 1;
	inode->i_uid = current->fsuid;
	if (test_opt (sb, GRPID))
		inode->i_gid = dir->i_gid;
	else if (dir->i_mode & S_ISGID) {
		inode->i_gid = dir->i_gid;
		if (S_ISDIR(mode))
			mode |= S_ISGID;
	} else
		inode->i_gid = current->fsgid;
	inode->i_mode = mode;

	inode->i_ino = ino;
	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
	inode->i_blocks = 0;
	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
	inode->u.ext2_i.i_new_inode = 1;
	inode->u.ext2_i.i_flags = dir->u.ext2_i.i_flags & ~EXT2_BTREE_FL;
	if (S_ISLNK(mode))
		inode->u.ext2_i.i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL);
	inode->u.ext2_i.i_block_group = group;
	if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL)
		inode->i_flags |= S_SYNC;
	insert_inode_hash(inode);
	inode->i_generation = event++;
	mark_inode_dirty(inode);

	unlock_super (sb);
	if(DQUOT_ALLOC_INODE(inode)) {
		DQUOT_DROP(inode);
		inode->i_flags |= S_NOQUOTA;
		inode->i_nlink = 0;
		iput(inode);
		return ERR_PTR(-EDQUOT);
	}
	ext2_debug ("allocating inode %lu\n", inode->i_ino);
	return inode;

fail2:
	desc = ext2_get_group_desc (sb, group, &bh2);
	desc->bg_free_inodes_count =
		cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1);
	if (S_ISDIR(mode))
		desc->bg_used_dirs_count =
			cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1);
	mark_buffer_dirty(bh2);
fail:
	unlock_super(sb);
	make_bad_inode(inode);
	iput(inode);
	return ERR_PTR(err);

bad_count:
	ext2_error (sb, "ext2_new_inode",
		    "Free inodes count corrupted in group %d",
		    group);
	/* Is it really ENOSPC? */
	err = -ENOSPC;
	if (sb->s_flags & MS_RDONLY)
		goto fail;

	desc = ext2_get_group_desc (sb, group, &bh2);
	desc->bg_free_inodes_count = 0;
	mark_buffer_dirty(bh2);
	goto repeat;
}
예제 #21
0
/*
 * NOTE! When we get the inode, we're the only people
 * that have access to it, and as such there are no
 * race conditions we have to worry about. The inode
 * is not on the hash-lists, and it cannot be reached
 * through the filesystem because the directory entry
 * has been deleted earlier.
 *
 * HOWEVER: we must make sure that we get no aliases,
 * which means that we have to call "clear_inode()"
 * _before_ we mark the inode not in use in the inode
 * bitmaps. Otherwise a newly created file might use
 * the same inode number (not actually the same pointer
 * though), and then we'd have two inodes sharing the
 * same inode number and space on the harddisk.
 */
void ext2_free_inode (struct inode * inode)
{
	struct super_block * sb = inode->i_sb;
	int is_directory;
	unsigned long ino;
	struct buffer_head * bh;
	struct buffer_head * bh2;
	unsigned long block_group;
	unsigned long bit;
	struct ext2_group_desc * desc;
	struct ext2_super_block * es;

	ino = inode->i_ino;
	ext2_debug ("freeing inode %lu\n", ino);

	/*
	 * Note: we must free any quota before locking the superblock,
	 * as writing the quota to disk may need the lock as well.
	 */
	if (!is_bad_inode(inode)) {
		/* Quota is already initialized in iput() */
	    	DQUOT_FREE_INODE(inode);
		DQUOT_DROP(inode);
	}

	lock_super (sb);
	es = sb->u.ext2_sb.s_es;
	is_directory = S_ISDIR(inode->i_mode);

	/* Do this BEFORE marking the inode not in use or returning an error */
	clear_inode (inode);

	if (ino < EXT2_FIRST_INO(sb) ||
	    ino > le32_to_cpu(es->s_inodes_count)) {
		ext2_error (sb, "ext2_free_inode",
			    "reserved or nonexistent inode %lu", ino);
		goto error_return;
	}
	block_group = (ino - 1) / EXT2_INODES_PER_GROUP(sb);
	bit = (ino - 1) % EXT2_INODES_PER_GROUP(sb);
	bh = load_inode_bitmap (sb, block_group);
	if (IS_ERR(bh))
		goto error_return;

	/* Ok, now we can actually update the inode bitmaps.. */
	if (!ext2_clear_bit (bit, bh->b_data))
		ext2_error (sb, "ext2_free_inode",
			      "bit already cleared for inode %lu", ino);
	else {
		desc = ext2_get_group_desc (sb, block_group, &bh2);
		if (desc) {
			desc->bg_free_inodes_count =
				cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1);
			if (is_directory)
				desc->bg_used_dirs_count =
					cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1);
		}
		mark_buffer_dirty(bh2);
		es->s_free_inodes_count =
			cpu_to_le32(le32_to_cpu(es->s_free_inodes_count) + 1);
		mark_buffer_dirty(sb->u.ext2_sb.s_sbh);
	}
	mark_buffer_dirty(bh);
	if (sb->s_flags & MS_SYNCHRONOUS) {
		ll_rw_block (WRITE, 1, &bh);
		wait_on_buffer (bh);
	}
	sb->s_dirt = 1;
error_return:
	unlock_super (sb);
}