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

📄 balloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (UDF_SB_LVIDBH(sb)) {		UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =			cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)]) + count);		mark_buffer_dirty(UDF_SB_LVIDBH(sb));	}	start = bloc.logicalBlockNum + offset;	end = bloc.logicalBlockNum + offset + count - 1;	epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry);	elen = 0;	epos.block = oepos.block = UDF_I_LOCATION(table);	epos.bh = oepos.bh = NULL;	while (count &&	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {		if (((eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits)) == start)) {			if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) {				count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);				start += ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);				elen = (etype << 30) | (0x40000000 - sb->s_blocksize);			} else {				elen = (etype << 30) | (elen + (count << sb->s_blocksize_bits));				start += count;				count = 0;			}			udf_write_aext(table, &oepos, eloc, elen, 1);		} else if (eloc.logicalBlockNum == (end + 1)) {			if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) {				count -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);				end -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);				eloc.logicalBlockNum -= ((0x3FFFFFFF - elen) >> sb->s_blocksize_bits);				elen = (etype << 30) | (0x40000000 - sb->s_blocksize);			} else {				eloc.logicalBlockNum = start;				elen = (etype << 30) | (elen + (count << sb->s_blocksize_bits));				end -= count;				count = 0;			}			udf_write_aext(table, &oepos, eloc, elen, 1);		}		if (epos.bh != oepos.bh) {			i = -1;			oepos.block = epos.block;			brelse(oepos.bh);			get_bh(epos.bh);			oepos.bh = epos.bh;			oepos.offset = 0;		} else {			oepos.offset = epos.offset;		}	}	if (count) {		/*		 * NOTE: we CANNOT use udf_add_aext here, as it can try to allocate		 * a new block, and since we hold the super block lock already		 * very bad things would happen :)		 *		 * We copy the behavior of udf_add_aext, but instead of		 * trying to allocate a new block close to the existing one,		 * we just steal a block from the extent we are trying to add.		 *		 * It would be nice if the blocks were close together, but it		 * isn't required.		 */		int adsize;		short_ad *sad = NULL;		long_ad *lad = NULL;		struct allocExtDesc *aed;		eloc.logicalBlockNum = start;		elen = EXT_RECORDED_ALLOCATED |			(count << sb->s_blocksize_bits);		if (UDF_I_ALLOCTYPE(table) == ICBTAG_FLAG_AD_SHORT) {			adsize = sizeof(short_ad);		} else if (UDF_I_ALLOCTYPE(table) == ICBTAG_FLAG_AD_LONG) {			adsize = sizeof(long_ad);		} else {			brelse(oepos.bh);			brelse(epos.bh);			goto error_return;		}		if (epos.offset + (2 * adsize) > sb->s_blocksize) {			char *sptr, *dptr;			int loffset;			brelse(oepos.bh);			oepos = epos;			/* Steal a block from the extent being free'd */			epos.block.logicalBlockNum = eloc.logicalBlockNum;			eloc.logicalBlockNum++;			elen -= sb->s_blocksize;			if (!(epos.bh = udf_tread(sb, udf_get_lb_pblock(sb, epos.block, 0)))) {				brelse(oepos.bh);				goto error_return;			}			aed = (struct allocExtDesc *)(epos.bh->b_data);			aed->previousAllocExtLocation = cpu_to_le32(oepos.block.logicalBlockNum);			if (epos.offset + adsize > sb->s_blocksize) {				loffset = epos.offset;				aed->lengthAllocDescs = cpu_to_le32(adsize);				sptr = UDF_I_DATA(table) + epos.offset - adsize;				dptr = epos.bh->b_data + sizeof(struct allocExtDesc);				memcpy(dptr, sptr, adsize);				epos.offset = sizeof(struct allocExtDesc) + adsize;			} else {				loffset = epos.offset + adsize;				aed->lengthAllocDescs = cpu_to_le32(0);				if (oepos.bh) {					sptr = oepos.bh->b_data + epos.offset;					aed = (struct allocExtDesc *)oepos.bh->b_data;					aed->lengthAllocDescs =						cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);				} else {					sptr = UDF_I_DATA(table) + epos.offset;					UDF_I_LENALLOC(table) += adsize;					mark_inode_dirty(table);				}				epos.offset = sizeof(struct allocExtDesc);			}			if (UDF_SB_UDFREV(sb) >= 0x0200)				udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 3, 1,					    epos.block.logicalBlockNum, sizeof(tag));			else				udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 2, 1,					    epos.block.logicalBlockNum, sizeof(tag));			switch (UDF_I_ALLOCTYPE(table)) {				case ICBTAG_FLAG_AD_SHORT:					sad = (short_ad *)sptr;					sad->extLength = cpu_to_le32(						EXT_NEXT_EXTENT_ALLOCDECS |						sb->s_blocksize);					sad->extPosition = cpu_to_le32(epos.block.logicalBlockNum);					break;				case ICBTAG_FLAG_AD_LONG:					lad = (long_ad *)sptr;					lad->extLength = cpu_to_le32(						EXT_NEXT_EXTENT_ALLOCDECS |						sb->s_blocksize);					lad->extLocation = cpu_to_lelb(epos.block);					break;			}			if (oepos.bh) {				udf_update_tag(oepos.bh->b_data, loffset);				mark_buffer_dirty(oepos.bh);			} else {				mark_inode_dirty(table);			}		}		if (elen) { /* It's possible that stealing the block emptied the extent */			udf_write_aext(table, &epos, eloc, elen, 1);			if (!epos.bh) {				UDF_I_LENALLOC(table) += adsize;				mark_inode_dirty(table);			} else {				aed = (struct allocExtDesc *)epos.bh->b_data;				aed->lengthAllocDescs =					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);				udf_update_tag(epos.bh->b_data, epos.offset);				mark_buffer_dirty(epos.bh);			}		}	}	brelse(epos.bh);	brelse(oepos.bh);error_return:	sb->s_dirt = 1;	mutex_unlock(&sbi->s_alloc_mutex);	return;}static int udf_table_prealloc_blocks(struct super_block *sb,				     struct inode *inode,				     struct inode *table, uint16_t partition,				     uint32_t first_block, uint32_t block_count){	struct udf_sb_info *sbi = UDF_SB(sb);	int alloc_count = 0;	uint32_t elen, adsize;	kernel_lb_addr eloc;	struct extent_position epos;	int8_t etype = -1;	if (first_block < 0 || first_block >= UDF_SB_PARTLEN(sb, partition))		return 0;	if (UDF_I_ALLOCTYPE(table) == ICBTAG_FLAG_AD_SHORT)		adsize = sizeof(short_ad);	else if (UDF_I_ALLOCTYPE(table) == ICBTAG_FLAG_AD_LONG)		adsize = sizeof(long_ad);	else		return 0;	mutex_lock(&sbi->s_alloc_mutex);	epos.offset = sizeof(struct unallocSpaceEntry);	epos.block = UDF_I_LOCATION(table);	epos.bh = NULL;	eloc.logicalBlockNum = 0xFFFFFFFF;	while (first_block != eloc.logicalBlockNum &&	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {		udf_debug("eloc=%d, elen=%d, first_block=%d\n",			  eloc.logicalBlockNum, elen, first_block);		; /* empty loop body */	}	if (first_block == eloc.logicalBlockNum) {		epos.offset -= adsize;		alloc_count = (elen >> sb->s_blocksize_bits);		if (inode && DQUOT_PREALLOC_BLOCK(inode, alloc_count > block_count ? block_count : alloc_count)) {			alloc_count = 0;		} else if (alloc_count > block_count) {			alloc_count = block_count;			eloc.logicalBlockNum += alloc_count;			elen -= (alloc_count << sb->s_blocksize_bits);			udf_write_aext(table, &epos, eloc, (etype << 30) | elen, 1);		} else {			udf_delete_aext(table, epos, eloc, (etype << 30) | elen);		}	} else {		alloc_count = 0;	}	brelse(epos.bh);	if (alloc_count && UDF_SB_LVIDBH(sb)) {		UDF_SB_LVID(sb)->freeSpaceTable[partition] =			cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition]) - alloc_count);		mark_buffer_dirty(UDF_SB_LVIDBH(sb));		sb->s_dirt = 1;	}	mutex_unlock(&sbi->s_alloc_mutex);	return alloc_count;}static int udf_table_new_block(struct super_block *sb,			       struct inode *inode,			       struct inode *table, uint16_t partition,			       uint32_t goal, int *err){	struct udf_sb_info *sbi = UDF_SB(sb);	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;	uint32_t newblock = 0, adsize;	uint32_t elen, goal_elen = 0;	kernel_lb_addr eloc, uninitialized_var(goal_eloc);	struct extent_position epos, goal_epos;	int8_t etype;	*err = -ENOSPC;	if (UDF_I_ALLOCTYPE(table) == ICBTAG_FLAG_AD_SHORT)		adsize = sizeof(short_ad);	else if (UDF_I_ALLOCTYPE(table) == ICBTAG_FLAG_AD_LONG)		adsize = sizeof(long_ad);	else		return newblock;	mutex_lock(&sbi->s_alloc_mutex);	if (goal < 0 || goal >= UDF_SB_PARTLEN(sb, partition))		goal = 0;	/* We search for the closest matching block to goal. If we find a exact hit,	   we stop. Otherwise we keep going till we run out of extents.	   We store the buffer_head, bloc, and extoffset of the current closest	   match and use that when we are done.	 */	epos.offset = sizeof(struct unallocSpaceEntry);	epos.block = UDF_I_LOCATION(table);	epos.bh = goal_epos.bh = NULL;	while (spread &&	       (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) {		if (goal >= eloc.logicalBlockNum) {			if (goal < eloc.logicalBlockNum + (elen >> sb->s_blocksize_bits))				nspread = 0;			else				nspread = goal - eloc.logicalBlockNum -					(elen >> sb->s_blocksize_bits);		} else {			nspread = eloc.logicalBlockNum - goal;		}		if (nspread < spread) {			spread = nspread;			if (goal_epos.bh != epos.bh) {				brelse(goal_epos.bh);				goal_epos.bh = epos.bh;				get_bh(goal_epos.bh);			}			goal_epos.block = epos.block;			goal_epos.offset = epos.offset - adsize;			goal_eloc = eloc;			goal_elen = (etype << 30) | elen;		}	}	brelse(epos.bh);	if (spread == 0xFFFFFFFF) {		brelse(goal_epos.bh);		mutex_unlock(&sbi->s_alloc_mutex);		return 0;	}	/* Only allocate blocks from the beginning of the extent.	   That way, we only delete (empty) extents, never have to insert an	   extent because of splitting */	/* This works, but very poorly.... */	newblock = goal_eloc.logicalBlockNum;	goal_eloc.logicalBlockNum++;	goal_elen -= sb->s_blocksize;	if (inode && DQUOT_ALLOC_BLOCK(inode, 1)) {		brelse(goal_epos.bh);		mutex_unlock(&sbi->s_alloc_mutex);		*err = -EDQUOT;		return 0;	}	if (goal_elen)		udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1);	else		udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);	brelse(goal_epos.bh);	if (UDF_SB_LVIDBH(sb)) {		UDF_SB_LVID(sb)->freeSpaceTable[partition] =			cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[partition]) - 1);		mark_buffer_dirty(UDF_SB_LVIDBH(sb));	}	sb->s_dirt = 1;	mutex_unlock(&sbi->s_alloc_mutex);	*err = 0;	return newblock;}inline void udf_free_blocks(struct super_block *sb,			    struct inode *inode,			    kernel_lb_addr bloc, uint32_t offset,			    uint32_t count){	uint16_t partition = bloc.partitionReferenceNum;	if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) {		return udf_bitmap_free_blocks(sb, inode,					      UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,					      bloc, offset, count);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) {		return udf_table_free_blocks(sb, inode,					     UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_table,					     bloc, offset, count);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_BITMAP) {		return udf_bitmap_free_blocks(sb, inode,					      UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_bitmap,					      bloc, offset, count);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_TABLE) {		return udf_table_free_blocks(sb, inode,					     UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_table,					     bloc, offset, count);	} else {		return;	}}inline int udf_prealloc_blocks(struct super_block *sb,			       struct inode *inode,			       uint16_t partition, uint32_t first_block,			       uint32_t block_count){	if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) {		return udf_bitmap_prealloc_blocks(sb, inode,						  UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,						  partition, first_block, block_count);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) {		return udf_table_prealloc_blocks(sb, inode,						 UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_table,						 partition, first_block, block_count);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_BITMAP) {		return udf_bitmap_prealloc_blocks(sb, inode,						  UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_bitmap,						  partition, first_block, block_count);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_TABLE) {		return udf_table_prealloc_blocks(sb, inode,						 UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_table,						 partition, first_block, block_count);	} else {		return 0;	}}inline int udf_new_block(struct super_block *sb,			 struct inode *inode,			 uint16_t partition, uint32_t goal, int *err){	int ret;	if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP) {		ret = udf_bitmap_new_block(sb, inode,					   UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,					   partition, goal, err);		return ret;	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_TABLE) {		return udf_table_new_block(sb, inode,					   UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_table,					   partition, goal, err);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_BITMAP) {		return udf_bitmap_new_block(sb, inode,					    UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_bitmap,					    partition, goal, err);	} else if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_FREED_TABLE) {		return udf_table_new_block(sb, inode,					   UDF_SB_PARTMAPS(sb)[partition].s_fspace.s_table,					   partition, goal, err);	} else {		*err = -EIO;		return 0;	}}

⌨️ 快捷键说明

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