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

📄 balloc.c

📁 这是Linux系统下的对UDF文件系统新增的功能
💻 C
📖 第 1 页 / 共 2 页
字号:
			{				elen = (etype << 30) |					(elen + (count << sb->s_blocksize_bits));				start += count;				count = 0;			}			udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 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, obloc, &oextoffset, eloc, elen, obh, 1);		}		if (nbh != obh)		{			i = -1;			obloc = nbloc;			udf_release_data(obh);			atomic_inc(&nbh->b_count);			obh = nbh;			oextoffset = 0;		}		else			oextoffset = nextoffset;	}	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		{			udf_release_data(obh);			udf_release_data(nbh);			goto error_return;		}		if (nextoffset + (2 * adsize) > sb->s_blocksize)		{			char *sptr, *dptr;			int loffset;				udf_release_data(obh);			obh = nbh;			obloc = nbloc;			oextoffset = nextoffset;			/* Steal a block from the extent being free'd */			nbloc.logicalBlockNum = eloc.logicalBlockNum;			eloc.logicalBlockNum ++;			elen -= sb->s_blocksize;			if (!(nbh = udf_tread(sb,				udf_get_lb_pblock(sb, nbloc, 0))))			{				udf_release_data(obh);				goto error_return;			}			aed = (struct allocExtDesc *)(nbh->b_data);			aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);			if (nextoffset + adsize > sb->s_blocksize)			{				loffset = nextoffset;				aed->lengthAllocDescs = cpu_to_le32(adsize);				if (obh)					sptr = UDF_I_DATA(inode) + nextoffset -  udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;				else					sptr = obh->b_data + nextoffset - adsize;				dptr = nbh->b_data + sizeof(struct allocExtDesc);				memcpy(dptr, sptr, adsize);				nextoffset = sizeof(struct allocExtDesc) + adsize;			}			else			{				loffset = nextoffset + adsize;				aed->lengthAllocDescs = cpu_to_le32(0);				sptr = (obh)->b_data + nextoffset;				nextoffset = sizeof(struct allocExtDesc);				if (obh)				{					aed = (struct allocExtDesc *)(obh)->b_data;					aed->lengthAllocDescs =						cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);				}				else				{					UDF_I_LENALLOC(table) += adsize;					mark_inode_dirty(table);				}			}			if (UDF_SB_UDFREV(sb) >= 0x0200)				udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,					nbloc.logicalBlockNum, sizeof(tag));			else				udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,					nbloc.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(nbloc.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(nbloc);					break;				}			}			if (obh)			{				udf_update_tag(obh->b_data, loffset);				mark_buffer_dirty(obh);			}			else				mark_inode_dirty(table);		}		if (elen) /* It's possible that stealing the block emptied the extent */		{			udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);			if (!nbh)			{				UDF_I_LENALLOC(table) += adsize;				mark_inode_dirty(table);			}			else			{				aed = (struct allocExtDesc *)nbh->b_data;				aed->lengthAllocDescs =					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);				udf_update_tag(nbh->b_data, nextoffset);				mark_buffer_dirty(nbh);			}		}	}	udf_release_data(nbh);	udf_release_data(obh);error_return:	sb->s_dirt = 1;	unlock_kernel();	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){	int alloc_count = 0;	uint32_t extoffset, elen, adsize;	lb_addr bloc, eloc;	struct buffer_head *bh;	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;	lock_kernel();	extoffset = sizeof(struct unallocSpaceEntry);	bloc = UDF_I_LOCATION(table);	bh = NULL;	eloc.logicalBlockNum = 0xFFFFFFFF;	while (first_block != eloc.logicalBlockNum && (etype =		udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 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)	{		extoffset -= 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, bloc, &extoffset, eloc, (etype << 30) | elen, bh, 1);		}		else			udf_delete_aext(table, bloc, extoffset, eloc, (etype << 30) | elen, bh);	}	else		alloc_count = 0;	udf_release_data(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;	}	unlock_kernel();	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){	uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF;	uint32_t newblock = 0, adsize;	uint32_t extoffset, goal_extoffset, elen, goal_elen = 0;	lb_addr bloc, goal_bloc, eloc, goal_eloc;	struct buffer_head *bh, *goal_bh;	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;	lock_kernel();	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.	*/	extoffset = sizeof(struct unallocSpaceEntry);	bloc = UDF_I_LOCATION(table);	goal_bh = bh = NULL;	while (spread && (etype =		udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 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_bh != bh)			{				udf_release_data(goal_bh);				goal_bh = bh;				atomic_inc(&goal_bh->b_count);			}			goal_bloc = bloc;			goal_extoffset = extoffset - adsize;			goal_eloc = eloc;			goal_elen = (etype << 30) | elen;		}	}	udf_release_data(bh);	if (spread == 0xFFFFFFFF)	{		udf_release_data(goal_bh);		unlock_kernel();		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))	{		udf_release_data(goal_bh);		unlock_kernel();		*err = -EDQUOT;		return 0;	}	if (goal_elen)		udf_write_aext(table, goal_bloc, &goal_extoffset, goal_eloc, goal_elen, goal_bh, 1);	else		udf_delete_aext(table, goal_bloc, goal_extoffset, goal_eloc, goal_elen, goal_bh);	udf_release_data(goal_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;	unlock_kernel();	*err = 0;	return newblock;}inline void udf_free_blocks(struct super_block * sb,	struct inode * inode,	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){	if (UDF_SB_PARTFLAGS(sb, partition) & UDF_PART_FLAG_UNALLOC_BITMAP)	{		return udf_bitmap_new_block(sb, inode,			UDF_SB_PARTMAPS(sb)[partition].s_uspace.s_bitmap,			partition, goal, err);	}	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 + -