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

📄 xfs_buf_item.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);		ASSERT(!(XFS_BUF_ISDELAYWRITE(bp)));		ASSERT(XFS_BUF_ISSTALE(bp));		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);		xfs_buf_item_trace("UNPIN STALE", bip);		xfs_buftrace("XFS_UNPIN STALE", bp);		/*		 * If we get called here because of an IO error, we may		 * or may not have the item on the AIL. xfs_trans_delete_ail()		 * will take care of that situation.		 * xfs_trans_delete_ail() drops the AIL lock.		 */		if (bip->bli_flags & XFS_BLI_STALE_INODE) {			xfs_buf_do_callbacks(bp, (xfs_log_item_t *)bip);			XFS_BUF_SET_FSPRIVATE(bp, NULL);			XFS_BUF_CLR_IODONE_FUNC(bp);		} else {			AIL_LOCK(mp,s);			xfs_trans_delete_ail(mp, (xfs_log_item_t *)bip, s);			xfs_buf_item_relse(bp);			ASSERT(XFS_BUF_FSPRIVATE(bp, void *) == NULL);		}		xfs_buf_relse(bp);	}}/* * this is called from uncommit in the forced-shutdown path. * we need to check to see if the reference count on the log item * is going to drop to zero.  If so, unpin will free the log item * so we need to free the item's descriptor (that points to the item) * in the transaction. */STATIC voidxfs_buf_item_unpin_remove(	xfs_buf_log_item_t	*bip,	xfs_trans_t		*tp){	xfs_buf_t		*bp;	xfs_log_item_desc_t	*lidp;	int			stale = 0;	bp = bip->bli_buf;	/*	 * will xfs_buf_item_unpin() call xfs_buf_item_relse()?	 */	if ((atomic_read(&bip->bli_refcount) == 1) &&	    (bip->bli_flags & XFS_BLI_STALE)) {		ASSERT(XFS_BUF_VALUSEMA(bip->bli_buf) <= 0);		xfs_buf_item_trace("UNPIN REMOVE", bip);		xfs_buftrace("XFS_UNPIN_REMOVE", bp);		/*		 * yes -- clear the xaction descriptor in-use flag		 * and free the chunk if required.  We can safely		 * do some work here and then call buf_item_unpin		 * to do the rest because if the if is true, then		 * we are holding the buffer locked so no one else		 * will be able to bump up the refcount.		 */		lidp = xfs_trans_find_item(tp, (xfs_log_item_t *) bip);		stale = lidp->lid_flags & XFS_LID_BUF_STALE;		xfs_trans_free_item(tp, lidp);		/*		 * Since the transaction no longer refers to the buffer,		 * the buffer should no longer refer to the transaction.		 */		XFS_BUF_SET_FSPRIVATE2(bp, NULL);	}	xfs_buf_item_unpin(bip, stale);	return;}/* * This is called to attempt to lock the buffer associated with this * buf log item.  Don't sleep on the buffer lock.  If we can't get * the lock right away, return 0.  If we can get the lock, pull the * buffer from the free list, mark it busy, and return 1. */STATIC uintxfs_buf_item_trylock(	xfs_buf_log_item_t	*bip){	xfs_buf_t	*bp;	bp = bip->bli_buf;	if (XFS_BUF_ISPINNED(bp)) {		return XFS_ITEM_PINNED;	}	if (!XFS_BUF_CPSEMA(bp)) {		return XFS_ITEM_LOCKED;	}	/*	 * Remove the buffer from the free list.  Only do this	 * if it's on the free list.  Private buffers like the	 * superblock buffer are not.	 */	XFS_BUF_HOLD(bp);	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));	xfs_buf_item_trace("TRYLOCK SUCCESS", bip);	return XFS_ITEM_SUCCESS;}/* * Release the buffer associated with the buf log item. * If there is no dirty logged data associated with the * buffer recorded in the buf log item, then free the * buf log item and remove the reference to it in the * buffer. * * This call ignores the recursion count.  It is only called * when the buffer should REALLY be unlocked, regardless * of the recursion count. * * If the XFS_BLI_HOLD flag is set in the buf log item, then * free the log item if necessary but do not unlock the buffer. * This is for support of xfs_trans_bhold(). Make sure the * XFS_BLI_HOLD field is cleared if we don't free the item. */STATIC voidxfs_buf_item_unlock(	xfs_buf_log_item_t	*bip){	int		aborted;	xfs_buf_t	*bp;	uint		hold;	bp = bip->bli_buf;	xfs_buftrace("XFS_UNLOCK", bp);	/*	 * Clear the buffer's association with this transaction.	 */	XFS_BUF_SET_FSPRIVATE2(bp, NULL);	/*	 * If this is a transaction abort, don't return early.	 * Instead, allow the brelse to happen.	 * Normally it would be done for stale (cancelled) buffers	 * at unpin time, but we'll never go through the pin/unpin	 * cycle if we abort inside commit.	 */	aborted = (bip->bli_item.li_flags & XFS_LI_ABORTED) != 0;	/*	 * If the buf item is marked stale, then don't do anything.	 * We'll unlock the buffer and free the buf item when the	 * buffer is unpinned for the last time.	 */	if (bip->bli_flags & XFS_BLI_STALE) {		bip->bli_flags &= ~XFS_BLI_LOGGED;		xfs_buf_item_trace("UNLOCK STALE", bip);		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);		if (!aborted)			return;	}	/*	 * Drop the transaction's reference to the log item if	 * it was not logged as part of the transaction.  Otherwise	 * we'll drop the reference in xfs_buf_item_unpin() when	 * the transaction is really through with the buffer.	 */	if (!(bip->bli_flags & XFS_BLI_LOGGED)) {		atomic_dec(&bip->bli_refcount);	} else {		/*		 * Clear the logged flag since this is per		 * transaction state.		 */		bip->bli_flags &= ~XFS_BLI_LOGGED;	}	/*	 * Before possibly freeing the buf item, determine if we should	 * release the buffer at the end of this routine.	 */	hold = bip->bli_flags & XFS_BLI_HOLD;	xfs_buf_item_trace("UNLOCK", bip);	/*	 * If the buf item isn't tracking any data, free it.	 * Otherwise, if XFS_BLI_HOLD is set clear it.	 */	if (xfs_bitmap_empty(bip->bli_format.blf_data_map,			     bip->bli_format.blf_map_size)) {		xfs_buf_item_relse(bp);	} else if (hold) {		bip->bli_flags &= ~XFS_BLI_HOLD;	}	/*	 * Release the buffer if XFS_BLI_HOLD was not set.	 */	if (!hold) {		xfs_buf_relse(bp);	}}/* * This is called to find out where the oldest active copy of the * buf log item in the on disk log resides now that the last log * write of it completed at the given lsn. * We always re-log all the dirty data in a buffer, so usually the * latest copy in the on disk log is the only one that matters.  For * those cases we simply return the given lsn. * * The one exception to this is for buffers full of newly allocated * inodes.  These buffers are only relogged with the XFS_BLI_INODE_BUF * flag set, indicating that only the di_next_unlinked fields from the * inodes in the buffers will be replayed during recovery.  If the * original newly allocated inode images have not yet been flushed * when the buffer is so relogged, then we need to make sure that we * keep the old images in the 'active' portion of the log.  We do this * by returning the original lsn of that transaction here rather than * the current one. */STATIC xfs_lsn_txfs_buf_item_committed(	xfs_buf_log_item_t	*bip,	xfs_lsn_t		lsn){	xfs_buf_item_trace("COMMITTED", bip);	if ((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) &&	    (bip->bli_item.li_lsn != 0)) {		return bip->bli_item.li_lsn;	}	return (lsn);}/* * This is called to asynchronously write the buffer associated with this * buf log item out to disk. The buffer will already have been locked by * a successful call to xfs_buf_item_trylock().  If the buffer still has * B_DELWRI set, then get it going out to disk with a call to bawrite(). * If not, then just release the buffer. */STATIC voidxfs_buf_item_push(	xfs_buf_log_item_t	*bip){	xfs_buf_t	*bp;	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));	xfs_buf_item_trace("PUSH", bip);	bp = bip->bli_buf;	if (XFS_BUF_ISDELAYWRITE(bp)) {		xfs_bawrite(bip->bli_item.li_mountp, bp);	} else {		xfs_buf_relse(bp);	}}/* ARGSUSED */STATIC voidxfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn){}/* * This is the ops vector shared by all buf log items. */static struct xfs_item_ops xfs_buf_item_ops = {	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_buf_item_size,	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))					xfs_buf_item_format,	.iop_pin	= (void(*)(xfs_log_item_t*))xfs_buf_item_pin,	.iop_unpin	= (void(*)(xfs_log_item_t*, int))xfs_buf_item_unpin,	.iop_unpin_remove = (void(*)(xfs_log_item_t*, xfs_trans_t *))					xfs_buf_item_unpin_remove,	.iop_trylock	= (uint(*)(xfs_log_item_t*))xfs_buf_item_trylock,	.iop_unlock	= (void(*)(xfs_log_item_t*))xfs_buf_item_unlock,	.iop_committed	= (xfs_lsn_t(*)(xfs_log_item_t*, xfs_lsn_t))					xfs_buf_item_committed,	.iop_push	= (void(*)(xfs_log_item_t*))xfs_buf_item_push,	.iop_pushbuf	= NULL,	.iop_committing = (void(*)(xfs_log_item_t*, xfs_lsn_t))					xfs_buf_item_committing};/* * Allocate a new buf log item to go with the given buffer. * Set the buffer's b_fsprivate field to point to the new * buf log item.  If there are other item's attached to the * buffer (see xfs_buf_attach_iodone() below), then put the * buf log item at the front. */voidxfs_buf_item_init(	xfs_buf_t	*bp,	xfs_mount_t	*mp){	xfs_log_item_t		*lip;	xfs_buf_log_item_t	*bip;	int			chunks;	int			map_size;	/*	 * Check to see if there is already a buf log item for	 * this buffer.  If there is, it is guaranteed to be	 * the first.  If we do already have one, there is	 * nothing to do here so return.	 */	if (XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *) != mp)		XFS_BUF_SET_FSPRIVATE3(bp, mp);	XFS_BUF_SET_BDSTRAT_FUNC(bp, xfs_bdstrat_cb);	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {		lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);		if (lip->li_type == XFS_LI_BUF) {			return;		}	}	/*	 * chunks is the number of XFS_BLI_CHUNK size pieces	 * the buffer can be divided into. Make sure not to	 * truncate any pieces.  map_size is the size of the	 * bitmap needed to describe the chunks of the buffer.	 */	chunks = (int)((XFS_BUF_COUNT(bp) + (XFS_BLI_CHUNK - 1)) >> XFS_BLI_SHIFT);	map_size = (int)((chunks + NBWORD) >> BIT_TO_WORD_SHIFT);	bip = (xfs_buf_log_item_t*)kmem_zone_zalloc(xfs_buf_item_zone,						    KM_SLEEP);	bip->bli_item.li_type = XFS_LI_BUF;	bip->bli_item.li_ops = &xfs_buf_item_ops;	bip->bli_item.li_mountp = mp;	bip->bli_buf = bp;	bip->bli_format.blf_type = XFS_LI_BUF;	bip->bli_format.blf_blkno = (__int64_t)XFS_BUF_ADDR(bp);	bip->bli_format.blf_len = (ushort)BTOBB(XFS_BUF_COUNT(bp));	bip->bli_format.blf_map_size = map_size;#ifdef XFS_BLI_TRACE	bip->bli_trace = ktrace_alloc(XFS_BLI_TRACE_SIZE, KM_SLEEP);#endif#ifdef XFS_TRANS_DEBUG	/*	 * Allocate the arrays for tracking what needs to be logged	 * and what our callers request to be logged.  bli_orig	 * holds a copy of the original, clean buffer for comparison	 * against, and bli_logged keeps a 1 bit flag per byte in	 * the buffer to indicate which bytes the callers have asked	 * to have logged.	 */	bip->bli_orig = (char *)kmem_alloc(XFS_BUF_COUNT(bp), KM_SLEEP);	memcpy(bip->bli_orig, XFS_BUF_PTR(bp), XFS_BUF_COUNT(bp));	bip->bli_logged = (char *)kmem_zalloc(XFS_BUF_COUNT(bp) / NBBY, KM_SLEEP);#endif	/*	 * Put the buf item into the list of items attached to the	 * buffer at the front.	 */	if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) {		bip->bli_item.li_bio_list =				XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *);	}	XFS_BUF_SET_FSPRIVATE(bp, bip);}/* * Mark bytes first through last inclusive as dirty in the buf * item's bitmap. */voidxfs_buf_item_log(	xfs_buf_log_item_t	*bip,	uint			first,	uint			last){	uint		first_bit;	uint		last_bit;	uint		bits_to_set;	uint		bits_set;	uint		word_num;	uint		*wordp;	uint		bit;	uint		end_bit;	uint		mask;	/*	 * Mark the item as having some dirty data for	 * quick reference in xfs_buf_item_dirty.	 */

⌨️ 快捷键说明

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