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

📄 xfs_buf_item.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2000-2005 Silicon Graphics, Inc. * All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write the Free Software Foundation, * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */#include "xfs.h"#include "xfs_fs.h"#include "xfs_types.h"#include "xfs_bit.h"#include "xfs_log.h"#include "xfs_inum.h"#include "xfs_trans.h"#include "xfs_sb.h"#include "xfs_ag.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_buf_item.h"#include "xfs_trans_priv.h"#include "xfs_error.h"kmem_zone_t	*xfs_buf_item_zone;#ifdef XFS_TRANS_DEBUG/* * This function uses an alternate strategy for tracking the bytes * that the user requests to be logged.  This can then be used * in conjunction with the bli_orig array in the buf log item to * catch bugs in our callers' code. * * We also double check the bits set in xfs_buf_item_log using a * simple algorithm to check that every byte is accounted for. */STATIC voidxfs_buf_item_log_debug(	xfs_buf_log_item_t	*bip,	uint			first,	uint			last){	uint	x;	uint	byte;	uint	nbytes;	uint	chunk_num;	uint	word_num;	uint	bit_num;	uint	bit_set;	uint	*wordp;	ASSERT(bip->bli_logged != NULL);	byte = first;	nbytes = last - first + 1;	bfset(bip->bli_logged, first, nbytes);	for (x = 0; x < nbytes; x++) {		chunk_num = byte >> XFS_BLI_SHIFT;		word_num = chunk_num >> BIT_TO_WORD_SHIFT;		bit_num = chunk_num & (NBWORD - 1);		wordp = &(bip->bli_format.blf_data_map[word_num]);		bit_set = *wordp & (1 << bit_num);		ASSERT(bit_set);		byte++;	}}/* * This function is called when we flush something into a buffer without * logging it.  This happens for things like inodes which are logged * separately from the buffer. */voidxfs_buf_item_flush_log_debug(	xfs_buf_t	*bp,	uint		first,	uint		last){	xfs_buf_log_item_t	*bip;	uint			nbytes;	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);	if ((bip == NULL) || (bip->bli_item.li_type != XFS_LI_BUF)) {		return;	}	ASSERT(bip->bli_logged != NULL);	nbytes = last - first + 1;	bfset(bip->bli_logged, first, nbytes);}/* * This function is called to verify that our callers have logged * all the bytes that they changed. * * It does this by comparing the original copy of the buffer stored in * the buf log item's bli_orig array to the current copy of the buffer * and ensuring that all bytes which mismatch are set in the bli_logged * array of the buf log item. */STATIC voidxfs_buf_item_log_check(	xfs_buf_log_item_t	*bip){	char		*orig;	char		*buffer;	int		x;	xfs_buf_t	*bp;	ASSERT(bip->bli_orig != NULL);	ASSERT(bip->bli_logged != NULL);	bp = bip->bli_buf;	ASSERT(XFS_BUF_COUNT(bp) > 0);	ASSERT(XFS_BUF_PTR(bp) != NULL);	orig = bip->bli_orig;	buffer = XFS_BUF_PTR(bp);	for (x = 0; x < XFS_BUF_COUNT(bp); x++) {		if (orig[x] != buffer[x] && !btst(bip->bli_logged, x))			cmn_err(CE_PANIC,	"xfs_buf_item_log_check bip %x buffer %x orig %x index %d",				bip, bp, orig, x);	}}#else#define		xfs_buf_item_log_debug(x,y,z)#define		xfs_buf_item_log_check(x)#endifSTATIC void	xfs_buf_error_relse(xfs_buf_t *bp);STATIC void	xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip);/* * This returns the number of log iovecs needed to log the * given buf log item. * * It calculates this as 1 iovec for the buf log format structure * and 1 for each stretch of non-contiguous chunks to be logged. * Contiguous chunks are logged in a single iovec. * * If the XFS_BLI_STALE flag has been set, then log nothing. */STATIC uintxfs_buf_item_size(	xfs_buf_log_item_t	*bip){	uint		nvecs;	int		next_bit;	int		last_bit;	xfs_buf_t	*bp;	ASSERT(atomic_read(&bip->bli_refcount) > 0);	if (bip->bli_flags & XFS_BLI_STALE) {		/*		 * The buffer is stale, so all we need to log		 * is the buf log format structure with the		 * cancel flag in it.		 */		xfs_buf_item_trace("SIZE STALE", bip);		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);		return 1;	}	bp = bip->bli_buf;	ASSERT(bip->bli_flags & XFS_BLI_LOGGED);	nvecs = 1;	last_bit = xfs_next_bit(bip->bli_format.blf_data_map,					 bip->bli_format.blf_map_size, 0);	ASSERT(last_bit != -1);	nvecs++;	while (last_bit != -1) {		/*		 * This takes the bit number to start looking from and		 * returns the next set bit from there.  It returns -1		 * if there are no more bits set or the start bit is		 * beyond the end of the bitmap.		 */		next_bit = xfs_next_bit(bip->bli_format.blf_data_map,						 bip->bli_format.blf_map_size,						 last_bit + 1);		/*		 * If we run out of bits, leave the loop,		 * else if we find a new set of bits bump the number of vecs,		 * else keep scanning the current set of bits.		 */		if (next_bit == -1) {			last_bit = -1;		} else if (next_bit != last_bit + 1) {			last_bit = next_bit;			nvecs++;		} else if (xfs_buf_offset(bp, next_bit * XFS_BLI_CHUNK) !=			   (xfs_buf_offset(bp, last_bit * XFS_BLI_CHUNK) +			    XFS_BLI_CHUNK)) {			last_bit = next_bit;			nvecs++;		} else {			last_bit++;		}	}	xfs_buf_item_trace("SIZE NORM", bip);	return nvecs;}/* * This is called to fill in the vector of log iovecs for the * given log buf item.  It fills the first entry with a buf log * format structure, and the rest point to contiguous chunks * within the buffer. */STATIC voidxfs_buf_item_format(	xfs_buf_log_item_t	*bip,	xfs_log_iovec_t		*log_vector){	uint		base_size;	uint		nvecs;	xfs_log_iovec_t	*vecp;	xfs_buf_t	*bp;	int		first_bit;	int		last_bit;	int		next_bit;	uint		nbits;	uint		buffer_offset;	ASSERT(atomic_read(&bip->bli_refcount) > 0);	ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||	       (bip->bli_flags & XFS_BLI_STALE));	bp = bip->bli_buf;	vecp = log_vector;	/*	 * The size of the base structure is the size of the	 * declared structure plus the space for the extra words	 * of the bitmap.  We subtract one from the map size, because	 * the first element of the bitmap is accounted for in the	 * size of the base structure.	 */	base_size =		(uint)(sizeof(xfs_buf_log_format_t) +		       ((bip->bli_format.blf_map_size - 1) * sizeof(uint)));	vecp->i_addr = (xfs_caddr_t)&bip->bli_format;	vecp->i_len = base_size;	XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BFORMAT);	vecp++;	nvecs = 1;	if (bip->bli_flags & XFS_BLI_STALE) {		/*		 * The buffer is stale, so all we need to log		 * is the buf log format structure with the		 * cancel flag in it.		 */		xfs_buf_item_trace("FORMAT STALE", bip);		ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL);		bip->bli_format.blf_size = nvecs;		return;	}	/*	 * Fill in an iovec for each set of contiguous chunks.	 */	first_bit = xfs_next_bit(bip->bli_format.blf_data_map,					 bip->bli_format.blf_map_size, 0);	ASSERT(first_bit != -1);	last_bit = first_bit;	nbits = 1;	for (;;) {		/*		 * This takes the bit number to start looking from and		 * returns the next set bit from there.  It returns -1		 * if there are no more bits set or the start bit is		 * beyond the end of the bitmap.		 */		next_bit = xfs_next_bit(bip->bli_format.blf_data_map,						 bip->bli_format.blf_map_size,						 (uint)last_bit + 1);		/*		 * If we run out of bits fill in the last iovec and get		 * out of the loop.		 * Else if we start a new set of bits then fill in the		 * iovec for the series we were looking at and start		 * counting the bits in the new one.		 * Else we're still in the same set of bits so just		 * keep counting and scanning.		 */		if (next_bit == -1) {			buffer_offset = first_bit * XFS_BLI_CHUNK;			vecp->i_addr = xfs_buf_offset(bp, buffer_offset);			vecp->i_len = nbits * XFS_BLI_CHUNK;			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);			nvecs++;			break;		} else if (next_bit != last_bit + 1) {			buffer_offset = first_bit * XFS_BLI_CHUNK;			vecp->i_addr = xfs_buf_offset(bp, buffer_offset);			vecp->i_len = nbits * XFS_BLI_CHUNK;			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);			nvecs++;			vecp++;			first_bit = next_bit;			last_bit = next_bit;			nbits = 1;		} else if (xfs_buf_offset(bp, next_bit << XFS_BLI_SHIFT) !=			   (xfs_buf_offset(bp, last_bit << XFS_BLI_SHIFT) +			    XFS_BLI_CHUNK)) {			buffer_offset = first_bit * XFS_BLI_CHUNK;			vecp->i_addr = xfs_buf_offset(bp, buffer_offset);			vecp->i_len = nbits * XFS_BLI_CHUNK;			XLOG_VEC_SET_TYPE(vecp, XLOG_REG_TYPE_BCHUNK);/* You would think we need to bump the nvecs here too, but we do not * this number is used by recovery, and it gets confused by the boundary * split here *			nvecs++; */			vecp++;			first_bit = next_bit;			last_bit = next_bit;			nbits = 1;		} else {			last_bit++;			nbits++;		}	}	bip->bli_format.blf_size = nvecs;	/*	 * Check to make sure everything is consistent.	 */	xfs_buf_item_trace("FORMAT NORM", bip);	xfs_buf_item_log_check(bip);}/* * This is called to pin the buffer associated with the buf log * item in memory so it cannot be written out.  Simply call bpin() * on the buffer to do this. */STATIC voidxfs_buf_item_pin(	xfs_buf_log_item_t	*bip){	xfs_buf_t	*bp;	bp = bip->bli_buf;	ASSERT(XFS_BUF_ISBUSY(bp));	ASSERT(atomic_read(&bip->bli_refcount) > 0);	ASSERT((bip->bli_flags & XFS_BLI_LOGGED) ||	       (bip->bli_flags & XFS_BLI_STALE));	xfs_buf_item_trace("PIN", bip);	xfs_buftrace("XFS_PIN", bp);	xfs_bpin(bp);}/* * This is called to unpin the buffer associated with the buf log * item which was previously pinned with a call to xfs_buf_item_pin(). * Just call bunpin() on the buffer to do this. * * Also drop the reference to the buf item for the current transaction. * If the XFS_BLI_STALE flag is set and we are the last reference, * then free up the buf log item and unlock the buffer. */STATIC voidxfs_buf_item_unpin(	xfs_buf_log_item_t	*bip,	int			stale){	xfs_mount_t	*mp;	xfs_buf_t	*bp;	int		freed;	SPLDECL(s);	bp = bip->bli_buf;	ASSERT(bp != NULL);	ASSERT(XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *) == bip);	ASSERT(atomic_read(&bip->bli_refcount) > 0);	xfs_buf_item_trace("UNPIN", bip);	xfs_buftrace("XFS_UNPIN", bp);	freed = atomic_dec_and_test(&bip->bli_refcount);	mp = bip->bli_item.li_mountp;	xfs_bunpin(bp);	if (freed && stale) {		ASSERT(bip->bli_flags & XFS_BLI_STALE);

⌨️ 快捷键说明

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