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

📄 jfs_txnmgr.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		jfs_ip->atlhead = lid;		if (tlck->next == 0) {			/* This inode's first anonymous transaction */			jfs_ip->atltail = lid;			list_add_tail(&jfs_ip->anon_inode_list,				      &TxAnchor.anon_list);		}	}	TXN_UNLOCK();	/* initialize type dependent area for maplock */	maplock = (struct maplock *) & tlck->lock;	maplock->next = 0;	maplock->maxcnt = 0;	maplock->index = 0;	return tlck;}/* *	txLinelock() * * function: allocate a transaction lock for log vector list */struct linelock *txLinelock(struct linelock * tlock){	lid_t lid;	struct tlock *tlck;	struct linelock *linelock;	TXN_LOCK();	/* allocate a TxLock structure */	lid = txLockAlloc();	tlck = lid_to_tlock(lid);	TXN_UNLOCK();	/* initialize linelock */	linelock = (struct linelock *) tlck;	linelock->next = 0;	linelock->flag = tlckLINELOCK;	linelock->maxcnt = TLOCKLONG;	linelock->index = 0;	if (tlck->flag & tlckDIRECTORY)		linelock->flag |= tlckDIRECTORY;	/* append linelock after tlock */	linelock->next = tlock->next;	tlock->next = lid;	return linelock;}/* *		transaction commit management *		----------------------------- *//* * NAME:	txCommit() * * FUNCTION:	commit the changes to the objects specified in *		clist.  For journalled segments only the *		changes of the caller are committed, ie by tid. *		for non-journalled segments the data are flushed to *		disk and then the change to the disk inode and indirect *		blocks committed (so blocks newly allocated to the *		segment will be made a part of the segment atomically). * *		all of the segments specified in clist must be in *		one file system. no more than 6 segments are needed *		to handle all unix svcs. * *		if the i_nlink field (i.e. disk inode link count) *		is zero, and the type of inode is a regular file or *		directory, or symbolic link , the inode is truncated *		to zero length. the truncation is committed but the *		VM resources are unaffected until it is closed (see *		iput and iclose). * * PARAMETER: * * RETURN: * * serialization: *		on entry the inode lock on each segment is assumed *		to be held. * * i/o error: */int txCommit(tid_t tid,		/* transaction identifier */	     int nip,		/* number of inodes to commit */	     struct inode **iplist,	/* list of inode to commit */	     int flag){	int rc = 0;	struct commit cd;	struct jfs_log *log;	struct tblock *tblk;	struct lrd *lrd;	int lsn;	struct inode *ip;	struct jfs_inode_info *jfs_ip;	int k, n;	ino_t top;	struct super_block *sb;	jfs_info("txCommit, tid = %d, flag = %d", tid, flag);	/* is read-only file system ? */	if (isReadOnly(iplist[0])) {		rc = -EROFS;		goto TheEnd;	}	sb = cd.sb = iplist[0]->i_sb;	cd.tid = tid;	if (tid == 0)		tid = txBegin(sb, 0);	tblk = tid_to_tblock(tid);	/*	 * initialize commit structure	 */	log = JFS_SBI(sb)->log;	cd.log = log;	/* initialize log record descriptor in commit */	lrd = &cd.lrd;	lrd->logtid = cpu_to_le32(tblk->logtid);	lrd->backchain = 0;	tblk->xflag |= flag;	if ((flag & (COMMIT_FORCE | COMMIT_SYNC)) == 0)		tblk->xflag |= COMMIT_LAZY;	/*	 *	prepare non-journaled objects for commit	 *	 * flush data pages of non-journaled file	 * to prevent the file getting non-initialized disk blocks	 * in case of crash.	 * (new blocks - )	 */	cd.iplist = iplist;	cd.nip = nip;	/*	 *	acquire transaction lock on (on-disk) inodes	 *	 * update on-disk inode from in-memory inode	 * acquiring transaction locks for AFTER records	 * on the on-disk inode of file object	 *	 * sort the inodes array by inode number in descending order	 * to prevent deadlock when acquiring transaction lock	 * of on-disk inodes on multiple on-disk inode pages by	 * multiple concurrent transactions	 */	for (k = 0; k < cd.nip; k++) {		top = (cd.iplist[k])->i_ino;		for (n = k + 1; n < cd.nip; n++) {			ip = cd.iplist[n];			if (ip->i_ino > top) {				top = ip->i_ino;				cd.iplist[n] = cd.iplist[k];				cd.iplist[k] = ip;			}		}		ip = cd.iplist[k];		jfs_ip = JFS_IP(ip);		/*		 * BUGBUG - This code has temporarily been removed.  The		 * intent is to ensure that any file data is written before		 * the metadata is committed to the journal.  This prevents		 * uninitialized data from appearing in a file after the		 * journal has been replayed.  (The uninitialized data		 * could be sensitive data removed by another user.)		 *		 * The problem now is that we are holding the IWRITELOCK		 * on the inode, and calling filemap_fdatawrite on an		 * unmapped page will cause a deadlock in jfs_get_block.		 *		 * The long term solution is to pare down the use of		 * IWRITELOCK.  We are currently holding it too long.		 * We could also be smarter about which data pages need		 * to be written before the transaction is committed and		 * when we don't need to worry about it at all.		 *		 * if ((!S_ISDIR(ip->i_mode))		 *    && (tblk->flag & COMMIT_DELETE) == 0)		 *	filemap_write_and_wait(ip->i_mapping);		 */		/*		 * Mark inode as not dirty.  It will still be on the dirty		 * inode list, but we'll know not to commit it again unless		 * it gets marked dirty again		 */		clear_cflag(COMMIT_Dirty, ip);		/* inherit anonymous tlock(s) of inode */		if (jfs_ip->atlhead) {			lid_to_tlock(jfs_ip->atltail)->next = tblk->next;			tblk->next = jfs_ip->atlhead;			if (!tblk->last)				tblk->last = jfs_ip->atltail;			jfs_ip->atlhead = jfs_ip->atltail = 0;			TXN_LOCK();			list_del_init(&jfs_ip->anon_inode_list);			TXN_UNLOCK();		}		/*		 * acquire transaction lock on on-disk inode page		 * (become first tlock of the tblk's tlock list)		 */		if (((rc = diWrite(tid, ip))))			goto out;	}	/*	 *	write log records from transaction locks	 *	 * txUpdateMap() resets XAD_NEW in XAD.	 */	if ((rc = txLog(log, tblk, &cd)))		goto TheEnd;	/*	 * Ensure that inode isn't reused before	 * lazy commit thread finishes processing	 */	if (tblk->xflag & COMMIT_DELETE) {		atomic_inc(&tblk->u.ip->i_count);		/*		 * Avoid a rare deadlock		 *		 * If the inode is locked, we may be blocked in		 * jfs_commit_inode.  If so, we don't want the		 * lazy_commit thread doing the last iput() on the inode		 * since that may block on the locked inode.  Instead,		 * commit the transaction synchronously, so the last iput		 * will be done by the calling thread (or later)		 */		/*		 * I believe this code is no longer needed.  Splitting I_LOCK		 * into two bits, I_LOCK and I_SYNC should prevent this		 * deadlock as well.  But since I don't have a JFS testload		 * to verify this, only a trivial s/I_LOCK/I_SYNC/ was done.		 * Joern		 */		if (tblk->u.ip->i_state & I_SYNC)			tblk->xflag &= ~COMMIT_LAZY;	}	ASSERT((!(tblk->xflag & COMMIT_DELETE)) ||	       ((tblk->u.ip->i_nlink == 0) &&		!test_cflag(COMMIT_Nolink, tblk->u.ip)));	/*	 *	write COMMIT log record	 */	lrd->type = cpu_to_le16(LOG_COMMIT);	lrd->length = 0;	lsn = lmLog(log, tblk, lrd, NULL);	lmGroupCommit(log, tblk);	/*	 *	- transaction is now committed -	 */	/*	 * force pages in careful update	 * (imap addressing structure update)	 */	if (flag & COMMIT_FORCE)		txForce(tblk);	/*	 *	update allocation map.	 *	 * update inode allocation map and inode:	 * free pager lock on memory object of inode if any.	 * update block allocation map.	 *	 * txUpdateMap() resets XAD_NEW in XAD.	 */	if (tblk->xflag & COMMIT_FORCE)		txUpdateMap(tblk);	/*	 *	free transaction locks and pageout/free pages	 */	txRelease(tblk);	if ((tblk->flag & tblkGC_LAZY) == 0)		txUnlock(tblk);	/*	 *	reset in-memory object state	 */	for (k = 0; k < cd.nip; k++) {		ip = cd.iplist[k];		jfs_ip = JFS_IP(ip);		/*		 * reset in-memory inode state		 */		jfs_ip->bxflag = 0;		jfs_ip->blid = 0;	}      out:	if (rc != 0)		txAbort(tid, 1);      TheEnd:	jfs_info("txCommit: tid = %d, returning %d", tid, rc);	return rc;}/* * NAME:	txLog() * * FUNCTION:	Writes AFTER log records for all lines modified *		by tid for segments specified by inodes in comdata. *		Code assumes only WRITELOCKS are recorded in lockwords. * * PARAMETERS: * * RETURN : */static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd){	int rc = 0;	struct inode *ip;	lid_t lid;	struct tlock *tlck;	struct lrd *lrd = &cd->lrd;	/*	 * write log record(s) for each tlock of transaction,	 */	for (lid = tblk->next; lid; lid = tlck->next) {		tlck = lid_to_tlock(lid);		tlck->flag |= tlckLOG;		/* initialize lrd common */		ip = tlck->ip;		lrd->aggregate = cpu_to_le32(JFS_SBI(ip->i_sb)->aggregate);		lrd->log.redopage.fileset = cpu_to_le32(JFS_IP(ip)->fileset);		lrd->log.redopage.inode = cpu_to_le32(ip->i_ino);		/* write log record of page from the tlock */		switch (tlck->type & tlckTYPE) {		case tlckXTREE:			xtLog(log, tblk, lrd, tlck);			break;		case tlckDTREE:			dtLog(log, tblk, lrd, tlck);			break;		case tlckINODE:			diLog(log, tblk, lrd, tlck, cd);			break;		case tlckMAP:			mapLog(log, tblk, lrd, tlck);			break;		case tlckDATA:			dataLog(log, tblk, lrd, tlck);			break;		default:			jfs_err("UFO tlock:0x%p", tlck);		}	}	return rc;}/* *	diLog() * * function:	log inode tlock and format maplock to update bmap; */static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,		 struct tlock * tlck, struct commit * cd){	int rc = 0;	struct metapage *mp;	pxd_t *pxd;	struct pxd_lock *pxdlock;	mp = tlck->mp;	/* initialize as REDOPAGE record format */	lrd->log.redopage.type = cpu_to_le16(LOG_INODE);	lrd->log.redopage.l2linesize = cpu_to_le16(L2INODESLOTSIZE);	pxd = &lrd->log.redopage.pxd;	/*	 *	inode after image	 */	if (tlck->type & tlckENTRY) {		/* log after-image for logredo(): */		lrd->type = cpu_to_le16(LOG_REDOPAGE);		PXDaddress(pxd, mp->index);		PXDlength(pxd,			  mp->logical_size >> tblk->sb->s_blocksize_bits);		lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));		/* mark page as homeward bound */		tlck->flag |= tlckWRITEPAGE;	} else if (tlck->type & tlckFREE) {		/*		 *	free inode extent		 *		 * (pages of the freed inode extent have been invalidated and		 * a maplock for free of the extent has been formatted at		 * txLock() time);		 *		 * the tlock had been acquired on the inode allocation map page		 * (iag) that specifies the freed extent, even though the map		 * page is not itself logged, to prevent pageout of the map		 * page before the log;		 */		/* log LOG_NOREDOINOEXT of the freed inode extent for		 * logredo() to start NoRedoPage filters, and to update		 * imap and bmap for free of the extent;		 */		lrd->type = cpu_to_le16(LOG_NOREDOINOEXT);		/*		 * For the LOG_NOREDOINOEXT record, we need		 * to pass the IAG number and inode extent		 * index (within that IAG) from which the		 * the extent being released.  These have been		 * passed to us in the iplist[1] and iplist[2].		 */		lrd->log.noredoinoext.iagnum =		    cpu_to_le32((u32) (size_t) cd->iplist[1]);		lrd->log.noredoinoext.inoext_idx =		    cpu_to_le32((u32) (size_t) cd->iplist[2]);		pxdlock = (struct pxd_lock *) & tlck->lock;		*pxd = pxdlock->pxd;		lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, NULL));		/* update bmap */		tlck->flag |= tlckUPDATEMAP;		/* mark page as homeward bound */		tlck->flag |= tlckWRITEPAGE;	} else		jfs_err("diLog: UFO type tlck:0x%p", tlck);#ifdef  _JFS_WIP	/*	 *	alloc/free external EA extent	 *	 * a maplock for txUpdateMap() to update bPWMAP for alloc/free	 * of the extent has been formatted at txLock() time;	 */	else {		assert(tlck->type & tlckEA);		/* log LOG_UPDATEMAP for logredo() to update bmap for		 * alloc of new (and free of old) external EA extent;		 */		lrd->type = cpu_to_le16(LOG_UPDATEMAP);		pxdlock = (struct pxd_lock *) & tlck->lock;		nlock = pxdlock->index;		for (i = 0; i < nlock; i++, pxdlock++) {			if (pxdlock->flag & mlckALLOCPXD)				lrd->log.updatemap.type =				    cpu_to_le16(LOG_ALLOCPXD);			else				lrd->log.updatemap.type =				    cpu_to_le16(LOG_FREEPXD);			lrd->log.updatemap.nxd = cpu_to_le16(1);			lrd->log.updatemap.pxd = pxdlock->pxd;			lrd->backchain =			    cpu_to_le32(lmLog(log, tblk, lrd, NULL));		}		/* update bmap */		tlck->flag |= tlckUPDATEMAP;	}#endif				/* _JFS_WIP */	return rc;}/* *	dataLog() * * function:	log data tlock */static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,	    struct tlock * tlck){	struct metapage *mp;	pxd_t *pxd;	mp = tlck->mp;	/* initialize as REDOPAGE record format */	lrd->log.redopage.type = cpu_to_le16(LOG_DATA);	lrd->log.redopage.l2linesize = cpu_to_le16(L2DATASLOTSIZE);

⌨️ 快捷键说明

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