diff options
Diffstat (limited to 'fs/ext3/ialloc.c')
| -rw-r--r-- | fs/ext3/ialloc.c | 97 | 
1 files changed, 20 insertions, 77 deletions
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 9724aef2246..a1b810230cc 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -12,20 +12,10 @@   *        David S. Miller (davem@caip.rutgers.edu), 1995   */ -#include <linux/time.h> -#include <linux/fs.h> -#include <linux/jbd.h> -#include <linux/ext3_fs.h> -#include <linux/ext3_jbd.h> -#include <linux/stat.h> -#include <linux/string.h>  #include <linux/quotaops.h> -#include <linux/buffer_head.h>  #include <linux/random.h> -#include <linux/bitops.h> - -#include <asm/byteorder.h> +#include "ext3.h"  #include "xattr.h"  #include "acl.h" @@ -118,6 +108,7 @@ void ext3_free_inode (handle_t *handle, struct inode * inode)  	ino = inode->i_ino;  	ext3_debug ("freeing inode %lu\n", ino); +	trace_ext3_free_inode(inode);  	is_directory = S_ISDIR(inode->i_mode); @@ -176,42 +167,6 @@ error_return:  }  /* - * 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. - */ -static int find_group_dir(struct super_block *sb, struct inode *parent) -{ -	int ngroups = EXT3_SB(sb)->s_groups_count; -	unsigned int freei, avefreei; -	struct ext3_group_desc *desc, *best_desc = NULL; -	int group, best_group = -1; - -	freei = percpu_counter_read_positive(&EXT3_SB(sb)->s_freeinodes_counter); -	avefreei = freei / ngroups; - -	for (group = 0; group < ngroups; group++) { -		desc = ext3_get_group_desc (sb, group, NULL); -		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; -		} -	} -	return best_group; -} - -/*   * Orlov's allocator for directories.   *   * We always try to spread first-level directories. @@ -225,8 +180,7 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)   * It's OK to put directory into a group unless   * it has too many directories already (max_dirs) or   * it has too few free inodes left (min_inodes) or - * it has too few free blocks left (min_blocks) or - * it's already running too large debt (max_debt). + * it has too few free blocks left (min_blocks).   * Parent's group is preferred, if it doesn't satisfy these   * conditions we search cyclically through the rest. If none   * of the groups look good we just look for a group with more @@ -236,21 +190,16 @@ static int find_group_dir(struct super_block *sb, struct inode *parent)   * when we allocate an inode, within 0--255.   */ -#define INODE_COST 64 -#define BLOCK_COST 256 -  static int find_group_orlov(struct super_block *sb, struct inode *parent)  {  	int parent_group = EXT3_I(parent)->i_block_group;  	struct ext3_sb_info *sbi = EXT3_SB(sb); -	struct ext3_super_block *es = sbi->s_es;  	int ngroups = sbi->s_groups_count;  	int inodes_per_group = EXT3_INODES_PER_GROUP(sb);  	unsigned int freei, avefreei;  	ext3_fsblk_t freeb, avefreeb; -	ext3_fsblk_t blocks_per_dir;  	unsigned int ndirs; -	int max_debt, max_dirs, min_inodes; +	int max_dirs, min_inodes;  	ext3_grpblk_t min_blocks;  	int group = -1, i;  	struct ext3_group_desc *desc; @@ -266,7 +215,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)  		int best_ndir = inodes_per_group;  		int best_group = -1; -		get_random_bytes(&group, sizeof(group)); +		group = prandom_u32();  		parent_group = (unsigned)group % ngroups;  		for (i = 0; i < ngroups; i++) {  			group = (parent_group + i) % ngroups; @@ -287,20 +236,10 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent)  		goto fallback;  	} -	blocks_per_dir = (le32_to_cpu(es->s_blocks_count) - freeb) / ndirs; -  	max_dirs = ndirs / ngroups + inodes_per_group / 16;  	min_inodes = avefreei - inodes_per_group / 4;  	min_blocks = avefreeb - EXT3_BLOCKS_PER_GROUP(sb) / 4; -	max_debt = EXT3_BLOCKS_PER_GROUP(sb) / max(blocks_per_dir, (ext3_fsblk_t)BLOCK_COST); -	if (max_debt * INODE_COST > inodes_per_group) -		max_debt = inodes_per_group / INODE_COST; -	if (max_debt > 255) -		max_debt = 255; -	if (max_debt == 0) -		max_debt = 1; -  	for (i = 0; i < ngroups; i++) {  		group = (parent_group + i) % ngroups;  		desc = ext3_get_group_desc (sb, group, NULL); @@ -404,7 +343,8 @@ static int find_group_other(struct super_block *sb, struct inode *parent)   * For other inodes, search forward from the parent directory's block   * group to find a free inode.   */ -struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode) +struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, +			     const struct qstr *qstr, umode_t mode)  {  	struct super_block *sb;  	struct buffer_head *bitmap_bh = NULL; @@ -425,6 +365,7 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)  		return ERR_PTR(-EPERM);  	sb = dir->i_sb; +	trace_ext3_request_inode(dir, mode);  	inode = new_inode(sb);  	if (!inode)  		return ERR_PTR(-ENOMEM); @@ -432,12 +373,9 @@ struct inode *ext3_new_inode(handle_t *handle, struct inode * dir, int mode)  	sbi = EXT3_SB(sb);  	es = sbi->s_es; -	if (S_ISDIR(mode)) { -		if (test_opt (sb, OLDALLOC)) -			group = find_group_dir(sb, dir); -		else -			group = find_group_orlov(sb, dir); -	} else +	if (S_ISDIR(mode)) +		group = find_group_orlov(sb, dir); +	else  		group = find_group_other(sb, dir);  	err = -ENOSPC; @@ -560,8 +498,12 @@ got:  	if (IS_DIRSYNC(inode))  		handle->h_sync = 1;  	if (insert_inode_locked(inode) < 0) { -		err = -EINVAL; -		goto fail_drop; +		/* +		 * Likely a bitmap corruption causing inode to be allocated +		 * twice. +		 */ +		err = -EIO; +		goto fail;  	}  	spin_lock(&sbi->s_next_gen_lock);  	inode->i_generation = sbi->s_next_generation++; @@ -589,7 +531,7 @@ got:  	if (err)  		goto fail_free_drop; -	err = ext3_init_security(handle,inode, dir); +	err = ext3_init_security(handle, inode, dir, qstr);  	if (err)  		goto fail_free_drop; @@ -600,6 +542,7 @@ got:  	}  	ext3_debug("allocating inode %lu\n", inode->i_ino); +	trace_ext3_allocate_inode(inode, dir, mode);  	goto really_out;  fail:  	ext3_std_error(sb, err); @@ -616,7 +559,7 @@ fail_free_drop:  fail_drop:  	dquot_drop(inode);  	inode->i_flags |= S_NOQUOTA; -	inode->i_nlink = 0; +	clear_nlink(inode);  	unlock_new_inode(inode);  	iput(inode);  	brelse(bitmap_bh);  | 
