xfs_buf_item.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,222 行 · 第 1/3 页

C
1,222
字号
/* * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 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. * * Further, this software is distributed without any warranty that it is * free of the rightful claim of any third person regarding infringement * or the like.  Any license provided herein, whether implied or * otherwise, applies only to this software file.  Patent licenses, if * any, provided herein do not apply to combinations of this program with * other software, or any other product whatsoever. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. * * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, * Mountain View, CA  94043, or: * * http://www.sgi.com * * For further information regarding this notice, see: * * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ *//* * This file contains the implementation of the xfs_buf_log_item. * It contains the item operations used to manipulate the buf log * items as well as utility routines used by the buffer specific * transaction routines. */#include "xfs.h"#include "xfs_macros.h"#include "xfs_types.h"#include "xfs_inum.h"#include "xfs_log.h"#include "xfs_trans.h"#include "xfs_buf_item.h"#include "xfs_sb.h"#include "xfs_dir.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_trans_priv.h"#include "xfs_rw.h"#include "xfs_bit.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 caller's 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 miscompare 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. */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. */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;	ASSERT(XFS_BUF_BP_ISMAPPED(bp));	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;	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;			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;			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;/* 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. */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. */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);

⌨️ 快捷键说明

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