Example #1
0
static void release_blocks(struct super_block *sb, int count)
{
	if (count) {
		struct ext2_sb_info *sbi = EXT2_SB(sb);

		percpu_counter_add(&sbi->s_freeblocks_counter, count);
	}
}
Example #2
0
int ext4_claim_free_blocks(struct ext4_sb_info *sbi,
						s64 nblocks)
{
	if (ext4_has_free_blocks(sbi, nblocks)) {
		percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks);
		return 0;
	} else
		return -ENOSPC;
}
void increment_partitioned_counter(PARTITIONED_COUNTER pc, uint64_t amount)
{
	percpu_counter_add(&pc->pcpu_counter, amount);
}
Example #4
0
/**
 * ext4_add_groupblocks() -- Add given blocks to an existing group
 * @handle:			handle to this transaction
 * @sb:				super block
 * @block:			start physcial block to add to the block group
 * @count:			number of blocks to free
 *
 * This marks the blocks as free in the bitmap. We ask the
 * mballoc to reload the buddy after this by setting group
 * EXT4_GROUP_INFO_NEED_INIT_BIT flag
 */
void ext4_add_groupblocks(handle_t *handle, struct super_block *sb,
			 ext4_fsblk_t block, unsigned long count)
{
	struct buffer_head *bitmap_bh = NULL;
	struct buffer_head *gd_bh;
	ext4_group_t block_group;
	ext4_grpblk_t bit;
	unsigned int i;
	struct ext4_group_desc *desc;
	struct ext4_super_block *es;
	struct ext4_sb_info *sbi;
	int err = 0, ret, blk_free_count;
	ext4_grpblk_t blocks_freed;
	struct ext4_group_info *grp;

	sbi = EXT4_SB(sb);
	es = sbi->s_es;
	ext4_debug("Adding block(s) %llu-%llu\n", block, block + count - 1);

	ext4_get_group_no_and_offset(sb, block, &block_group, &bit);
	grp = ext4_get_group_info(sb, block_group);
	/*
	 * Check to see if we are freeing blocks across a group
	 * boundary.
	 */
	if (bit + count > EXT4_BLOCKS_PER_GROUP(sb)) {
		goto error_return;
	}
	bitmap_bh = ext4_read_block_bitmap(sb, block_group);
	if (!bitmap_bh)
		goto error_return;
	desc = ext4_get_group_desc(sb, block_group, &gd_bh);
	if (!desc)
		goto error_return;

	if (in_range(ext4_block_bitmap(sb, desc), block, count) ||
	    in_range(ext4_inode_bitmap(sb, desc), block, count) ||
	    in_range(block, ext4_inode_table(sb, desc), sbi->s_itb_per_group) ||
	    in_range(block + count - 1, ext4_inode_table(sb, desc),
		     sbi->s_itb_per_group)) {
		ext4_error(sb, __func__,
			   "Adding blocks in system zones - "
			   "Block = %llu, count = %lu",
			   block, count);
		goto error_return;
	}

	/*
	 * We are about to add blocks to the bitmap,
	 * so we need undo access.
	 */
	BUFFER_TRACE(bitmap_bh, "getting undo access");
	err = ext4_journal_get_undo_access(handle, bitmap_bh);
	if (err)
		goto error_return;

	/*
	 * We are about to modify some metadata.  Call the journal APIs
	 * to unshare ->b_data if a currently-committing transaction is
	 * using it
	 */
	BUFFER_TRACE(gd_bh, "get_write_access");
	err = ext4_journal_get_write_access(handle, gd_bh);
	if (err)
		goto error_return;
	/*
	 * make sure we don't allow a parallel init on other groups in the
	 * same buddy cache
	 */
	down_write(&grp->alloc_sem);
	for (i = 0, blocks_freed = 0; i < count; i++) {
		BUFFER_TRACE(bitmap_bh, "clear bit");
		if (!ext4_clear_bit_atomic(ext4_group_lock_ptr(sb, block_group),
						bit + i, bitmap_bh->b_data)) {
			ext4_error(sb, __func__,
				   "bit already cleared for block %llu",
				   (ext4_fsblk_t)(block + i));
			BUFFER_TRACE(bitmap_bh, "bit already cleared");
		} else {
			blocks_freed++;
		}
	}
	ext4_lock_group(sb, block_group);
	blk_free_count = blocks_freed + ext4_free_blks_count(sb, desc);
	ext4_free_blks_set(sb, desc, blk_free_count);
	desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc);
	ext4_unlock_group(sb, block_group);
	percpu_counter_add(&sbi->s_freeblocks_counter, blocks_freed);

	if (sbi->s_log_groups_per_flex) {
		ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
		atomic_add(blocks_freed,
			   &sbi->s_flex_groups[flex_group].free_blocks);
	}
	/*
	 * request to reload the buddy with the
	 * new bitmap information
	 */
	set_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &(grp->bb_state));
	grp->bb_free += blocks_freed;
	up_write(&grp->alloc_sem);

	/* We dirtied the bitmap block */
	BUFFER_TRACE(bitmap_bh, "dirtied bitmap block");
	err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);

	/* And the group descriptor block */
	BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
	ret = ext4_handle_dirty_metadata(handle, NULL, gd_bh);
	if (!err)
		err = ret;
	sb->s_dirt = 1;

error_return:
	brelse(bitmap_bh);
	ext4_std_error(sb, err);
	return;
}
/*
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
	Function	:me2fsAllocNewInode
	Input		:struct inode *dir
				 < vfs inode of directory >
				 umode_t mode
				 < file mode >
				 const struct qstr *qstr
				 < entry name for new inode >
	Output		:void
	Return		:struct inode*
				 < new allocated inode >

	Description	:allocate new inode
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
*/
struct inode*
me2fsAllocNewInode( struct inode *dir, umode_t mode, const struct qstr *qstr )
{
	struct super_block		*sb;
	struct buffer_head		*bitmap_bh;
	struct buffer_head		*bh_gdesc;

	struct inode			*inode;			/* new inode */
	ino_t					ino;
	struct ext2_group_desc	*gdesc;
	struct ext2_super_block	*esb;
	struct me2fs_inode_info	*mi;
	struct me2fs_sb_info	*msi;

	unsigned long			group;
	int						i;
	int						err;

	/* ------------------------------------------------------------------------ */
	/* allocate vfs new inode													*/
	/* ------------------------------------------------------------------------ */
	sb = dir->i_sb;

	if( !( inode = new_inode( sb ) ) )
	{
		return( ERR_PTR( -ENOMEM ) );
	}

	bitmap_bh	= NULL;
	ino			= 0;

	msi			= ME2FS_SB( sb );

	if( S_ISDIR( mode ) )
	{
		group = findDirectoryGroup( sb, dir );
	}
	else
	{
		/* -------------------------------------------------------------------- */
		/* as for now allocating inode for file is not support					*/
		/* -------------------------------------------------------------------- */
		err = -ENOSPC;
		goto fail;
	}

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

	for( i = 0 ; i < msi->s_groups_count ; i++ )
	{
		brelse( bitmap_bh );
		if( !( bitmap_bh = readInodeBitmap( sb, group ) ) )
		{
			err = -EIO;
			goto fail;
		}

		ino = 0;

		/* -------------------------------------------------------------------- */
		/* find free inode														*/
		/* -------------------------------------------------------------------- */
repeat_in_this_group:
		ino = find_next_zero_bit_le( ( unsigned long* )bitmap_bh->b_data,
									 msi->s_inodes_per_group,
									 ino );

		if( ME2FS_SB( sb )->s_inodes_per_group <= ino )
		{
			/* cannot find ino. bitmap is already full							*/
			group++;

			if( group <= msi->s_groups_count )
			{
				group = 0;
			}

			continue;
		}

		/* -------------------------------------------------------------------- */
		/* allocate inode atomically											*/
		/* -------------------------------------------------------------------- */
		if( ext2_set_bit_atomic( getSbBlockGroupLock( msi, group ),
								 ( int )ino,
								 bitmap_bh->b_data ) )
		{
			/* ---------------------------------------------------------------- */
			/* already set the bitmap											*/
			/* ---------------------------------------------------------------- */
			ino++;
			if( msi->s_inodes_per_group <= ino )
			{
				/* the group has no entry, try next								*/
				group++;
				if( msi->s_groups_count <= group )
				{
					group = 0;
				}
				continue;
			}

			/* try to find in the same group									*/
			goto repeat_in_this_group;
		}

		goto got;
	}

	/* ------------------------------------------------------------------------ */
	/* cannot find free inode													*/
	/* ------------------------------------------------------------------------ */
	err = -ENOSPC;
	goto fail;

	/* ------------------------------------------------------------------------ */
	/* found free inode															*/
	/* ------------------------------------------------------------------------ */
got:
	mi		= ME2FS_I( inode );
	esb		= msi->s_esb;

	mark_buffer_dirty( bitmap_bh );
	if( sb->s_flags & MS_SYNCHRONOUS )
	{
		sync_dirty_buffer( bitmap_bh );
	}
	brelse( bitmap_bh );

	/* ------------------------------------------------------------------------ */
	/* get absolute inode number												*/
	/* ------------------------------------------------------------------------ */
	ino	+= ( group * ME2FS_SB( sb )->s_inodes_per_group ) + 1;

	if( ( ino < msi->s_first_ino ) ||
		( le32_to_cpu( esb->s_inodes_count ) < ino ) )
	{
		ME2FS_ERROR( "<ME2FS>%s:insane inode number. ino=%lu,group=%lu\n",
					  __func__, ( unsigned long )ino, group );
		err = -EIO;
		goto fail;
	}

	/* ------------------------------------------------------------------------ */
	/* update group descriptor													*/
	/* ------------------------------------------------------------------------ */
	gdesc		= me2fsGetGroupDescriptor( sb, group );
	bh_gdesc	= me2fsGetGdescBufferCache( sb, group );

	percpu_counter_add( &msi->s_freeinodes_counter, -1 );

	if( S_ISDIR( mode ) )
	{
		percpu_counter_inc( &msi->s_dirs_counter );
	}

	spin_lock( getSbBlockGroupLock( msi, group ) );
	{
		le16_add_cpu( &gdesc->bg_free_inodes_count, -1 );
		if( S_ISDIR( mode ) )
		{
			le16_add_cpu( &gdesc->bg_used_dirs_count, 1 );
		}
	}
	spin_unlock( getSbBlockGroupLock( msi, group ) );

	mark_buffer_dirty( bh_gdesc );

	/* ------------------------------------------------------------------------ */
	/* initialize vfs inode														*/
	/* ------------------------------------------------------------------------ */
	inode_init_owner( inode, dir, mode );

	inode->i_ino	= ino;
	inode->i_blocks	= 0;
	inode->i_mtime	= CURRENT_TIME_SEC;
	inode->i_atime	= inode->i_mtime;
	inode->i_ctime	= inode->i_mtime;

	/* ------------------------------------------------------------------------ */
	/* initialize me2fs inode information										*/
	/* ------------------------------------------------------------------------ */
	memset( mi->i_data, 0, sizeof( mi->i_data ) );

	mi->i_flags = ME2FS_I( dir )->i_flags & EXT2_FL_INHERITED;

	if( S_ISDIR( mode ) )
	{
		/* do nothing															*/
	}
	else if( S_ISREG( mode ) )
	{
		mi->i_flags &= EXT2_REG_FLMASK;
	}
	else
	{
		mi->i_flags &= EXT2_OTHER_FLMASK;
	}

	mi->i_faddr				= 0;
	mi->i_frag_no			= 0;
	mi->i_frag_size			= 0;
	mi->i_file_acl			= 0;
	mi->i_dir_acl			= 0;
	mi->i_dtime				= 0;
	//mi->i_block_alloc_info	= NULL;
	mi->i_state				= EXT2_STATE_NEW;

	me2fsSetVfsInodeFlags( inode );
	
	/* insert vfs inode to hash table											*/
	if( insert_inode_locked( inode ) < 0 )
	{
		ME2FS_ERROR( "<ME2FS>%s:inode number already in use[%lu]\n",
					 __func__, ( unsigned long )ino );
		err = -EIO;
		goto fail;
	}

	/* initialize quota															*/
#if 0	// quota
	dquot_initialize( inode );
	if( dquot_alloc_inode( inode ) )
	{
		goto fail_drop;
	}
#endif
#if 0	// acl
	/* initialize acl															*/
	if( me2fsInitAcl( inde, dir ) )
	{
		goto fail_free_drop;
	}
#endif
#if 0	// security
	/* initialize security														*/
	if( me2fsInitSecurity( inode, dir, qstr ) )
	{
		goto fail_free_drop;
	}
#endif

	mark_inode_dirty( inode );

	DBGPRINT( "<ME2FS>allocating new inode %lu\n",
			  ( unsigned long )inode->i_ino );

#if 0	// preread
	me2fsPrereadInode( inode );
#endif

	return( inode );

	/* ------------------------------------------------------------------------ */
	/* allocation of new inode is failed										*/
	/* ------------------------------------------------------------------------ */
fail:
	make_bad_inode( inode );
	iput( inode );
	return( ERR_PTR( err ) );
}