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

📄 xfs_buf_item.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	bip->bli_flags |= XFS_BLI_DIRTY;	/*	 * Convert byte offsets to bit numbers.	 */	first_bit = first >> XFS_BLI_SHIFT;	last_bit = last >> XFS_BLI_SHIFT;	/*	 * Calculate the total number of bits to be set.	 */	bits_to_set = last_bit - first_bit + 1;	/*	 * Get a pointer to the first word in the bitmap	 * to set a bit in.	 */	word_num = first_bit >> BIT_TO_WORD_SHIFT;	wordp = &(bip->bli_format.blf_data_map[word_num]);	/*	 * Calculate the starting bit in the first word.	 */	bit = first_bit & (uint)(NBWORD - 1);	/*	 * First set any bits in the first word of our range.	 * If it starts at bit 0 of the word, it will be	 * set below rather than here.  That is what the variable	 * bit tells us. The variable bits_set tracks the number	 * of bits that have been set so far.  End_bit is the number	 * of the last bit to be set in this word plus one.	 */	if (bit) {		end_bit = MIN(bit + bits_to_set, (uint)NBWORD);		mask = ((1 << (end_bit - bit)) - 1) << bit;		*wordp |= mask;		wordp++;		bits_set = end_bit - bit;	} else {		bits_set = 0;	}	/*	 * Now set bits a whole word at a time that are between	 * first_bit and last_bit.	 */	while ((bits_to_set - bits_set) >= NBWORD) {		*wordp |= 0xffffffff;		bits_set += NBWORD;		wordp++;	}	/*	 * Finally, set any bits left to be set in one last partial word.	 */	end_bit = bits_to_set - bits_set;	if (end_bit) {		mask = (1 << end_bit) - 1;		*wordp |= mask;	}	xfs_buf_item_log_debug(bip, first, last);}/* * Return 1 if the buffer has some data that has been logged (at any * point, not just the current transaction) and 0 if not. */uintxfs_buf_item_dirty(	xfs_buf_log_item_t	*bip){	return (bip->bli_flags & XFS_BLI_DIRTY);}/* * This is called when the buf log item is no longer needed.  It should * free the buf log item associated with the given buffer and clear * the buffer's pointer to the buf log item.  If there are no more * items in the list, clear the b_iodone field of the buffer (see * xfs_buf_attach_iodone() below). */voidxfs_buf_item_relse(	xfs_buf_t	*bp){	xfs_buf_log_item_t	*bip;	xfs_buftrace("XFS_RELSE", bp);	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);	XFS_BUF_SET_FSPRIVATE(bp, bip->bli_item.li_bio_list);	if ((XFS_BUF_FSPRIVATE(bp, void *) == NULL) &&	    (XFS_BUF_IODONE_FUNC(bp) != NULL)) {		XFS_BUF_CLR_IODONE_FUNC(bp);	}#ifdef XFS_TRANS_DEBUG	kmem_free(bip->bli_orig, XFS_BUF_COUNT(bp));	bip->bli_orig = NULL;	kmem_free(bip->bli_logged, XFS_BUF_COUNT(bp) / NBBY);	bip->bli_logged = NULL;#endif /* XFS_TRANS_DEBUG */#ifdef XFS_BLI_TRACE	ktrace_free(bip->bli_trace);#endif	kmem_zone_free(xfs_buf_item_zone, bip);}/* * Add the given log item with its callback to the list of callbacks * to be called when the buffer's I/O completes.  If it is not set * already, set the buffer's b_iodone() routine to be * xfs_buf_iodone_callbacks() and link the log item into the list of * items rooted at b_fsprivate.  Items are always added as the second * entry in the list if there is a first, because the buf item code * assumes that the buf log item is first. */voidxfs_buf_attach_iodone(	xfs_buf_t	*bp,	void		(*cb)(xfs_buf_t *, xfs_log_item_t *),	xfs_log_item_t	*lip){	xfs_log_item_t	*head_lip;	ASSERT(XFS_BUF_ISBUSY(bp));	ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);	lip->li_cb = cb;	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {		head_lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);		lip->li_bio_list = head_lip->li_bio_list;		head_lip->li_bio_list = lip;	} else {		XFS_BUF_SET_FSPRIVATE(bp, lip);	}	ASSERT((XFS_BUF_IODONE_FUNC(bp) == xfs_buf_iodone_callbacks) ||	       (XFS_BUF_IODONE_FUNC(bp) == NULL));	XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks);}STATIC voidxfs_buf_do_callbacks(	xfs_buf_t	*bp,	xfs_log_item_t	*lip){	xfs_log_item_t	*nlip;	while (lip != NULL) {		nlip = lip->li_bio_list;		ASSERT(lip->li_cb != NULL);		/*		 * Clear the next pointer so we don't have any		 * confusion if the item is added to another buf.		 * Don't touch the log item after calling its		 * callback, because it could have freed itself.		 */		lip->li_bio_list = NULL;		lip->li_cb(bp, lip);		lip = nlip;	}}/* * This is the iodone() function for buffers which have had callbacks * attached to them by xfs_buf_attach_iodone().  It should remove each * log item from the buffer's list and call the callback of each in turn. * When done, the buffer's fsprivate field is set to NULL and the buffer * is unlocked with a call to iodone(). */voidxfs_buf_iodone_callbacks(	xfs_buf_t	*bp){	xfs_log_item_t	*lip;	static ulong	lasttime;	static xfs_buftarg_t *lasttarg;	xfs_mount_t	*mp;	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);	lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);	if (XFS_BUF_GETERROR(bp) != 0) {		/*		 * If we've already decided to shutdown the filesystem		 * because of IO errors, there's no point in giving this		 * a retry.		 */		mp = lip->li_mountp;		if (XFS_FORCED_SHUTDOWN(mp)) {			ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp);			XFS_BUF_SUPER_STALE(bp);			xfs_buftrace("BUF_IODONE_CB", bp);			xfs_buf_do_callbacks(bp, lip);			XFS_BUF_SET_FSPRIVATE(bp, NULL);			XFS_BUF_CLR_IODONE_FUNC(bp);			/*			 * XFS_SHUT flag gets set when we go thru the			 * entire buffer cache and deliberately start			 * throwing away delayed write buffers.			 * Since there's no biowait done on those,			 * we should just brelse them.			 */			if (XFS_BUF_ISSHUT(bp)) {			    XFS_BUF_UNSHUT(bp);				xfs_buf_relse(bp);			} else {				xfs_biodone(bp);			}			return;		}		if ((XFS_BUF_TARGET(bp) != lasttarg) ||		    (time_after(jiffies, (lasttime + 5*HZ)))) {			lasttime = jiffies;			cmn_err(CE_ALERT, "Device %s, XFS metadata write error"					" block 0x%llx in %s",				XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),			      (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname);		}		lasttarg = XFS_BUF_TARGET(bp);		if (XFS_BUF_ISASYNC(bp)) {			/*			 * If the write was asynchronous then noone will be			 * looking for the error.  Clear the error state			 * and write the buffer out again delayed write.			 *			 * XXXsup This is OK, so long as we catch these			 * before we start the umount; we don't want these			 * DELWRI metadata bufs to be hanging around.			 */			XFS_BUF_ERROR(bp,0); /* errno of 0 unsets the flag */			if (!(XFS_BUF_ISSTALE(bp))) {				XFS_BUF_DELAYWRITE(bp);				XFS_BUF_DONE(bp);				XFS_BUF_SET_START(bp);			}			ASSERT(XFS_BUF_IODONE_FUNC(bp));			xfs_buftrace("BUF_IODONE ASYNC", bp);			xfs_buf_relse(bp);		} else {			/*			 * If the write of the buffer was not asynchronous,			 * then we want to make sure to return the error			 * to the caller of bwrite().  Because of this we			 * cannot clear the B_ERROR state at this point.			 * Instead we install a callback function that			 * will be called when the buffer is released, and			 * that routine will clear the error state and			 * set the buffer to be written out again after			 * some delay.			 */			/* We actually overwrite the existing b-relse			   function at times, but we're gonna be shutting down			   anyway. */			XFS_BUF_SET_BRELSE_FUNC(bp,xfs_buf_error_relse);			XFS_BUF_DONE(bp);			XFS_BUF_V_IODONESEMA(bp);		}		return;	}#ifdef XFSERRORDEBUG	xfs_buftrace("XFS BUFCB NOERR", bp);#endif	xfs_buf_do_callbacks(bp, lip);	XFS_BUF_SET_FSPRIVATE(bp, NULL);	XFS_BUF_CLR_IODONE_FUNC(bp);	xfs_biodone(bp);}/* * This is a callback routine attached to a buffer which gets an error * when being written out synchronously. */STATIC voidxfs_buf_error_relse(	xfs_buf_t	*bp){	xfs_log_item_t	*lip;	xfs_mount_t	*mp;	lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);	mp = (xfs_mount_t *)lip->li_mountp;	ASSERT(XFS_BUF_TARGET(bp) == mp->m_ddev_targp);	XFS_BUF_STALE(bp);	XFS_BUF_DONE(bp);	XFS_BUF_UNDELAYWRITE(bp);	XFS_BUF_ERROR(bp,0);	xfs_buftrace("BUF_ERROR_RELSE", bp);	if (! XFS_FORCED_SHUTDOWN(mp))		xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR);	/*	 * We have to unpin the pinned buffers so do the	 * callbacks.	 */	xfs_buf_do_callbacks(bp, lip);	XFS_BUF_SET_FSPRIVATE(bp, NULL);	XFS_BUF_CLR_IODONE_FUNC(bp);	XFS_BUF_SET_BRELSE_FUNC(bp,NULL);	xfs_buf_relse(bp);}/* * This is the iodone() function for buffers which have been * logged.  It is called when they are eventually flushed out. * It should remove the buf item from the AIL, and free the buf item. * It is called by xfs_buf_iodone_callbacks() above which will take * care of cleaning up the buffer itself. *//* ARGSUSED */voidxfs_buf_iodone(	xfs_buf_t		*bp,	xfs_buf_log_item_t	*bip){	struct xfs_mount	*mp;	SPLDECL(s);	ASSERT(bip->bli_buf == bp);	mp = bip->bli_item.li_mountp;	/*	 * If we are forcibly shutting down, this may well be	 * off the AIL already. That's because we simulate the	 * log-committed callbacks to unpin these buffers. Or we may never	 * have put this item on AIL because of the transaction was	 * aborted forcibly. xfs_trans_delete_ail() takes care of these.	 *	 * Either way, AIL is useless if we're forcing a shutdown.	 */	AIL_LOCK(mp,s);	/*	 * xfs_trans_delete_ail() drops the AIL lock.	 */	xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip, s);#ifdef XFS_TRANS_DEBUG	kmem_free(bip->bli_orig, XFS_BUF_COUNT(bp));	bip->bli_orig = NULL;	kmem_free(bip->bli_logged, XFS_BUF_COUNT(bp) / NBBY);	bip->bli_logged = NULL;#endif /* XFS_TRANS_DEBUG */#ifdef XFS_BLI_TRACE	ktrace_free(bip->bli_trace);#endif	kmem_zone_free(xfs_buf_item_zone, bip);}#if defined(XFS_BLI_TRACE)voidxfs_buf_item_trace(	char			*id,	xfs_buf_log_item_t	*bip){	xfs_buf_t		*bp;	ASSERT(bip->bli_trace != NULL);	bp = bip->bli_buf;	ktrace_enter(bip->bli_trace,		     (void *)id,		     (void *)bip->bli_buf,		     (void *)((unsigned long)bip->bli_flags),		     (void *)((unsigned long)bip->bli_recur),		     (void *)((unsigned long)atomic_read(&bip->bli_refcount)),		     (void *)((unsigned long)				(0xFFFFFFFF & XFS_BUF_ADDR(bp) >> 32)),		     (void *)((unsigned long)(0xFFFFFFFF & XFS_BUF_ADDR(bp))),		     (void *)((unsigned long)XFS_BUF_COUNT(bp)),		     (void *)((unsigned long)XFS_BUF_BFLAGS(bp)),		     XFS_BUF_FSPRIVATE(bp, void *),		     XFS_BUF_FSPRIVATE2(bp, void *),		     (void *)(unsigned long)XFS_BUF_ISPINNED(bp),		     (void *)XFS_BUF_IODONE_FUNC(bp),		     (void *)((unsigned long)(XFS_BUF_VALUSEMA(bp))),		     (void *)bip->bli_item.li_desc,		     (void *)((unsigned long)bip->bli_item.li_flags));}#endif /* XFS_BLI_TRACE */

⌨️ 快捷键说明

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