⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ialloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			continue;		if (le16_to_cpu(desc->bg_used_dirs_count) >= max_dirs)			continue;		if (le16_to_cpu(desc->bg_free_inodes_count) < min_inodes)			continue;		if (le16_to_cpu(desc->bg_free_blocks_count) < min_blocks)			continue;		goto found;	}fallback:	for (i = 0; i < ngroups; i++) {		group = (parent_group + i) % ngroups;		desc = ext2_get_group_desc (sb, group, NULL);		if (!desc || !desc->bg_free_inodes_count)			continue;		if (le16_to_cpu(desc->bg_free_inodes_count) >= avefreei)			goto found;	}	if (avefreei) {		/*		 * The free-inodes counter is approximate, and for really small		 * filesystems the above test can fail to find any blockgroups		 */		avefreei = 0;		goto fallback;	}	return -1;found:	return group;}static int find_group_other(struct super_block *sb, struct inode *parent){	int parent_group = EXT2_I(parent)->i_block_group;	int ngroups = EXT2_SB(sb)->s_groups_count;	struct ext2_group_desc *desc;	int group, i;	/*	 * Try to place the inode in its parent directory	 */	group = parent_group;	desc = ext2_get_group_desc (sb, group, NULL);	if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&			le16_to_cpu(desc->bg_free_blocks_count))		goto found;	/*	 * We're going to place this inode in a different blockgroup from its	 * parent.  We want to cause files in a common directory to all land in	 * the same blockgroup.  But we want files which are in a different	 * directory which shares a blockgroup with our parent to land in a	 * different blockgroup.	 *	 * So add our directory's i_ino into the starting point for the hash.	 */	group = (group + parent->i_ino) % ngroups;	/*	 * Use a quadratic hash to find a group with a free inode and some	 * free blocks.	 */	for (i = 1; i < ngroups; i <<= 1) {		group += i;		if (group >= ngroups)			group -= ngroups;		desc = ext2_get_group_desc (sb, group, NULL);		if (desc && le16_to_cpu(desc->bg_free_inodes_count) &&				le16_to_cpu(desc->bg_free_blocks_count))			goto found;	}	/*	 * That failed: try linear search for a free inode, even if that group	 * has no free blocks.	 */	group = parent_group;	for (i = 0; i < ngroups; i++) {		if (++group >= ngroups)			group = 0;		desc = ext2_get_group_desc (sb, group, NULL);		if (desc && le16_to_cpu(desc->bg_free_inodes_count))			goto found;	}	return -1;found:	return group;}struct inode *ext2_new_inode(struct inode *dir, int mode){	struct super_block *sb;	struct buffer_head *bitmap_bh = NULL;	struct buffer_head *bh2;	int group, i;	ino_t ino = 0;	struct inode * inode;	struct ext2_group_desc *gdp;	struct ext2_super_block *es;	struct ext2_inode_info *ei;	struct ext2_sb_info *sbi;	int err;	sb = dir->i_sb;	inode = new_inode(sb);	if (!inode)		return ERR_PTR(-ENOMEM);	ei = EXT2_I(inode);	sbi = EXT2_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 		group = find_group_other(sb, dir);	if (group == -1) {		err = -ENOSPC;		goto fail;	}	for (i = 0; i < sbi->s_groups_count; i++) {		gdp = ext2_get_group_desc(sb, group, &bh2);		brelse(bitmap_bh);		bitmap_bh = read_inode_bitmap(sb, group);		if (!bitmap_bh) {			err = -EIO;			goto fail;		}		ino = 0;repeat_in_this_group:		ino = ext2_find_next_zero_bit((unsigned long *)bitmap_bh->b_data,					      EXT2_INODES_PER_GROUP(sb), ino);		if (ino >= EXT2_INODES_PER_GROUP(sb)) {			/*			 * Rare race: find_group_xx() decided that there were			 * free inodes in this group, but by the time we tried			 * to allocate one, they're all gone.  This can also			 * occur because the counters which find_group_orlov()			 * uses are approximate.  So just go and search the			 * next block group.			 */			if (++group == sbi->s_groups_count)				group = 0;			continue;		}		if (ext2_set_bit_atomic(sb_bgl_lock(sbi, group),						ino, bitmap_bh->b_data)) {			/* we lost this inode */			if (++ino >= EXT2_INODES_PER_GROUP(sb)) {				/* this group is exhausted, try next group */				if (++group == sbi->s_groups_count)					group = 0;				continue;			}			/* try to find free inode in the same group */			goto repeat_in_this_group;		}		goto got;	}	/*	 * Scanned all blockgroups.	 */	err = -ENOSPC;	goto fail;got:	mark_buffer_dirty(bitmap_bh);	if (sb->s_flags & MS_SYNCHRONOUS)		sync_dirty_buffer(bitmap_bh);	brelse(bitmap_bh);	ino += group * EXT2_INODES_PER_GROUP(sb) + 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=%lu", group,			    (unsigned long) ino);		err = -EIO;		goto fail;	}	percpu_counter_add(&sbi->s_freeinodes_counter, -1);	if (S_ISDIR(mode))		percpu_counter_inc(&sbi->s_dirs_counter);	spin_lock(sb_bgl_lock(sbi, group));	gdp->bg_free_inodes_count =                cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1);	if (S_ISDIR(mode)) {		if (sbi->s_debts[group] < 255)			sbi->s_debts[group]++;		gdp->bg_used_dirs_count =			cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1);	} else {		if (sbi->s_debts[group])			sbi->s_debts[group]--;	}	spin_unlock(sb_bgl_lock(sbi, group));	sb->s_dirt = 1;	mark_buffer_dirty(bh2);	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_blocks = 0;	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;	memset(ei->i_data, 0, sizeof(ei->i_data));	ei->i_flags = EXT2_I(dir)->i_flags & ~EXT2_BTREE_FL;	if (S_ISLNK(mode))		ei->i_flags &= ~(EXT2_IMMUTABLE_FL|EXT2_APPEND_FL);	/* dirsync is only applied to directories */	if (!S_ISDIR(mode))		ei->i_flags &= ~EXT2_DIRSYNC_FL;	ei->i_faddr = 0;	ei->i_frag_no = 0;	ei->i_frag_size = 0;	ei->i_file_acl = 0;	ei->i_dir_acl = 0;	ei->i_dtime = 0;	ei->i_block_alloc_info = NULL;	ei->i_block_group = group;	ei->i_dir_start_lookup = 0;	ei->i_state = EXT2_STATE_NEW;	ext2_set_inode_flags(inode);	spin_lock(&sbi->s_next_gen_lock);	inode->i_generation = sbi->s_next_generation++;	spin_unlock(&sbi->s_next_gen_lock);	insert_inode_hash(inode);	if (DQUOT_ALLOC_INODE(inode)) {		err = -EDQUOT;		goto fail_drop;	}	err = ext2_init_acl(inode, dir);	if (err)		goto fail_free_drop;	err = ext2_init_security(inode,dir);	if (err)		goto fail_free_drop;	mark_inode_dirty(inode);	ext2_debug("allocating inode %lu\n", inode->i_ino);	ext2_preread_inode(inode);	return inode;fail_free_drop:	DQUOT_FREE_INODE(inode);fail_drop:	DQUOT_DROP(inode);	inode->i_flags |= S_NOQUOTA;	inode->i_nlink = 0;	iput(inode);	return ERR_PTR(err);fail:	make_bad_inode(inode);	iput(inode);	return ERR_PTR(err);}unsigned long ext2_count_free_inodes (struct super_block * sb){	struct ext2_group_desc *desc;	unsigned long desc_count = 0;	int i;	#ifdef EXT2FS_DEBUG	struct ext2_super_block *es;	unsigned long bitmap_count = 0;	struct buffer_head *bitmap_bh = NULL;	es = EXT2_SB(sb)->s_es;	for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {		unsigned x;		desc = ext2_get_group_desc (sb, i, NULL);		if (!desc)			continue;		desc_count += le16_to_cpu(desc->bg_free_inodes_count);		brelse(bitmap_bh);		bitmap_bh = read_inode_bitmap(sb, i);		if (!bitmap_bh)			continue;		x = ext2_count_free(bitmap_bh, EXT2_INODES_PER_GROUP(sb) / 8);		printk("group %d: stored = %d, counted = %u\n",			i, le16_to_cpu(desc->bg_free_inodes_count), x);		bitmap_count += x;	}	brelse(bitmap_bh);	printk("ext2_count_free_inodes: stored = %lu, computed = %lu, %lu\n",		percpu_counter_read(&EXT2_SB(sb)->s_freeinodes_counter),		desc_count, bitmap_count);	return desc_count;#else	for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {		desc = ext2_get_group_desc (sb, i, NULL);		if (!desc)			continue;		desc_count += le16_to_cpu(desc->bg_free_inodes_count);	}	return desc_count;#endif}/* Called at mount-time, super-block is locked */unsigned long ext2_count_dirs (struct super_block * sb){	unsigned long count = 0;	int i;	for (i = 0; i < EXT2_SB(sb)->s_groups_count; i++) {		struct ext2_group_desc *gdp = ext2_get_group_desc (sb, i, NULL);		if (!gdp)			continue;		count += le16_to_cpu(gdp->bg_used_dirs_count);	}	return count;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -