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

📄 balloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	mark_buffer_dirty(bitmap_bh);	if (sb->s_flags & MS_SYNCHRONOUS)		sync_dirty_buffer(bitmap_bh);	group_adjust_blocks(sb, block_group, desc, bh2, group_freed);	freed += group_freed;	if (overflow) {		block += count;		count = overflow;		goto do_more;	}error_return:	brelse(bitmap_bh);	release_blocks(sb, freed);	DQUOT_FREE_BLOCK(inode, freed);}/** * bitmap_search_next_usable_block() * @start:		the starting block (group relative) of the search * @bh:			bufferhead contains the block group bitmap * @maxblocks:		the ending block (group relative) of the reservation * * The bitmap search --- search forward through the actual bitmap on disk until * we find a bit free. */static ext2_grpblk_tbitmap_search_next_usable_block(ext2_grpblk_t start, struct buffer_head *bh,					ext2_grpblk_t maxblocks){	ext2_grpblk_t next;	next = ext2_find_next_zero_bit(bh->b_data, maxblocks, start);	if (next >= maxblocks)		return -1;	return next;}/** * find_next_usable_block() * @start:		the starting block (group relative) to find next * 			allocatable block in bitmap. * @bh:			bufferhead contains the block group bitmap * @maxblocks:		the ending block (group relative) for the search * * Find an allocatable block in a bitmap.  We perform the "most * appropriate allocation" algorithm of looking for a free block near * the initial goal; then for a free byte somewhere in the bitmap; * then for any free bit in the bitmap. */static ext2_grpblk_tfind_next_usable_block(int start, struct buffer_head *bh, int maxblocks){	ext2_grpblk_t here, next;	char *p, *r;	if (start > 0) {		/*		 * The goal was occupied; search forward for a free 		 * block within the next XX blocks.		 *		 * end_goal is more or less random, but it has to be		 * less than EXT2_BLOCKS_PER_GROUP. Aligning up to the		 * next 64-bit boundary is simple..		 */		ext2_grpblk_t end_goal = (start + 63) & ~63;		if (end_goal > maxblocks)			end_goal = maxblocks;		here = ext2_find_next_zero_bit(bh->b_data, end_goal, start);		if (here < end_goal)			return here;		ext2_debug("Bit not found near goal\n");	}	here = start;	if (here < 0)		here = 0;	p = ((char *)bh->b_data) + (here >> 3);	r = memscan(p, 0, ((maxblocks + 7) >> 3) - (here >> 3));	next = (r - ((char *)bh->b_data)) << 3;	if (next < maxblocks && next >= here)		return next;	here = bitmap_search_next_usable_block(here, bh, maxblocks);	return here;}/* * ext2_try_to_allocate() * @sb:			superblock * @handle:		handle to this transaction * @group:		given allocation block group * @bitmap_bh:		bufferhead holds the block bitmap * @grp_goal:		given target block within the group * @count:		target number of blocks to allocate * @my_rsv:		reservation window * * Attempt to allocate blocks within a give range. Set the range of allocation * first, then find the first free bit(s) from the bitmap (within the range), * and at last, allocate the blocks by claiming the found free bit as allocated. * * To set the range of this allocation: * 	if there is a reservation window, only try to allocate block(s) * 	from the file's own reservation window; * 	Otherwise, the allocation range starts from the give goal block, * 	ends at the block group's last block. * * If we failed to allocate the desired block then we may end up crossing to a * new bitmap. */static intext2_try_to_allocate(struct super_block *sb, int group,			struct buffer_head *bitmap_bh, ext2_grpblk_t grp_goal,			unsigned long *count,			struct ext2_reserve_window *my_rsv){	ext2_fsblk_t group_first_block;       	ext2_grpblk_t start, end;	unsigned long num = 0;	/* we do allocation within the reservation window if we have a window */	if (my_rsv) {		group_first_block = ext2_group_first_block_no(sb, group);		if (my_rsv->_rsv_start >= group_first_block)			start = my_rsv->_rsv_start - group_first_block;		else			/* reservation window cross group boundary */			start = 0;		end = my_rsv->_rsv_end - group_first_block + 1;		if (end > EXT2_BLOCKS_PER_GROUP(sb))			/* reservation window crosses group boundary */			end = EXT2_BLOCKS_PER_GROUP(sb);		if ((start <= grp_goal) && (grp_goal < end))			start = grp_goal;		else			grp_goal = -1;	} else {		if (grp_goal > 0)			start = grp_goal;		else			start = 0;		end = EXT2_BLOCKS_PER_GROUP(sb);	}	BUG_ON(start > EXT2_BLOCKS_PER_GROUP(sb));repeat:	if (grp_goal < 0) {		grp_goal = find_next_usable_block(start, bitmap_bh, end);		if (grp_goal < 0)			goto fail_access;		if (!my_rsv) {			int i;			for (i = 0; i < 7 && grp_goal > start &&					!ext2_test_bit(grp_goal - 1,					     		bitmap_bh->b_data);			     		i++, grp_goal--)				;		}	}	start = grp_goal;	if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group), grp_goal,			       				bitmap_bh->b_data)) {		/*		 * The block was allocated by another thread, or it was		 * allocated and then freed by another thread		 */		start++;		grp_goal++;		if (start >= end)			goto fail_access;		goto repeat;	}	num++;	grp_goal++;	while (num < *count && grp_goal < end		&& !ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group),					grp_goal, bitmap_bh->b_data)) {		num++;		grp_goal++;	}	*count = num;	return grp_goal - num;fail_access:	*count = num;	return -1;}/** * 	find_next_reservable_window(): *		find a reservable space within the given range. *		It does not allocate the reservation window for now: *		alloc_new_reservation() will do the work later. * * 	@search_head: the head of the searching list; *		This is not necessarily the list head of the whole filesystem * *		We have both head and start_block to assist the search *		for the reservable space. The list starts from head, *		but we will shift to the place where start_block is, *		then start from there, when looking for a reservable space. * * 	@size: the target new reservation window size * * 	@group_first_block: the first block we consider to start *			the real search from * * 	@last_block: *		the maximum block number that our goal reservable space *		could start from. This is normally the last block in this *		group. The search will end when we found the start of next *		possible reservable space is out of this boundary. *		This could handle the cross boundary reservation window *		request. * * 	basically we search from the given range, rather than the whole * 	reservation double linked list, (start_block, last_block) * 	to find a free region that is of my size and has not * 	been reserved. * */static int find_next_reservable_window(				struct ext2_reserve_window_node *search_head,				struct ext2_reserve_window_node *my_rsv,				struct super_block * sb,				ext2_fsblk_t start_block,				ext2_fsblk_t last_block){	struct rb_node *next;	struct ext2_reserve_window_node *rsv, *prev;	ext2_fsblk_t cur;	int size = my_rsv->rsv_goal_size;	/* TODO: make the start of the reservation window byte-aligned */	/* cur = *start_block & ~7;*/	cur = start_block;	rsv = search_head;	if (!rsv)		return -1;	while (1) {		if (cur <= rsv->rsv_end)			cur = rsv->rsv_end + 1;		/* TODO?		 * in the case we could not find a reservable space		 * that is what is expected, during the re-search, we could		 * remember what's the largest reservable space we could have		 * and return that one.		 *		 * For now it will fail if we could not find the reservable		 * space with expected-size (or more)...		 */		if (cur > last_block)			return -1;		/* fail */		prev = rsv;		next = rb_next(&rsv->rsv_node);		rsv = rb_entry(next,struct ext2_reserve_window_node,rsv_node);		/*		 * Reached the last reservation, we can just append to the		 * previous one.		 */		if (!next)			break;		if (cur + size <= rsv->rsv_start) {			/*			 * Found a reserveable space big enough.  We could			 * have a reservation across the group boundary here		 	 */			break;		}	}	/*	 * we come here either :	 * when we reach the end of the whole list,	 * and there is empty reservable space after last entry in the list.	 * append it to the end of the list.	 *	 * or we found one reservable space in the middle of the list,	 * return the reservation window that we could append to.	 * succeed.	 */	if ((prev != my_rsv) && (!rsv_is_empty(&my_rsv->rsv_window)))		rsv_window_remove(sb, my_rsv);	/*	 * Let's book the whole avaliable window for now.  We will check the	 * disk bitmap later and then, if there are free blocks then we adjust	 * the window size if it's larger than requested.	 * Otherwise, we will remove this node from the tree next time	 * call find_next_reservable_window.	 */	my_rsv->rsv_start = cur;	my_rsv->rsv_end = cur + size - 1;	my_rsv->rsv_alloc_hit = 0;	if (prev != my_rsv)		ext2_rsv_window_add(sb, my_rsv);	return 0;}/** * 	alloc_new_reservation()--allocate a new reservation window * *		To make a new reservation, we search part of the filesystem *		reservation list (the list that inside the group). We try to *		allocate a new reservation window near the allocation goal, *		or the beginning of the group, if there is no goal. * *		We first find a reservable space after the goal, then from *		there, we check the bitmap for the first free block after *		it. If there is no free block until the end of group, then the *		whole group is full, we failed. Otherwise, check if the free *		block is inside the expected reservable space, if so, we *		succeed. *		If the first free block is outside the reservable space, then *		start from the first free block, we search for next available *		space, and go on. * *	on succeed, a new reservation will be found and inserted into the list *	It contains at least one free block, and it does not overlap with other *	reservation windows. * *	failed: we failed to find a reservation window in this group * *	@rsv: the reservation * *	@grp_goal: The goal (group-relative).  It is where the search for a *		free reservable space should start from. *		if we have a goal(goal >0 ), then start from there, *		no goal(goal = -1), we start from the first block *		of the group. * *	@sb: the super block *	@group: the group we are trying to allocate in *	@bitmap_bh: the block group block bitmap * */static int alloc_new_reservation(struct ext2_reserve_window_node *my_rsv,		ext2_grpblk_t grp_goal, struct super_block *sb,		unsigned int group, struct buffer_head *bitmap_bh){	struct ext2_reserve_window_node *search_head;	ext2_fsblk_t group_first_block, group_end_block, start_block;	ext2_grpblk_t first_free_block;	struct rb_root *fs_rsv_root = &EXT2_SB(sb)->s_rsv_window_root;	unsigned long size;	int ret;	spinlock_t *rsv_lock = &EXT2_SB(sb)->s_rsv_window_lock;	group_first_block = ext2_group_first_block_no(sb, group);	group_end_block = group_first_block + (EXT2_BLOCKS_PER_GROUP(sb) - 1);	if (grp_goal < 0)		start_block = group_first_block;	else		start_block = grp_goal + group_first_block;	size = my_rsv->rsv_goal_size;	if (!rsv_is_empty(&my_rsv->rsv_window)) {		/*		 * if the old reservation is cross group boundary		 * and if the goal is inside the old reservation window,		 * we will come here when we just failed to allocate from		 * the first part of the window. We still have another part		 * that belongs to the next group. In this case, there is no		 * point to discard our window and try to allocate a new one		 * in this group(which will fail). we should		 * keep the reservation window, just simply move on.		 *		 * Maybe we could shift the start block of the reservation		 * window to the first block of next group.		 */		if ((my_rsv->rsv_start <= group_end_block) &&				(my_rsv->rsv_end > group_end_block) &&				(start_block >= my_rsv->rsv_start))			return -1;		if ((my_rsv->rsv_alloc_hit >		     (my_rsv->rsv_end - my_rsv->rsv_start + 1) / 2)) {			/*			 * if the previously allocation hit ratio is			 * greater than 1/2, then we double the size of			 * the reservation window the next time,			 * otherwise we keep the same size window			 */			size = size * 2;			if (size > EXT2_MAX_RESERVE_BLOCKS)				size = EXT2_MAX_RESERVE_BLOCKS;			my_rsv->rsv_goal_size= size;		}	}	spin_lock(rsv_lock);	/*	 * shift the search start to the window near the goal block	 */	search_head = search_reserve_window(fs_rsv_root, start_block);	/*	 * find_next_reservable_window() simply finds a reservable window	 * inside the given range(start_block, group_end_block).	 *	 * To make sure the reservation window has a free bit inside it, we	 * need to check the bitmap after we found a reservable window.	 */retry:	ret = find_next_reservable_window(search_head, my_rsv, sb,						start_block, group_end_block);	if (ret == -1) {		if (!rsv_is_empty(&my_rsv->rsv_window))			rsv_window_remove(sb, my_rsv);		spin_unlock(rsv_lock);		return -1;	}	/*	 * On success, find_next_reservable_window() returns the	 * reservation window where there is a reservable space after it.	 * Before we reserve this reservable space, we need	 * to make sure there is at least a free block inside this region.	 *	 * Search the first free bit on the block bitmap.  Search starts from	 * the start block of the reservable space we just found.	 */	spin_unlock(rsv_lock);	first_free_block = bitmap_search_next_usable_block(			my_rsv->rsv_start - group_first_block,			bitmap_bh, group_end_block - group_first_block + 1);	if (first_free_block < 0) {		/*		 * no free block left on the bitmap, no point		 * to reserve the space. return failed.		 */		spin_lock(rsv_lock);		if (!rsv_is_empty(&my_rsv->rsv_window))			rsv_window_remove(sb, my_rsv);		spin_unlock(rsv_lock);		return -1;		/* failed */	}	start_block = first_free_block + group_first_block;	/*	 * check if the first free block is within the	 * free space we just reserved	 */	if (start_block >= my_rsv->rsv_start && start_block <= my_rsv->rsv_end)		return 0;		/* success */	/*	 * if the first free bit we found is out of the reservable space	 * continue search for next reservable space,	 * start from where the free block is,	 * we also shift the list head to where we stopped last time	 */	search_head = my_rsv;	spin_lock(rsv_lock);	goto retry;}/** * try_to_extend_reservation() * @my_rsv:		given reservation window * @sb:			super block * @size:		the delta to extend * * Attempt to expand the reservation window large enough to have * required number of free blocks * * Since ext2_try_to_allocate() will always allocate blocks within * the reservation window range, if the window size is too small, * multiple blocks allocation has to stop at the end of the reservation * window. To make this more efficient, given the total number of * blocks needed and the current size of the window, we try to * expand the reservation window size if necessary on a best-effort * basis before ext2_new_blocks() tries to allocate blocks. */static void try_to_extend_reservation(struct ext2_reserve_window_node *my_rsv,			struct super_block *sb, int size)

⌨️ 快捷键说明

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