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

📄 jfs_txnmgr.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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);		if (test_and_clear_cflag(COMMIT_Syncdata, ip) &&		    ((tblk->flag && COMMIT_DELETE) == 0))			fsync_inode_data_buffers(ip);		/*		 * 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_CREATE | COMMIT_DELETE)) {		atomic_inc(&tblk->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)		 */		if (tblk->ip->i_state & I_LOCK)			tblk->xflag &= ~COMMIT_LAZY;	}	ASSERT((!(tblk->xflag & COMMIT_DELETE)) ||	       ((tblk->ip->i_nlink == 0) &&		!test_cflag(COMMIT_Nolink, tblk->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(kdev_t_to_nr(ip->i_dev));		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);//              *pxd = mp->cm_pxd;		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);	pxd = &lrd->log.redopage.pxd;	/* log after-image for logredo(): */	lrd->type = cpu_to_le16(LOG_REDOPAGE);	if (JFS_IP(tlck->ip)->next_index < MAX_INLINE_DIRTABLE_ENTRY) {		/*		 * The table has been truncated, we've must have deleted		 * the last entry, so don't bother logging this		 */		mp->lid = 0;		hold_metapage(mp, 0);		atomic_dec(&mp->nohomeok);		discard_metapage(mp);		tlck->mp = 0;		return 0;	}	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;	return 0;}/* *      dtLog() * * function:    log dtree tlock and format maplock to update bmap; */static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,	   struct tlock * tlck){	struct metapage *mp;	struct pxd_lock *pxdlock;	pxd_t *pxd;	mp = tlck->mp;	/* initialize as REDOPAGE/NOREDOPAGE record format */	lrd->log.redopage.type = cpu_to_le16(LOG_DTREE);	lrd->log.redopage.l2linesize = cpu_to_le16(L2DTSLOTSIZE);	pxd = &lrd->log.redopage.pxd;	if (tlck->type & tlckBTROOT)		lrd->log.redopage.type |= cpu_to_le16(LOG_BTROOT);	/*	 *      page extension via relocation: entry insertion;	 *      page extension in-place: entry insertion;	 *      new right page from page split, reinitialized in-line	 *      root from root page split: entry insertion;	 */	if (tlck->type & (tlckNEW | tlckEXTEND)) {		/* log after-image of the new page for logredo():		 * mark log (LOG_NEW) for logredo() to initialize		 * freelist and update bmap for alloc of the new page;		 */		lrd->type = cpu_to_le16(LOG_REDOPAGE);		if (tlck->type & tlckEXTEND)			lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND);		else			lrd->log.redopage.type |= cpu_to_le16(LOG_NEW);//              *pxd = mp->cm_pxd;		PXDaddress(pxd, mp->index);		PXDlength(pxd,			  mp->logical_size >> tblk->sb->s_blocksize_bits);		lrd->backchain = cpu_to_le32(lmLog(log, tblk, lrd, tlck));

⌨️ 快捷键说明

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