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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);		efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;		efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;		efe->uniqueID = cpu_to_le64(UDF_I_UNIQUE(inode));		efe->lengthExtendedAttr = cpu_to_le32(UDF_I_LENEATTR(inode));		efe->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));		efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);		crclen = sizeof(struct extendedFileEntry);	}	if (UDF_I_STRAT4096(inode)) {		fe->icbTag.strategyType = cpu_to_le16(4096);		fe->icbTag.strategyParameter = cpu_to_le16(1);		fe->icbTag.numEntries = cpu_to_le16(2);	} else {		fe->icbTag.strategyType = cpu_to_le16(4);		fe->icbTag.numEntries = cpu_to_le16(1);	}	if (S_ISDIR(inode->i_mode))		fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY;	else if (S_ISREG(inode->i_mode))		fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR;	else if (S_ISLNK(inode->i_mode))		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SYMLINK;	else if (S_ISBLK(inode->i_mode))		fe->icbTag.fileType = ICBTAG_FILE_TYPE_BLOCK;	else if (S_ISCHR(inode->i_mode))		fe->icbTag.fileType = ICBTAG_FILE_TYPE_CHAR;	else if (S_ISFIFO(inode->i_mode))		fe->icbTag.fileType = ICBTAG_FILE_TYPE_FIFO;	else if (S_ISSOCK(inode->i_mode))		fe->icbTag.fileType = ICBTAG_FILE_TYPE_SOCKET;	icbflags =	UDF_I_ALLOCTYPE(inode) |			((inode->i_mode & S_ISUID) ? ICBTAG_FLAG_SETUID : 0) |			((inode->i_mode & S_ISGID) ? ICBTAG_FLAG_SETGID : 0) |			((inode->i_mode & S_ISVTX) ? ICBTAG_FLAG_STICKY : 0) |			(le16_to_cpu(fe->icbTag.flags) &				~(ICBTAG_FLAG_AD_MASK | ICBTAG_FLAG_SETUID |				ICBTAG_FLAG_SETGID | ICBTAG_FLAG_STICKY));	fe->icbTag.flags = cpu_to_le16(icbflags);	if (UDF_SB_UDFREV(inode->i_sb) >= 0x0200)		fe->descTag.descVersion = cpu_to_le16(3);	else		fe->descTag.descVersion = cpu_to_le16(2);	fe->descTag.tagSerialNum = cpu_to_le16(UDF_SB_SERIALNUM(inode->i_sb));	fe->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);	crclen += UDF_I_LENEATTR(inode) + UDF_I_LENALLOC(inode) - sizeof(tag);	fe->descTag.descCRCLength = cpu_to_le16(crclen);	fe->descTag.descCRC = cpu_to_le16(udf_crc((char *)fe + sizeof(tag), crclen, 0));	fe->descTag.tagChecksum = 0;	for (i = 0; i < 16; i++) {		if (i != 4)			fe->descTag.tagChecksum += ((uint8_t *)&(fe->descTag))[i];	}	/* write the data blocks */	mark_buffer_dirty(bh);	if (do_sync) {		sync_dirty_buffer(bh);		if (buffer_req(bh) && !buffer_uptodate(bh)) {			printk("IO error syncing udf inode [%s:%08lx]\n",			       inode->i_sb->s_id, inode->i_ino);			err = -EIO;		}	}	brelse(bh);	return err;}struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino){	unsigned long block = udf_get_lb_pblock(sb, ino, 0);	struct inode *inode = iget_locked(sb, block);	if (!inode)		return NULL;	if (inode->i_state & I_NEW) {		memcpy(&UDF_I_LOCATION(inode), &ino, sizeof(kernel_lb_addr));		__udf_read_inode(inode);		unlock_new_inode(inode);	}	if (is_bad_inode(inode))		goto out_iput;	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);		goto out_iput;	}	return inode; out_iput:	iput(inode);	return NULL;}int8_t udf_add_aext(struct inode * inode, struct extent_position * epos,		    kernel_lb_addr eloc, uint32_t elen, int inc){	int adsize;	short_ad *sad = NULL;	long_ad *lad = NULL;	struct allocExtDesc *aed;	int8_t etype;	uint8_t *ptr;	if (!epos->bh)		ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);	else		ptr = epos->bh->b_data + epos->offset;	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 (epos->offset + (2 * adsize) > inode->i_sb->s_blocksize) {		char *sptr, *dptr;		struct buffer_head *nbh;		int err, loffset;		kernel_lb_addr obloc = epos->block;		if (!(epos->block.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,								       epos->block, 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 (epos->offset + adsize > inode->i_sb->s_blocksize) {			loffset = epos->offset;			aed->lengthAllocDescs = cpu_to_le32(adsize);			sptr = ptr - adsize;			dptr = nbh->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);			sptr = ptr;			epos->offset = sizeof(struct allocExtDesc);			if (epos->bh) {				aed = (struct allocExtDesc *)epos->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,				    epos->block.logicalBlockNum, sizeof(tag));		else			udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1,				    epos->block.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(epos->block.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(epos->block);			memset(lad->impUse, 0x00, sizeof(lad->impUse));			break;		}		if (epos->bh) {			if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||			    UDF_SB_UDFREV(inode->i_sb) >= 0x0201)				udf_update_tag(epos->bh->b_data, loffset);			else				udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));			mark_buffer_dirty_inode(epos->bh, inode);			brelse(epos->bh);		} else {			mark_inode_dirty(inode);		}		epos->bh = nbh;	}	etype = udf_write_aext(inode, epos, eloc, elen, inc);	if (!epos->bh) {		UDF_I_LENALLOC(inode) += adsize;		mark_inode_dirty(inode);	} else {		aed = (struct allocExtDesc *)epos->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(epos->bh->b_data, epos->offset + (inc ? 0 : adsize));		else			udf_update_tag(epos->bh->b_data, sizeof(struct allocExtDesc));		mark_buffer_dirty_inode(epos->bh, inode);	}	return etype;}int8_t udf_write_aext(struct inode * inode, struct extent_position * epos,		      kernel_lb_addr eloc, uint32_t elen, int inc){	int adsize;	uint8_t *ptr;	short_ad *sad;	long_ad *lad;	if (!epos->bh)		ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);	else		ptr = epos->bh->b_data + epos->offset;	switch (UDF_I_ALLOCTYPE(inode)) {	case ICBTAG_FLAG_AD_SHORT:		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:		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 (epos->bh) {		if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) ||		    UDF_SB_UDFREV(inode->i_sb) >= 0x0201) {			struct allocExtDesc *aed = (struct allocExtDesc *)epos->bh->b_data;			udf_update_tag(epos->bh->b_data,				       le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));		}		mark_buffer_dirty_inode(epos->bh, inode);	} else {		mark_inode_dirty(inode);	}	if (inc)		epos->offset += adsize;	return (elen >> 30);}int8_t udf_next_aext(struct inode * inode, struct extent_position * epos,		     kernel_lb_addr * eloc, uint32_t * elen, int inc){	int8_t etype;	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==	       (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {		epos->block = *eloc;		epos->offset = sizeof(struct allocExtDesc);		brelse(epos->bh);		if (!(epos->bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, epos->block, 0)))) {			udf_debug("reading block %d failed!\n",				  udf_get_lb_pblock(inode->i_sb, epos->block, 0));			return -1;		}	}	return etype;}int8_t udf_current_aext(struct inode * inode, struct extent_position * epos,			kernel_lb_addr * eloc, uint32_t * elen, int inc){	int alen;	int8_t etype;	uint8_t *ptr;	short_ad *sad;	long_ad *lad;	if (!epos->bh) {		if (!epos->offset)			epos->offset = udf_file_entry_alloc_offset(inode);		ptr = UDF_I_DATA(inode) + epos->offset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);		alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);	} else {		if (!epos->offset)			epos->offset = sizeof(struct allocExtDesc);		ptr = epos->bh->b_data + epos->offset;		alen = sizeof(struct allocExtDesc) +			le32_to_cpu(((struct allocExtDesc *)epos->bh->b_data)->lengthAllocDescs);	}	switch (UDF_I_ALLOCTYPE(inode)) {	case ICBTAG_FLAG_AD_SHORT:		if (!(sad = udf_get_fileshortad(ptr, alen, &epos->offset, 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:		if (!(lad = udf_get_filelongad(ptr, alen, &epos->offset, 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;}static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos,			      kernel_lb_addr neloc, uint32_t nelen){	kernel_lb_addr oeloc;	uint32_t oelen;	int8_t etype;	if (epos.bh)		get_bh(epos.bh);	while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) {		udf_write_aext(inode, &epos, neloc, nelen, 1);		neloc = oeloc;		nelen = (etype << 30) | oelen;	}	udf_add_aext(inode, &epos, neloc, nelen, 1);	brelse(epos.bh);	return (nelen >> 30);}int8_t udf_delete_aext(struct inode * inode, struct extent_position epos,		       kernel_lb_addr eloc, uint32_t elen){	struct extent_position oepos;	int adsize;	int8_t etype;	struct allocExtDesc *aed;	if (epos.bh) {		get_bh(epos.bh);		get_bh(epos.bh);	}	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;	oepos = epos;	if (udf_next_aext(inode, &epos, &eloc, &elen, 1) == -1)		return -1;	while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) {		udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1);		if (oepos.bh != epos.bh) {			oepos.block = epos.block;			brelse(oepos.bh);			get_bh(epos.bh);			oepos.bh = epos.bh;			oepos.offset = epos.offset - adsize;		}	}	memset(&eloc, 0x00, sizeof(kernel_lb_addr));	elen = 0;	if (epos.bh != oepos.bh) {		udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1);		udf_write_aext(inode, &oepos, eloc, elen, 1);		udf_write_aext(inode, &oepos, eloc, elen, 1);		if (!oepos.bh) {			UDF_I_LENALLOC(inode) -= (adsize * 2);			mark_inode_dirty(inode);		} else {			aed = (struct allocExtDesc *)oepos.bh->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(oepos.bh->b_data, oepos.offset - (2 * adsize));			else				udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));			mark_buffer_dirty_inode(oepos.bh, inode);		}	} else {		udf_write_aext(inode, &oepos, eloc, elen, 1);		if (!oepos.bh) {			UDF_I_LENALLOC(inode) -= adsize;			mark_inode_dirty(inode);		} else {			aed = (struct allocExtDesc *)oepos.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(oepos.bh->b_data, epos.offset - adsize);			else				udf_update_tag(oepos.bh->b_data, sizeof(struct allocExtDesc));			mark_buffer_dirty_inode(oepos.bh, inode);		}	}	brelse(epos.bh);	brelse(oepos.bh);	return (elen >> 30);}int8_t inode_bmap(struct inode * inode, sector_t block,		  struct extent_position * pos, kernel_lb_addr * eloc,		  uint32_t * elen, sector_t * offset){	loff_t lbcount = 0, bcount =	    (loff_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;	}	pos->offset = 0;	pos->block = UDF_I_LOCATION(inode);	pos->bh = NULL;	*elen = 0;	do {		if ((etype = udf_next_aext(inode, pos, eloc, elen, 1)) == -1) {			*offset = (bcount - lbcount) >> inode->i_sb->s_blocksize_bits;			UDF_I_LENEXTENTS(inode) = lbcount;			return -1;		}		lbcount += *elen;	} while (lbcount <= bcount);	*offset = (bcount + *elen - lbcount) >> inode->i_sb->s_blocksize_bits;	return etype;}long udf_block_map(struct inode *inode, sector_t block){	kernel_lb_addr eloc;	uint32_t elen;	sector_t offset;	struct extent_position epos = {};	int ret;	lock_kernel();	if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30))		ret = udf_get_lb_pblock(inode->i_sb, eloc, offset);	else		ret = 0;	unlock_kernel();	brelse(epos.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 + -