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

📄 jfs_txnmgr.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
			jfs_info("log barrier off: 0x%x", log->lsn);			/* enable new transactions start */			clear_bit(log_SYNCBARRIER, &log->flag);			/* wakeup all waitors for logsync barrier */			TXN_WAKEUP(&log->syncwait);		}	}	/*	 * wakeup all waitors for a free tblock	 */	TXN_WAKEUP(&TxAnchor.freewait);	TXN_UNLOCK();}/* *      txLock() * * function: acquire a transaction lock on the specified <mp> * * parameter: * * return:      transaction lock id * * serialization: */struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,		     int type){	struct jfs_inode_info *jfs_ip = JFS_IP(ip);	int dir_xtree = 0;	lid_t lid;	tid_t xtid;	struct tlock *tlck;	struct xtlock *xtlck;	struct linelock *linelock;	xtpage_t *p;	struct tblock *tblk;	assert(!test_cflag(COMMIT_Nolink, ip));	TXN_LOCK();	if (S_ISDIR(ip->i_mode) && (type & tlckXTREE) &&	    !(mp->xflag & COMMIT_PAGE)) {		/*		 * Directory inode is special.  It can have both an xtree tlock		 * and a dtree tlock associated with it.		 */		dir_xtree = 1;		lid = jfs_ip->xtlid;	} else		lid = mp->lid;	/* is page not locked by a transaction ? */	if (lid == 0)		goto allocateLock;	jfs_info("txLock: tid:%d ip:0x%p mp:0x%p lid:%d", tid, ip, mp, lid);	/* is page locked by the requester transaction ? */	tlck = lid_to_tlock(lid);	if ((xtid = tlck->tid) == tid)		goto grantLock;	/*	 * is page locked by anonymous transaction/lock ?	 *	 * (page update without transaction (i.e., file write) is	 * locked under anonymous transaction tid = 0:	 * anonymous tlocks maintained on anonymous tlock list of	 * the inode of the page and available to all anonymous	 * transactions until txCommit() time at which point	 * they are transferred to the transaction tlock list of	 * the commiting transaction of the inode)	 */	if (xtid == 0) {		tlck->tid = tid;		tblk = tid_to_tblock(tid);		/*		 * The order of the tlocks in the transaction is important		 * (during truncate, child xtree pages must be freed before		 * parent's tlocks change the working map).		 * Take tlock off anonymous list and add to tail of		 * transaction list		 *		 * Note:  We really need to get rid of the tid & lid and		 * use list_head's.  This code is getting UGLY!		 */		if (jfs_ip->atlhead == lid) {			if (jfs_ip->atltail == lid) {				/* only anonymous txn.				 * Remove from anon_list				 */				list_del_init(&jfs_ip->anon_inode_list);			}			jfs_ip->atlhead = tlck->next;		} else {			lid_t last;			for (last = jfs_ip->atlhead;			     lid_to_tlock(last)->next != lid;			     last = lid_to_tlock(last)->next) {				assert(last);			}			lid_to_tlock(last)->next = tlck->next;			if (jfs_ip->atltail == lid)				jfs_ip->atltail = last;		}		/* insert the tlock at tail of transaction tlock list */		if (tblk->next)			lid_to_tlock(tblk->last)->next = lid;		else			tblk->next = lid;		tlck->next = 0;		tblk->last = lid;		goto grantLock;	}	goto waitLock;	/*	 * allocate a tlock	 */      allocateLock:	lid = txLockAlloc();	tlck = lid_to_tlock(lid);	/*	 * initialize tlock	 */	tlck->tid = tid;	/* mark tlock for meta-data page */	if (mp->xflag & COMMIT_PAGE) {		tlck->flag = tlckPAGELOCK;		/* mark the page dirty and nohomeok */		mark_metapage_dirty(mp);		atomic_inc(&mp->nohomeok);		jfs_info("locking mp = 0x%p, nohomeok = %d tid = %d tlck = 0x%p",			 mp, atomic_read(&mp->nohomeok), tid, tlck);		/* if anonymous transaction, and buffer is on the group		 * commit synclist, mark inode to show this.  This will		 * prevent the buffer from being marked nohomeok for too		 * long a time.		 */		if ((tid == 0) && mp->lsn)			set_cflag(COMMIT_Synclist, ip);	}	/* mark tlock for in-memory inode */	else		tlck->flag = tlckINODELOCK;	tlck->type = 0;	/* bind the tlock and the page */	tlck->ip = ip;	tlck->mp = mp;	if (dir_xtree)		jfs_ip->xtlid = lid;	else		mp->lid = lid;	/*	 * enqueue transaction lock to transaction/inode	 */	/* insert the tlock at tail of transaction tlock list */	if (tid) {		tblk = tid_to_tblock(tid);		if (tblk->next)			lid_to_tlock(tblk->last)->next = lid;		else			tblk->next = lid;		tlck->next = 0;		tblk->last = lid;	}	/* anonymous transaction:	 * insert the tlock at head of inode anonymous tlock list	 */	else {		tlck->next = jfs_ip->atlhead;		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);		}	}	/* initialize type dependent area for linelock */	linelock = (struct linelock *) & tlck->lock;	linelock->next = 0;	linelock->flag = tlckLINELOCK;	linelock->maxcnt = TLOCKSHORT;	linelock->index = 0;	switch (type & tlckTYPE) {	case tlckDTREE:		linelock->l2linesize = L2DTSLOTSIZE;		break;	case tlckXTREE:		linelock->l2linesize = L2XTSLOTSIZE;		xtlck = (struct xtlock *) linelock;		xtlck->header.offset = 0;		xtlck->header.length = 2;		if (type & tlckNEW) {			xtlck->lwm.offset = XTENTRYSTART;		} else {			if (mp->xflag & COMMIT_PAGE)				p = (xtpage_t *) mp->data;			else				p = &jfs_ip->i_xtroot;			xtlck->lwm.offset =			    le16_to_cpu(p->header.nextindex);		}		xtlck->lwm.length = 0;	/* ! */		xtlck->twm.offset = 0;		xtlck->hwm.offset = 0;		xtlck->index = 2;		break;	case tlckINODE:		linelock->l2linesize = L2INODESLOTSIZE;		break;	case tlckDATA:		linelock->l2linesize = L2DATASLOTSIZE;		break;	default:		jfs_err("UFO tlock:0x%p", tlck);	}	/*	 * update tlock vector	 */      grantLock:	tlck->type |= type;	TXN_UNLOCK();	return tlck;	/*	 * page is being locked by another transaction:	 */      waitLock:	/* Only locks on ipimap or ipaimap should reach here */	/* assert(jfs_ip->fileset == AGGREGATE_I); */	if (jfs_ip->fileset != AGGREGATE_I) {		jfs_err("txLock: trying to lock locked page!");		dump_mem("ip", ip, sizeof(struct inode));		dump_mem("mp", mp, sizeof(struct metapage));		dump_mem("Locker's tblk", tid_to_tblock(tid),			 sizeof(struct tblock));		dump_mem("Tlock", tlck, sizeof(struct tlock));		BUG();	}	INCREMENT(stattx.waitlock);	/* statistics */	release_metapage(mp);	jfs_info("txLock: in waitLock, tid = %d, xtid = %d, lid = %d",		 tid, xtid, lid);	TXN_SLEEP_DROP_LOCK(&tid_to_tblock(xtid)->waitor);	jfs_info("txLock: awakened     tid = %d, lid = %d", tid, lid);	return NULL;}/* * NAME:        txRelease() * * FUNCTION:    Release buffers associated with transaction locks, but don't *		mark homeok yet.  The allows other transactions to modify *		buffers, but won't let them go to disk until commit record *		actually gets written. * * PARAMETER: *              tblk    - * * RETURN:      Errors from subroutines. */static void txRelease(struct tblock * tblk){	struct metapage *mp;	lid_t lid;	struct tlock *tlck;	TXN_LOCK();	for (lid = tblk->next; lid; lid = tlck->next) {		tlck = lid_to_tlock(lid);		if ((mp = tlck->mp) != NULL &&		    (tlck->type & tlckBTROOT) == 0) {			assert(mp->xflag & COMMIT_PAGE);			mp->lid = 0;		}	}	/*	 * wakeup transactions waiting on a page locked	 * by the current transaction	 */	TXN_WAKEUP(&tblk->waitor);	TXN_UNLOCK();}/* * NAME:        txUnlock() * * FUNCTION:    Initiates pageout of pages modified by tid in journalled *              objects and frees their lockwords. */static void txUnlock(struct tblock * tblk){	struct tlock *tlck;	struct linelock *linelock;	lid_t lid, next, llid, k;	struct metapage *mp;	struct jfs_log *log;	int difft, diffp;	jfs_info("txUnlock: tblk = 0x%p", tblk);	log = JFS_SBI(tblk->sb)->log;	/*	 * mark page under tlock homeok (its log has been written):	 */	for (lid = tblk->next; lid; lid = next) {		tlck = lid_to_tlock(lid);		next = tlck->next;		jfs_info("unlocking lid = %d, tlck = 0x%p", lid, tlck);		/* unbind page from tlock */		if ((mp = tlck->mp) != NULL &&		    (tlck->type & tlckBTROOT) == 0) {			assert(mp->xflag & COMMIT_PAGE);			/* hold buffer			 *			 * It's possible that someone else has the metapage.			 * The only things were changing are nohomeok, which			 * is handled atomically, and clsn which is protected			 * by the LOGSYNC_LOCK.			 */			hold_metapage(mp, 1);			assert(atomic_read(&mp->nohomeok) > 0);			atomic_dec(&mp->nohomeok);			/* inherit younger/larger clsn */			LOGSYNC_LOCK(log);			if (mp->clsn) {				logdiff(difft, tblk->clsn, log);				logdiff(diffp, mp->clsn, log);				if (difft > diffp)					mp->clsn = tblk->clsn;			} else				mp->clsn = tblk->clsn;			LOGSYNC_UNLOCK(log);			assert(!(tlck->flag & tlckFREEPAGE));			if (tlck->flag & tlckWRITEPAGE) {				write_metapage(mp);			} else {				/* release page which has been forced */				release_metapage(mp);			}		}		/* insert tlock, and linelock(s) of the tlock if any,		 * at head of freelist		 */		TXN_LOCK();		llid = ((struct linelock *) & tlck->lock)->next;		while (llid) {			linelock = (struct linelock *) lid_to_tlock(llid);			k = linelock->next;			txLockFree(llid);			llid = k;		}		txLockFree(lid);		TXN_UNLOCK();	}	tblk->next = tblk->last = 0;	/*	 * remove tblock from logsynclist	 * (allocation map pages inherited lsn of tblk and	 * has been inserted in logsync list at txUpdateMap())	 */	if (tblk->lsn) {		LOGSYNC_LOCK(log);		log->count--;		list_del(&tblk->synclist);		LOGSYNC_UNLOCK(log);	}}/* *      txMaplock() * * function: allocate a transaction lock for freed page/entry; *      for freed page, maplock is used as xtlock/dtlock type; */struct tlock *txMaplock(tid_t tid, struct inode *ip, int type){	struct jfs_inode_info *jfs_ip = JFS_IP(ip);	lid_t lid;	struct tblock *tblk;	struct tlock *tlck;	struct maplock *maplock;	TXN_LOCK();	/*	 * allocate a tlock	 */	lid = txLockAlloc();	tlck = lid_to_tlock(lid);	/*	 * initialize tlock	 */	tlck->tid = tid;	/* bind the tlock and the object */	tlck->flag = tlckINODELOCK;	tlck->ip = ip;	tlck->mp = NULL;	tlck->type = type;	/*	 * enqueue transaction lock to transaction/inode	 */	/* insert the tlock at tail of transaction tlock list */	if (tid) {		tblk = tid_to_tblock(tid);		if (tblk->next)			lid_to_tlock(tblk->last)->next = lid;		else			tblk->next = lid;		tlck->next = 0;		tblk->last = lid;	}	/* anonymous transaction:	 * insert the tlock at head of inode anonymous tlock list	 */	else {		tlck->next = jfs_ip->atlhead;		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;	/* append linelock after tlock */	linelock->next = tlock->next;	tlock->next = lid;

⌨️ 快捷键说明

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