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

📄 inode.c

📁 这是Linux系统下的对UDF文件系统新增的功能
💻 C
📖 第 1 页 / 共 4 页
字号:
	udf_release_data(bh);	return err;}/* * udf_iget * * PURPOSE *	Get an inode. * * DESCRIPTION *	This routine replaces iget() and read_inode(). * * HISTORY *	October 3, 1997 - Andrew E. Mileski *	Written, tested, and released. * * 12/19/98 dgb  Added semaphore and changed to be a wrapper of iget */struct inode *udf_iget(struct super_block *sb, lb_addr ino){	struct inode *inode;	unsigned long block;	block = udf_get_lb_pblock(sb, ino, 0);	/* Get the inode */	inode = iget(sb, block);		/* calls udf_read_inode() ! */	if (!inode)	{		printk(KERN_ERR "udf: iget() failed\n");		return NULL;	}	else if (is_bad_inode(inode))	{		iput(inode);		return NULL;	}	else if (UDF_I_LOCATION(inode).logicalBlockNum == 0xFFFFFFFF &&		UDF_I_LOCATION(inode).partitionReferenceNum == 0xFFFF)	{		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(lb_addr));		__udf_read_inode(inode);		if (is_bad_inode(inode))		{			iput(inode);			return NULL;		}	}	if ( ino.logicalBlockNum >= UDF_SB_PARTLEN(sb, ino.partitionReferenceNum) )	{		udf_debug("block=%d, partition=%d out of range\n",			ino.logicalBlockNum, ino.partitionReferenceNum);		make_bad_inode(inode);		iput(inode);		return NULL; 	}	return inode;}int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,	lb_addr eloc, uint32_t elen, struct buffer_head **bh, int inc){	int adsize;	short_ad *sad = NULL;	long_ad *lad = NULL;	struct allocExtDesc *aed;	int8_t etype;	uint8_t *ptr;	if (!*bh)		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);	else		ptr = (*bh)->b_data + *extoffset;	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)		adsize = sizeof(short_ad);	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)		adsize = sizeof(long_ad);	else		return -1;	if (*extoffset + (2 * adsize) > inode->i_sb->s_blocksize)	{		char *sptr, *dptr;		struct buffer_head *nbh;		int err, loffset;		lb_addr obloc = *bloc;		if (!(bloc->logicalBlockNum = udf_new_block(inode->i_sb, NULL,			obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))		{			return -1;		}		if (!(nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb,			*bloc, 0))))		{			return -1;		}		lock_buffer(nbh);		memset(nbh->b_data, 0x00, inode->i_sb->s_blocksize);		set_buffer_uptodate(nbh);		unlock_buffer(nbh);		mark_buffer_dirty_inode(nbh, inode);		aed = (struct allocExtDesc *)(nbh->b_data);		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT))			aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);		if (*extoffset + adsize > inode->i_sb->s_blocksize)		{			loffset = *extoffset;			aed->lengthAllocDescs = cpu_to_le32(adsize);			sptr = ptr - adsize;			dptr = nbh->b_data + sizeof(struct allocExtDesc);			memcpy(dptr, sptr, adsize);			*extoffset = sizeof(struct allocExtDesc) + adsize;		}		else		{			loffset = *extoffset + adsize;			aed->lengthAllocDescs = cpu_to_le32(0);			sptr = ptr;			*extoffset = sizeof(struct allocExtDesc);			if (*bh)			{				aed = (struct allocExtDesc *)(*bh)->b_data;				aed->lengthAllocDescs =					cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);			}			else			{				UDF_I_LENALLOC(inode) += adsize;				mark_inode_dirty(inode);			}		}		if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1,				bloc->logicalBlockNum, sizeof(tag));		else			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,				bloc->logicalBlockNum, sizeof(tag));		switch (UDF_I_ALLOCTYPE(inode))		{			case ICBTAG_FLAG_AD_SHORT:			{				sad = (short_ad *)sptr;				sad->extLength = cpu_to_le32(					EXT_NEXT_EXTENT_ALLOCDECS |					inode->i_sb->s_blocksize);				sad->extPosition = cpu_to_le32(bloc->logicalBlockNum);				break;			}			case ICBTAG_FLAG_AD_LONG:			{				lad = (long_ad *)sptr;				lad->extLength = cpu_to_le32(					EXT_NEXT_EXTENT_ALLOCDECS |					inode->i_sb->s_blocksize);				lad->extLocation = cpu_to_lelb(*bloc);				memset(lad->impUse, 0x00, sizeof(lad->impUse));				break;			}		}		if (*bh)		{			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)				udf_update_tag((*bh)->b_data, loffset);			else				udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));			mark_buffer_dirty_inode(*bh, inode);			udf_release_data(*bh);		}		else			mark_inode_dirty(inode);		*bh = nbh;	}	etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);	if (!*bh)	{		UDF_I_LENALLOC(inode) += adsize;		mark_inode_dirty(inode);	}	else	{		aed = (struct allocExtDesc *)(*bh)->b_data;		aed->lengthAllocDescs =			cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)			udf_update_tag((*bh)->b_data, *extoffset + (inc ? 0 : adsize));		else			udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));		mark_buffer_dirty_inode(*bh, inode);	}	return etype;}int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,    lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc){	int adsize;	uint8_t *ptr;	if (!bh)		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);	else	{		ptr = bh->b_data + *extoffset;		atomic_inc(&bh->b_count);	}	switch (UDF_I_ALLOCTYPE(inode))	{		case ICBTAG_FLAG_AD_SHORT:		{			short_ad *sad = (short_ad *)ptr;			sad->extLength = cpu_to_le32(elen);			sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);			adsize = sizeof(short_ad);			break;		}		case ICBTAG_FLAG_AD_LONG:		{			long_ad *lad = (long_ad *)ptr;			lad->extLength = cpu_to_le32(elen);			lad->extLocation = cpu_to_lelb(eloc);			memset(lad->impUse, 0x00, sizeof(lad->impUse));			adsize = sizeof(long_ad);			break;		}		default:			return -1;	}	if (bh)	{		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)		{			struct allocExtDesc *aed = (struct allocExtDesc *)(bh)->b_data;			udf_update_tag((bh)->b_data,				le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));		}		mark_buffer_dirty_inode(bh, inode);		udf_release_data(bh);	}	else		mark_inode_dirty(inode);	if (inc)		*extoffset += adsize;	return (elen >> 30);}int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc){	int8_t etype;	while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==		(EXT_NEXT_EXTENT_ALLOCDECS >> 30))	{		*bloc = *eloc;		*extoffset = sizeof(struct allocExtDesc);		udf_release_data(*bh);		if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))		{			udf_debug("reading block %d failed!\n",				udf_get_lb_pblock(inode->i_sb, *bloc, 0));			return -1;		}	}	return etype;}int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,	lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc){	int alen;	int8_t etype;	uint8_t *ptr;	if (!*bh)	{		if (!(*extoffset))			*extoffset = udf_file_entry_alloc_offset(inode);		ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);		alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);	}	else	{		if (!(*extoffset))			*extoffset = sizeof(struct allocExtDesc);		ptr = (*bh)->b_data + *extoffset;		alen = sizeof(struct allocExtDesc) + le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);	}	switch (UDF_I_ALLOCTYPE(inode))	{		case ICBTAG_FLAG_AD_SHORT:		{			short_ad *sad;			if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))				return -1;			etype = le32_to_cpu(sad->extLength) >> 30;			eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);			eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;			*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;			break;		}		case ICBTAG_FLAG_AD_LONG:		{			long_ad *lad;			if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))				return -1;			etype = le32_to_cpu(lad->extLength) >> 30;			*eloc = lelb_to_cpu(lad->extLocation);			*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;			break;		}		default:		{			udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));			return -1;		}	}	return etype;}int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,	lb_addr neloc, uint32_t nelen, struct buffer_head *bh){	lb_addr oeloc;	uint32_t oelen;	int8_t etype;	if (bh)		atomic_inc(&bh->b_count);	while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)	{		udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 1);		neloc = oeloc;		nelen = (etype << 30) | oelen;	}	udf_add_aext(inode, &bloc, &extoffset, neloc, nelen, &bh, 1);	udf_release_data(bh);	return (nelen >> 30);}int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,	lb_addr eloc, uint32_t elen, struct buffer_head *nbh){	struct buffer_head *obh;	lb_addr obloc;	int oextoffset, adsize;	int8_t etype;	struct allocExtDesc *aed;	if (nbh)	{		atomic_inc(&nbh->b_count);		atomic_inc(&nbh->b_count);	}	if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)		adsize = sizeof(short_ad);	else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)		adsize = sizeof(long_ad);	else		adsize = 0;	obh = nbh;	obloc = nbloc;	oextoffset = nextoffset;	if (udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1) == -1)		return -1;	while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)	{		udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);		if (obh != nbh)		{			obloc = nbloc;			udf_release_data(obh);			atomic_inc(&nbh->b_count);			obh = nbh;			oextoffset = nextoffset - adsize;		}	}	memset(&eloc, 0x00, sizeof(lb_addr));	elen = 0;	if (nbh != obh)	{		udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);		if (!obh)		{			UDF_I_LENALLOC(inode) -= (adsize * 2);			mark_inode_dirty(inode);		}		else		{			aed = (struct allocExtDesc *)(obh)->b_data;			aed->lengthAllocDescs =				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - (2*adsize));			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)				udf_update_tag((obh)->b_data, oextoffset - (2*adsize));			else				udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));			mark_buffer_dirty_inode(obh, inode);		}	}	else	{		udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);		if (!obh)		{			UDF_I_LENALLOC(inode) -= adsize;			mark_inode_dirty(inode);		}		else		{			aed = (struct allocExtDesc *)(obh)->b_data;			aed->lengthAllocDescs =				cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) - adsize);			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)				udf_update_tag((obh)->b_data, oextoffset - adsize);			else				udf_update_tag((obh)->b_data, sizeof(struct allocExtDesc));			mark_buffer_dirty_inode(obh, inode);		}	}		udf_release_data(nbh);	udf_release_data(obh);	return (elen >> 30);}int8_t inode_bmap(struct inode *inode, int block, lb_addr *bloc, uint32_t *extoffset,	lb_addr *eloc, uint32_t *elen, uint32_t *offset, struct buffer_head **bh){	uint64_t lbcount = 0, bcount = (uint64_t)block << inode->i_sb->s_blocksize_bits;	int8_t etype;	if (block < 0)	{		printk(KERN_ERR "udf: inode_bmap: block < 0\n");		return -1;	}	if (!inode)	{		printk(KERN_ERR "udf: inode_bmap: NULL inode\n");		return -1;	}	*extoffset = 0;	*elen = 0;	*bloc = UDF_I_LOCATION(inode);	do	{		if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)		{			*offset = bcount - lbcount;			UDF_I_LENEXTENTS(inode) = lbcount;			return -1;		}		lbcount += *elen;	} while (lbcount <= bcount);	*offset = bcount + *elen - lbcount;	return etype;}long udf_block_map(struct inode *inode, long block){	lb_addr eloc, bloc;	uint32_t offset, extoffset, elen;	struct buffer_head *bh = NULL;	int ret;	lock_kernel();	if (inode_bmap(inode, block, &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))		ret = udf_get_lb_pblock(inode->i_sb, eloc, offset >> inode->i_sb->s_blocksize_bits);	else		ret = 0;	unlock_kernel();	udf_release_data(bh);	if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))		return udf_fixed_to_variable(ret);	else		return ret;}

⌨️ 快捷键说明

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