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

📄 jfs_imap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	ip->i_mapping->a_ops = &jfs_metapage_aops;	mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS);	/* Allocations to metadata inodes should not affect quotas */	ip->i_flags |= S_NOQUOTA;	if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) {		sbi->gengen = le32_to_cpu(dp->di_gengen);		sbi->inostamp = le32_to_cpu(dp->di_inostamp);	}	/* release the page */	release_metapage(mp);	hlist_add_head(&ip->i_hash, &aggregate_hash);	return (ip);}/* * NAME:	diWriteSpecial() * * FUNCTION:	Write the special inode to disk * * PARAMETERS: *	ip - special inode *	secondary - 1 if secondary aggregate inode table * * RETURN VALUES: none */void diWriteSpecial(struct inode *ip, int secondary){	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);	uint address;	struct dinode *dp;	ino_t inum = ip->i_ino;	struct metapage *mp;	if (secondary)		address = addressPXD(&sbi->ait2) >> sbi->l2nbperpage;	else		address = AITBL_OFF >> L2PSIZE;	ASSERT(inum < INOSPEREXT);	address += inum >> 3;	/* 8 inodes per 4K page */	/* read the page of fixed disk inode (AIT) in raw mode */	mp = read_metapage(ip, address << sbi->l2nbperpage, PSIZE, 1);	if (mp == NULL) {		jfs_err("diWriteSpecial: failed to read aggregate inode "			"extent!");		return;	}	/* get the pointer to the disk inode of interest */	dp = (struct dinode *) (mp->data);	dp += inum % 8;		/* 8 inodes per 4K page */	/* copy on-disk inode to in-memory inode */	copy_to_dinode(dp, ip);	memcpy(&dp->di_xtroot, &JFS_IP(ip)->i_xtroot, 288);	if (inum == FILESYSTEM_I)		dp->di_gengen = cpu_to_le32(sbi->gengen);	/* write the page */	write_metapage(mp);}/* * NAME:	diFreeSpecial() * * FUNCTION:	Free allocated space for special inode */void diFreeSpecial(struct inode *ip){	if (ip == NULL) {		jfs_err("diFreeSpecial called with NULL ip!");		return;	}	filemap_write_and_wait(ip->i_mapping);	truncate_inode_pages(ip->i_mapping, 0);	iput(ip);}/* * NAME:	diWrite() * * FUNCTION:	write the on-disk inode portion of the in-memory inode *		to its corresponding on-disk inode. * *		on entry, the specifed incore inode should itself *		specify the disk inode number corresponding to the *		incore inode (i.e. i_number should be initialized). * *		the inode contains the inode extent address for the disk *		inode.  with the inode extent address in hand, the *		page of the extent that contains the disk inode is *		read and the disk inode portion of the incore inode *		is copied to the disk inode. * * PARAMETERS: *	tid -  transacation id *	ip  -  pointer to incore inode to be written to the inode extent. * * RETURN VALUES: *	0	- success *	-EIO	- i/o error. */int diWrite(tid_t tid, struct inode *ip){	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);	struct jfs_inode_info *jfs_ip = JFS_IP(ip);	int rc = 0;	s32 ino;	struct dinode *dp;	s64 blkno;	int block_offset;	int inodes_left;	struct metapage *mp;	unsigned long pageno;	int rel_inode;	int dioffset;	struct inode *ipimap;	uint type;	lid_t lid;	struct tlock *ditlck, *tlck;	struct linelock *dilinelock, *ilinelock;	struct lv *lv;	int n;	ipimap = jfs_ip->ipimap;	ino = ip->i_ino & (INOSPERIAG - 1);	if (!addressPXD(&(jfs_ip->ixpxd)) ||	    (lengthPXD(&(jfs_ip->ixpxd)) !=	     JFS_IP(ipimap)->i_imap->im_nbperiext)) {		jfs_error(ip->i_sb, "diWrite: ixpxd invalid");		return -EIO;	}	/*	 * read the page of disk inode containing the specified inode:	 */	/* compute the block address of the page */	blkno = INOPBLK(&(jfs_ip->ixpxd), ino, sbi->l2nbperpage);	rel_inode = (ino & (INOSPERPAGE - 1));	pageno = blkno >> sbi->l2nbperpage;	if ((block_offset = ((u32) blkno & (sbi->nbperpage - 1)))) {		/*		 * OS/2 didn't always align inode extents on page boundaries		 */		inodes_left =		    (sbi->nbperpage - block_offset) << sbi->l2niperblk;		if (rel_inode < inodes_left)			rel_inode += block_offset << sbi->l2niperblk;		else {			pageno += 1;			rel_inode -= inodes_left;		}	}	/* read the page of disk inode */      retry:	mp = read_metapage(ipimap, pageno << sbi->l2nbperpage, PSIZE, 1);	if (mp == 0)		return -EIO;	/* get the pointer to the disk inode */	dp = (struct dinode *) mp->data;	dp += rel_inode;	dioffset = (ino & (INOSPERPAGE - 1)) << L2DISIZE;	/*	 * acquire transaction lock on the on-disk inode;	 * N.B. tlock is acquired on ipimap not ip;	 */	if ((ditlck =	     txLock(tid, ipimap, mp, tlckINODE | tlckENTRY)) == NULL)		goto retry;	dilinelock = (struct linelock *) & ditlck->lock;	/*	 * copy btree root from in-memory inode to on-disk inode	 *	 * (tlock is taken from inline B+-tree root in in-memory	 * inode when the B+-tree root is updated, which is pointed	 * by jfs_ip->blid as well as being on tx tlock list)	 *	 * further processing of btree root is based on the copy	 * in in-memory inode, where txLog() will log from, and,	 * for xtree root, txUpdateMap() will update map and reset	 * XAD_NEW bit;	 */	if (S_ISDIR(ip->i_mode) && (lid = jfs_ip->xtlid)) {		/*		 * This is the special xtree inside the directory for storing		 * the directory table		 */		xtpage_t *p, *xp;		xad_t *xad;		jfs_ip->xtlid = 0;		tlck = lid_to_tlock(lid);		assert(tlck->type & tlckXTREE);		tlck->type |= tlckBTROOT;		tlck->mp = mp;		ilinelock = (struct linelock *) & tlck->lock;		/*		 * copy xtree root from inode to dinode:		 */		p = &jfs_ip->i_xtroot;		xp = (xtpage_t *) &dp->di_dirtable;		lv = ilinelock->lv;		for (n = 0; n < ilinelock->index; n++, lv++) {			memcpy(&xp->xad[lv->offset], &p->xad[lv->offset],			       lv->length << L2XTSLOTSIZE);		}		/* reset on-disk (metadata page) xtree XAD_NEW bit */		xad = &xp->xad[XTENTRYSTART];		for (n = XTENTRYSTART;		     n < le16_to_cpu(xp->header.nextindex); n++, xad++)			if (xad->flag & (XAD_NEW | XAD_EXTENDED))				xad->flag &= ~(XAD_NEW | XAD_EXTENDED);	}	if ((lid = jfs_ip->blid) == 0)		goto inlineData;	jfs_ip->blid = 0;	tlck = lid_to_tlock(lid);	type = tlck->type;	tlck->type |= tlckBTROOT;	tlck->mp = mp;	ilinelock = (struct linelock *) & tlck->lock;	/*	 *	regular file: 16 byte (XAD slot) granularity	 */	if (type & tlckXTREE) {		xtpage_t *p, *xp;		xad_t *xad;		/*		 * copy xtree root from inode to dinode:		 */		p = &jfs_ip->i_xtroot;		xp = &dp->di_xtroot;		lv = ilinelock->lv;		for (n = 0; n < ilinelock->index; n++, lv++) {			memcpy(&xp->xad[lv->offset], &p->xad[lv->offset],			       lv->length << L2XTSLOTSIZE);		}		/* reset on-disk (metadata page) xtree XAD_NEW bit */		xad = &xp->xad[XTENTRYSTART];		for (n = XTENTRYSTART;		     n < le16_to_cpu(xp->header.nextindex); n++, xad++)			if (xad->flag & (XAD_NEW | XAD_EXTENDED))				xad->flag &= ~(XAD_NEW | XAD_EXTENDED);	}	/*	 *	directory: 32 byte (directory entry slot) granularity	 */	else if (type & tlckDTREE) {		dtpage_t *p, *xp;		/*		 * copy dtree root from inode to dinode:		 */		p = (dtpage_t *) &jfs_ip->i_dtroot;		xp = (dtpage_t *) & dp->di_dtroot;		lv = ilinelock->lv;		for (n = 0; n < ilinelock->index; n++, lv++) {			memcpy(&xp->slot[lv->offset], &p->slot[lv->offset],			       lv->length << L2DTSLOTSIZE);		}	} else {		jfs_err("diWrite: UFO tlock");	}      inlineData:	/*	 * copy inline symlink from in-memory inode to on-disk inode	 */	if (S_ISLNK(ip->i_mode) && ip->i_size < IDATASIZE) {		lv = & dilinelock->lv[dilinelock->index];		lv->offset = (dioffset + 2 * 128) >> L2INODESLOTSIZE;		lv->length = 2;		memcpy(&dp->di_fastsymlink, jfs_ip->i_inline, IDATASIZE);		dilinelock->index++;	}	/*	 * copy inline data from in-memory inode to on-disk inode:	 * 128 byte slot granularity	 */	if (test_cflag(COMMIT_Inlineea, ip)) {		lv = & dilinelock->lv[dilinelock->index];		lv->offset = (dioffset + 3 * 128) >> L2INODESLOTSIZE;		lv->length = 1;		memcpy(&dp->di_inlineea, jfs_ip->i_inline_ea, INODESLOTSIZE);		dilinelock->index++;		clear_cflag(COMMIT_Inlineea, ip);	}	/*	 *	lock/copy inode base: 128 byte slot granularity	 */	lv = & dilinelock->lv[dilinelock->index];	lv->offset = dioffset >> L2INODESLOTSIZE;	copy_to_dinode(dp, ip);	if (test_and_clear_cflag(COMMIT_Dirtable, ip)) {		lv->length = 2;		memcpy(&dp->di_dirtable, &jfs_ip->i_dirtable, 96);	} else		lv->length = 1;	dilinelock->index++;	/* release the buffer holding the updated on-disk inode.	 * the buffer will be later written by commit processing.	 */	write_metapage(mp);	return (rc);}/* * NAME:	diFree(ip) * * FUNCTION:	free a specified inode from the inode working map *		for a fileset or aggregate. * *		if the inode to be freed represents the first (only) *		free inode within the iag, the iag will be placed on *		the ag free inode list. * *		freeing the inode will cause the inode extent to be *		freed if the inode is the only allocated inode within *		the extent.  in this case all the disk resource backing *		up the inode extent will be freed. in addition, the iag *		will be placed on the ag extent free list if the extent *		is the first free extent in the iag.  if freeing the *		extent also means that no free inodes will exist for *		the iag, the iag will also be removed from the ag free *		inode list. * *		the iag describing the inode will be freed if the extent *		is to be freed and it is the only backed extent within *		the iag.  in this case, the iag will be removed from the *		ag free extent list and ag free inode list and placed on *		the inode map's free iag list. * *		a careful update approach is used to provide consistency *		in the face of updates to multiple buffers.  under this *		approach, all required buffers are obtained before making *		any updates and are held until all updates are complete. * * PARAMETERS: *	ip	- inode to be freed. * * RETURN VALUES: *	0	- success *	-EIO	- i/o error. */int diFree(struct inode *ip){	int rc;	ino_t inum = ip->i_ino;	struct iag *iagp, *aiagp, *biagp, *ciagp, *diagp;	struct metapage *mp, *amp, *bmp, *cmp, *dmp;	int iagno, ino, extno, bitno, sword, agno;	int back, fwd;	u32 bitmap, mask;	struct inode *ipimap = JFS_SBI(ip->i_sb)->ipimap;	struct inomap *imap = JFS_IP(ipimap)->i_imap;	pxd_t freepxd;	tid_t tid;	struct inode *iplist[3];	struct tlock *tlck;	struct pxd_lock *pxdlock;	/*	 * This is just to suppress compiler warnings.  The same logic that	 * references these variables is used to initialize them.	 */	aiagp = biagp = ciagp = diagp = NULL;	/* get the iag number containing the inode.	 */	iagno = INOTOIAG(inum);	/* make sure that the iag is contained within	 * the map.	 */	if (iagno >= imap->im_nextiag) {		print_hex_dump(KERN_ERR, "imap: ", DUMP_PREFIX_ADDRESS, 16, 4,			       imap, 32, 0);		jfs_error(ip->i_sb,			  "diFree: inum = %d, iagno = %d, nextiag = %d",			  (uint) inum, iagno, imap->im_nextiag);		return -EIO;	}	/* get the allocation group for this ino.	 */	agno = JFS_IP(ip)->agno;	/* Lock the AG specific inode map information	 */	AG_LOCK(imap, agno);	/* Obtain read lock in imap inode.  Don't release it until we have	 * read all of the IAG's that we are going to.	 */	IREAD_LOCK(ipimap, RDWRLOCK_IMAP);	/* read the iag.	 */	if ((rc = diIAGRead(imap, iagno, &mp))) {		IREAD_UNLOCK(ipimap);		AG_UNLOCK(imap, agno);		return (rc);	}	iagp = (struct iag *) mp->data;	/* get the inode number and extent number of the inode within	 * the iag and the inode number within the extent.	 */	ino = inum & (INOSPERIAG - 1);	extno = ino >> L2INOSPEREXT;	bitno = ino & (INOSPEREXT - 1);	mask = HIGHORDER >> bitno;	if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {		jfs_error(ip->i_sb,			  "diFree: wmap shows inode already free");	}	if (!addressPXD(&iagp->inoext[extno])) {		release_metapage(mp);		IREAD_UNLOCK(ipimap);		AG_UNLOCK(imap, agno);		jfs_error(ip->i_sb, "diFree: invalid inoext");		return -EIO;	}	/* compute the bitmap for the extent reflecting the freed inode.	 */	bitmap = le32_to_cpu(iagp->wmap[extno]) & ~mask;	if (imap->im_agctl[agno].numfree > imap->im_agctl[agno].numinos) {		release_metapage(mp);		IREAD_UNLOCK(ipimap);		AG_UNLOCK(imap, agno);		jfs_error(ip->i_sb, "diFree: numfree > numinos");		return -EIO;	}	/*	 *	inode extent still has some inodes or below low water mark:	 *	keep the inode extent;	 */	if (bitmap ||	    imap->im_agctl[agno].numfree < 96 ||	    (imap->im_agctl[agno].numfree < 288 &&	     (((imap->im_agctl[agno].numfree * 100) /	       imap->im_agctl[agno].numinos) <= 25))) {		/* if the iag currently has no free inodes (i.e.,

⌨️ 快捷键说明

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