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

📄 jfs_logmgr.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	lbmfree(bp);	LCACHE_UNLOCK(flags);}static void lbmfree(struct lbuf * bp){	struct jfs_log *log = bp->l_log;	assert(bp->l_wqnext == NULL);	/*	 * return the buffer to head of freelist	 */	bp->l_freelist = log->lbuf_free;	log->lbuf_free = bp;	wake_up(&log->free_wait);	return;}/* * NAME:	lbmRedrive * * FUNCTION:	add a log buffer to the the log redrive list * * PARAMETER: *     bp	- log buffer * * NOTES: *	Takes log_redrive_lock. */static inline void lbmRedrive(struct lbuf *bp){	unsigned long flags;	spin_lock_irqsave(&log_redrive_lock, flags);	bp->l_redrive_next = log_redrive_list;	log_redrive_list = bp;	spin_unlock_irqrestore(&log_redrive_lock, flags);	wake_up(&jfs_IO_thread_wait);}/* *	lbmRead() */static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp){	struct lbuf *bp;	/*	 * allocate a log buffer	 */	*bpp = bp = lbmAllocate(log, pn);	jfs_info("lbmRead: bp:0x%p pn:0x%x", bp, pn);	bp->l_flag |= lbmREAD;	bp->l_bh.b_reqnext = NULL;	clear_bit(BH_Uptodate, &bp->l_bh.b_state);	lock_buffer(&bp->l_bh);	set_bit(BH_Mapped, &bp->l_bh.b_state);	set_bit(BH_Req, &bp->l_bh.b_state);	bp->l_bh.b_rdev = bp->l_bh.b_dev;	bp->l_bh.b_rsector = bp->l_blkno << (log->l2bsize - 9);	generic_make_request(READ, &bp->l_bh);	run_task_queue(&tq_disk);	wait_event(bp->l_ioevent, (bp->l_flag != lbmREAD));	return 0;}/* *	lbmWrite() * * buffer at head of pageout queue stays after completion of * partial-page pageout and redriven by explicit initiation of * pageout by caller until full-page pageout is completed and * released. * * device driver i/o done redrives pageout of new buffer at * head of pageout queue when current buffer at head of pageout * queue is released at the completion of its full-page pageout. * * LOGGC_LOCK() serializes lbmWrite() by lmNextPage() and lmGroupCommit(). * LCACHE_LOCK() serializes xflag between lbmWrite() and lbmIODone() */static void lbmWrite(struct jfs_log * log, struct lbuf * bp, int flag,		     int cant_block){	struct lbuf *tail;	unsigned long flags;	jfs_info("lbmWrite: bp:0x%p flag:0x%x pn:0x%x", bp, flag, bp->l_pn);	/* map the logical block address to physical block address */	bp->l_blkno =	    log->base + (bp->l_pn << (L2LOGPSIZE - log->l2bsize));	LCACHE_LOCK(flags);		/* disable+lock */	/*	 * initialize buffer for device driver	 */	bp->l_flag = flag;	/*	 *      insert bp at tail of write queue associated with log	 *	 * (request is either for bp already/currently at head of queue	 * or new bp to be inserted at tail)	 */	tail = log->wqueue;	/* is buffer not already on write queue ? */	if (bp->l_wqnext == NULL) {		/* insert at tail of wqueue */		if (tail == NULL) {			log->wqueue = bp;			bp->l_wqnext = bp;		} else {			log->wqueue = bp;			bp->l_wqnext = tail->l_wqnext;			tail->l_wqnext = bp;		}		tail = bp;	}	/* is buffer at head of wqueue and for write ? */	if ((bp != tail->l_wqnext) || !(flag & lbmWRITE)) {		LCACHE_UNLOCK(flags);	/* unlock+enable */		return;	}	LCACHE_UNLOCK(flags);	/* unlock+enable */	if (cant_block)		lbmRedrive(bp);	else if (flag & lbmSYNC)		lbmStartIO(bp);	else {		LOGGC_UNLOCK(log);		lbmStartIO(bp);		LOGGC_LOCK(log);	}}/* *	lbmDirectWrite() * * initiate pageout bypassing write queue for sidestream * (e.g., log superblock) write; */static void lbmDirectWrite(struct jfs_log * log, struct lbuf * bp, int flag){	jfs_info("lbmDirectWrite: bp:0x%p flag:0x%x pn:0x%x",		 bp, flag, bp->l_pn);	/*	 * initialize buffer for device driver	 */	bp->l_flag = flag | lbmDIRECT;	/* map the logical block address to physical block address */	bp->l_blkno =	    log->base + (bp->l_pn << (L2LOGPSIZE - log->l2bsize));	/*	 *      initiate pageout of the page	 */	lbmStartIO(bp);}/* * NAME:	lbmStartIO() * * FUNCTION:	Interface to DD strategy routine * * RETURN:      none * * serialization: LCACHE_LOCK() is NOT held during log i/o; */static void lbmStartIO(struct lbuf * bp){	jfs_info("lbmStartIO");//	lock_buffer(&bp->l_bh);	assert(!test_bit(BH_Lock, &bp->l_bh.b_state));	set_bit(BH_Lock, &bp->l_bh.b_state);	if (bp->l_log->no_integrity)		/* Don't really do I/O */		lbmIODone(&bp->l_bh, 1);	else {		bp->l_bh.b_reqnext = NULL;		set_bit(BH_Dirty, &bp->l_bh.b_state);		set_bit(BH_Mapped, &bp->l_bh.b_state);		set_bit(BH_Req, &bp->l_bh.b_state);		bp->l_bh.b_rdev = bp->l_bh.b_dev;		bp->l_bh.b_rsector = bp->l_blkno << (bp->l_log->l2bsize - 9);		generic_make_request(WRITE, &bp->l_bh);		INCREMENT(lmStat.submitted);		run_task_queue(&tq_disk);	}}/* *	lbmIOWait() */static int lbmIOWait(struct lbuf * bp, int flag){	unsigned long flags;	int rc = 0;	jfs_info("lbmIOWait1: bp:0x%p flag:0x%x:0x%x", bp, bp->l_flag, flag);	LCACHE_LOCK(flags);		/* disable+lock */	LCACHE_SLEEP_COND(bp->l_ioevent, (bp->l_flag & lbmDONE), flags);	rc = (bp->l_flag & lbmERROR) ? -EIO : 0;	if (flag & lbmFREE)		lbmfree(bp);	LCACHE_UNLOCK(flags);	/* unlock+enable */	jfs_info("lbmIOWait2: bp:0x%p flag:0x%x:0x%x", bp, bp->l_flag, flag);	return rc;}/* *	lbmIODone() * * executed at INTIODONE level */static void lbmIODone(struct buffer_head *bh, int uptodate){	struct lbuf *bp = bh->b_private;	struct lbuf *nextbp, *tail;	struct jfs_log *log;	unsigned long flags;	/*	 * get back jfs buffer bound to the i/o buffer	 */	jfs_info("lbmIODone: bp:0x%p flag:0x%x", bp, bp->l_flag);	LCACHE_LOCK(flags);		/* disable+lock */	unlock_buffer(&bp->l_bh);	bp->l_flag |= lbmDONE;	if (!uptodate) {		bp->l_flag |= lbmERROR;		jfs_err("lbmIODone: I/O error in JFS log");	}	/*	 *      pagein completion	 */	if (bp->l_flag & lbmREAD) {		bp->l_flag &= ~lbmREAD;		LCACHE_UNLOCK(flags);	/* unlock+enable */		/* wakeup I/O initiator */		LCACHE_WAKEUP(&bp->l_ioevent);		return;	}	/*	 *      pageout completion	 *	 * the bp at the head of write queue has completed pageout.	 *	 * if single-commit/full-page pageout, remove the current buffer	 * from head of pageout queue, and redrive pageout with	 * the new buffer at head of pageout queue;	 * otherwise, the partial-page pageout buffer stays at	 * the head of pageout queue to be redriven for pageout	 * by lmGroupCommit() until full-page pageout is completed.	 */	bp->l_flag &= ~lbmWRITE;	INCREMENT(lmStat.pagedone);	/* update committed lsn */	log = bp->l_log;	log->clsn = (bp->l_pn << L2LOGPSIZE) + bp->l_ceor;	if (bp->l_flag & lbmDIRECT) {		LCACHE_WAKEUP(&bp->l_ioevent);		LCACHE_UNLOCK(flags);		return;	}	tail = log->wqueue;	/* single element queue */	if (bp == tail) {		/* remove head buffer of full-page pageout		 * from log device write queue		 */		if (bp->l_flag & lbmRELEASE) {			log->wqueue = NULL;			bp->l_wqnext = NULL;		}	}	/* multi element queue */	else {		/* remove head buffer of full-page pageout		 * from log device write queue		 */		if (bp->l_flag & lbmRELEASE) {			nextbp = tail->l_wqnext = bp->l_wqnext;			bp->l_wqnext = NULL;			/*			 * redrive pageout of next page at head of write queue:			 * redrive next page without any bound tblk			 * (i.e., page w/o any COMMIT records), or			 * first page of new group commit which has been			 * queued after current page (subsequent pageout			 * is performed synchronously, except page without			 * any COMMITs) by lmGroupCommit() as indicated			 * by lbmWRITE flag;			 */			if (nextbp->l_flag & lbmWRITE) {				/*				 * We can't do the I/O at interrupt time.				 * The jfsIO thread can do it				 */				lbmRedrive(nextbp);			}		}	}	/*	 *      synchronous pageout:	 *	 * buffer has not necessarily been removed from write queue	 * (e.g., synchronous write of partial-page with COMMIT):	 * leave buffer for i/o initiator to dispose	 */	if (bp->l_flag & lbmSYNC) {		LCACHE_UNLOCK(flags);	/* unlock+enable */		/* wakeup I/O initiator */		LCACHE_WAKEUP(&bp->l_ioevent);	}	/*	 *      Group Commit pageout:	 */	else if (bp->l_flag & lbmGC) {		LCACHE_UNLOCK(flags);		lmPostGC(bp);	}	/*	 *      asynchronous pageout:	 *	 * buffer must have been removed from write queue:	 * insert buffer at head of freelist where it can be recycled	 */	else {		assert(bp->l_flag & lbmRELEASE);		assert(bp->l_flag & lbmFREE);		lbmfree(bp);		LCACHE_UNLOCK(flags);	/* unlock+enable */	}}int jfsIOWait(void *arg){	struct lbuf *bp;	lock_kernel();	daemonize();	current->tty = NULL;	strcpy(current->comm, "jfsIO");	unlock_kernel();	spin_lock_irq(&current->Sigmask_lock);	sigfillset(&current->blocked);	Recalc_sigpending(current);	spin_unlock_irq(&current->Sigmask_lock);	complete(&jfsIOwait);	do {		DECLARE_WAITQUEUE(wq, current);		spin_lock_irq(&log_redrive_lock);		while ((bp = log_redrive_list)) {			log_redrive_list = bp->l_redrive_next;			bp->l_redrive_next = NULL;			spin_unlock_irq(&log_redrive_lock);			lbmStartIO(bp);			spin_lock_irq(&log_redrive_lock);		}		add_wait_queue(&jfs_IO_thread_wait, &wq);		set_current_state(TASK_INTERRUPTIBLE);		spin_unlock_irq(&log_redrive_lock);		schedule();		current->state = TASK_RUNNING;		remove_wait_queue(&jfs_IO_thread_wait, &wq);	} while (!jfs_stop_threads);	jfs_info("jfsIOWait being killed!");	complete(&jfsIOwait);	return 0;}/* * NAME:	lmLogFormat()/jfs_logform() * * FUNCTION:	format file system log * * PARAMETERS: *      log	- volume log *	logAddress - start address of log space in FS block *	logSize	- length of log space in FS block; * * RETURN:	0	- success *		-EIO	- i/o error * * XXX: We're synchronously writing one page at a time.  This needs to *	be improved by writing multiple pages at once. */int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize){	int rc = -EIO;	struct jfs_sb_info *sbi = JFS_SBI(log->sb);	struct logsuper *logsuper;	struct logpage *lp;	int lspn;		/* log sequence page number */	struct lrd *lrd_ptr;	int npages = 0;	struct lbuf *bp;	jfs_info("lmLogFormat: logAddress:%Ld logSize:%d",		 (long long)logAddress, logSize);	/* allocate a log buffer */	bp = lbmAllocate(log, 1);	npages = logSize >> sbi->l2nbperpage;	/*	 *      log space:	 *	 * page 0 - reserved;	 * page 1 - log superblock;	 * page 2 - log data page: A SYNC log record is written	 *          into this page at logform time;	 * pages 3-N - log data page: set to empty log data pages;	 */	/*	 *      init log superblock: log page 1	 */	logsuper = (struct logsuper *) bp->l_ldata;	logsuper->magic = cpu_to_le32(LOGMAGIC);	logsuper->version = cpu_to_le32(LOGVERSION);	logsuper->state = cpu_to_le32(LOGREDONE);	logsuper->flag = cpu_to_le32(sbi->mntflag);	/* ? */	logsuper->size = cpu_to_le32(npages);	logsuper->bsize = cpu_to_le32(sbi->bsize);	logsuper->l2bsize = cpu_to_le32(sbi->l2bsize);	logsuper->end = cpu_to_le32(2 * LOGPSIZE + LOGPHDRSIZE + LOGRDSIZE);	bp->l_flag = lbmWRITE | lbmSYNC | lbmDIRECT;	bp->l_blkno = logAddress + sbi->nbperpage;	lbmStartIO(bp);	if ((rc = lbmIOWait(bp, 0)))		goto exit;	/*	 *      init pages 2 to npages-1 as log data pages:	 *	 * log page sequence number (lpsn) initialization:	 *	 * pn:   0     1     2     3                 n-1	 *       +-----+-----+=====+=====+===.....===+=====+	 * lspn:             N-1   0     1           N-2	 *                   <--- N page circular file ---->	 *	 * the N (= npages-2) data pages of the log is maintained as	 * a circular file for the log records;	 * lpsn grows by 1 monotonically as each log page is written	 * to the circular file of the log;	 * and setLogpage() will not reset the page number even if	 * the eor is equal to LOGPHDRSIZE. In order for binary search	 * still work in find log end process, we have to simulate the	 * log wrap situation at the log format time.	 * The 1st log page written will have the highest lpsn. Then	 * the succeeding log pages will have ascending order of	 * the lspn starting from 0, ... (N-2)	 */	lp = (struct logpage *) bp->l_ldata;	/*	 * initialize 1st log page to be written: lpsn = N - 1,	 * write a SYNCPT log record is written to this page	 */	lp->h.page = lp->t.page = cpu_to_le32(npages - 3);	lp->h.eor = lp->t.eor = cpu_to_le16(LOGPHDRSIZE + LOGRDSIZE);	lrd_ptr = (struct lrd *) &lp->data;	lrd_ptr->logtid = 0;	lrd_ptr->backchain = 0;	lrd_ptr->type = cpu_to_le16(LOG_SYNCPT);	lrd_ptr->length = 0;	lrd_ptr->log.syncpt.sync = 0;	bp->l_blkno += sbi->nbperpage;	bp->l_flag = lbmWRITE | lbmSYNC | lbmDIRECT;	lbmStartIO(bp);	if ((rc = lbmIOWait(bp, 0)))		goto exit;	/*	 *      initialize succeeding log pages: lpsn = 0, 1, ..., (N-2)	 */	for (lspn = 0; lspn < npages - 3; lspn++) {		lp->h.page = lp->t.page = cpu_to_le32(lspn);		lp->h.eor = lp->t.eor = cpu_to_le16(LOGPHDRSIZE);		bp->l_blkno += sbi->nbperpage;		bp->l_flag = lbmWRITE | lbmSYNC | lbmDIRECT;		lbmStartIO(bp);		if ((rc = lbmIOWait(bp, 0)))			goto exit;	}	rc = 0;exit:	/*	 *      finalize log	 */	/* release the buffer */	lbmFree(bp);	return rc;}#ifdef CONFIG_JFS_STATISTICSint jfs_lmstats_read(char *buffer, char **start, off_t offset, int length,		      int *eof, void *data){	int len = 0;	off_t begin;	len += sprintf(buffer,		       "JFS Logmgr stats\n"		       "================\n"		       "commits = %d\n"		       "writes submitted = %d\n"		       "writes completed = %d\n"		       "full pages submitted = %d\n"		       "partial pages submitted = %d\n",		       lmStat.commit,		       lmStat.submitted,		       lmStat.pagedone,		       lmStat.full_page,		       lmStat.partial_page);	begin = offset;	*start = buffer + begin;	len -= begin;	if (len > length)		len = length;	else		*eof = 1;	if (len < 0)		len = 0;	return len;}#endif /* CONFIG_JFS_STATISTICS */

⌨️ 快捷键说明

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