/*
* 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"
#include "xfs_trace.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 void
xfs_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.
*/
void
xfs_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 void
xfs_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)
#endif
STATIC 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