xfs_trans_buf.c

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

C
1,094
字号
/* * Copyright (c) 2000-2002 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/ */#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_ag.h"#include "xfs_dir.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_trans_priv.h"#include "xfs_error.h"#include "xfs_rw.h"STATIC xfs_buf_t *xfs_trans_buf_item_match(xfs_trans_t *, xfs_buftarg_t *,		xfs_daddr_t, int);STATIC xfs_buf_t *xfs_trans_buf_item_match_all(xfs_trans_t *, xfs_buftarg_t *,		xfs_daddr_t, int);/* * Get and lock the buffer for the caller if it is not already * locked within the given transaction.  If it is already locked * within the transaction, just increment its lock recursion count * and return a pointer to it. * * Use the fast path function xfs_trans_buf_item_match() or the buffer * cache routine incore_match() to find the buffer * if it is already owned by this transaction. * * If we don't already own the buffer, use get_buf() to get it. * If it doesn't yet have an associated xfs_buf_log_item structure, * then allocate one and add the item to this transaction. * * If the transaction pointer is NULL, make this just a normal * get_buf() call. */xfs_buf_t *xfs_trans_get_buf(xfs_trans_t	*tp,		  xfs_buftarg_t	*target_dev,		  xfs_daddr_t	blkno,		  int		len,		  uint		flags){	xfs_buf_t		*bp;	xfs_buf_log_item_t	*bip;	if (flags == 0)		flags = XFS_BUF_LOCK | XFS_BUF_MAPPED;	/*	 * Default to a normal get_buf() call if the tp is NULL.	 */	if (tp == NULL) {		bp = xfs_buf_get_flags(target_dev, blkno, len,							flags | BUF_BUSY);		return(bp);	}	/*	 * If we find the buffer in the cache with this transaction	 * pointer in its b_fsprivate2 field, then we know we already	 * have it locked.  In this case we just increment the lock	 * recursion count and return the buffer to the caller.	 */	if (tp->t_items.lic_next == NULL) {		bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len);	} else {		bp  = xfs_trans_buf_item_match_all(tp, target_dev, blkno, len);	}	if (bp != NULL) {		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);		if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) {			xfs_buftrace("TRANS GET RECUR SHUT", bp);			XFS_BUF_SUPER_STALE(bp);		}		/*		 * If the buffer is stale then it was binval'ed		 * since last read.  This doesn't matter since the		 * caller isn't allowed to use the data anyway.		 */		else if (XFS_BUF_ISSTALE(bp)) {			xfs_buftrace("TRANS GET RECUR STALE", bp);			ASSERT(!XFS_BUF_ISDELAYWRITE(bp));		}		ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);		ASSERT(bip != NULL);		ASSERT(atomic_read(&bip->bli_refcount) > 0);		bip->bli_recur++;		xfs_buftrace("TRANS GET RECUR", bp);		xfs_buf_item_trace("GET RECUR", bip);		return (bp);	}	/*	 * We always specify the BUF_BUSY flag within a transaction so	 * that get_buf does not try to push out a delayed write buffer	 * which might cause another transaction to take place (if the	 * buffer was delayed alloc).  Such recursive transactions can	 * easily deadlock with our current transaction as well as cause	 * us to run out of stack space.	 */	bp = xfs_buf_get_flags(target_dev, blkno, len, flags | BUF_BUSY);	if (bp == NULL) {		return NULL;	}	ASSERT(!XFS_BUF_GETERROR(bp));	/*	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If	 * it doesn't have one yet, then allocate one and initialize it.	 * The checks to see if one is there are in xfs_buf_item_init().	 */	xfs_buf_item_init(bp, tp->t_mountp);	/*	 * Set the recursion count for the buffer within this transaction	 * to 0.	 */	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));	bip->bli_recur = 0;	/*	 * Take a reference for this transaction on the buf item.	 */	atomic_inc(&bip->bli_refcount);	/*	 * Get a log_item_desc to point at the new item.	 */	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);	/*	 * Initialize b_fsprivate2 so we can find it with incore_match()	 * above.	 */	XFS_BUF_SET_FSPRIVATE2(bp, tp);	xfs_buftrace("TRANS GET", bp);	xfs_buf_item_trace("GET", bip);	return (bp);}/* * Get and lock the superblock buffer of this file system for the * given transaction. * * We don't need to use incore_match() here, because the superblock * buffer is a private buffer which we keep a pointer to in the * mount structure. */xfs_buf_t *xfs_trans_getsb(xfs_trans_t	*tp,		struct xfs_mount *mp,		int		flags){	xfs_buf_t		*bp;	xfs_buf_log_item_t	*bip;	/*	 * Default to just trying to lock the superblock buffer	 * if tp is NULL.	 */	if (tp == NULL) {		return (xfs_getsb(mp, flags));	}	/*	 * If the superblock buffer already has this transaction	 * pointer in its b_fsprivate2 field, then we know we already	 * have it locked.  In this case we just increment the lock	 * recursion count and return the buffer to the caller.	 */	bp = mp->m_sb_bp;	if (XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp) {		bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);		ASSERT(bip != NULL);		ASSERT(atomic_read(&bip->bli_refcount) > 0);		bip->bli_recur++;		xfs_buf_item_trace("GETSB RECUR", bip);		return (bp);	}	bp = xfs_getsb(mp, flags);	if (bp == NULL) {		return NULL;	}	/*	 * The xfs_buf_log_item pointer is stored in b_fsprivate.  If	 * it doesn't have one yet, then allocate one and initialize it.	 * The checks to see if one is there are in xfs_buf_item_init().	 */	xfs_buf_item_init(bp, mp);	/*	 * Set the recursion count for the buffer within this transaction	 * to 0.	 */	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));	ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));	bip->bli_recur = 0;	/*	 * Take a reference for this transaction on the buf item.	 */	atomic_inc(&bip->bli_refcount);	/*	 * Get a log_item_desc to point at the new item.	 */	(void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);	/*	 * Initialize b_fsprivate2 so we can find it with incore_match()	 * above.	 */	XFS_BUF_SET_FSPRIVATE2(bp, tp);	xfs_buf_item_trace("GETSB", bip);	return (bp);}#ifdef DEBUGxfs_buftarg_t *xfs_error_target;int	xfs_do_error;int	xfs_req_num;int	xfs_error_mod = 33;#endif/* * Get and lock the buffer for the caller if it is not already * locked within the given transaction.  If it has not yet been * read in, read it from disk. If it is already locked * within the transaction and already read in, just increment its * lock recursion count and return a pointer to it. * * Use the fast path function xfs_trans_buf_item_match() or the buffer * cache routine incore_match() to find the buffer * if it is already owned by this transaction. * * If we don't already own the buffer, use read_buf() to get it. * If it doesn't yet have an associated xfs_buf_log_item structure, * then allocate one and add the item to this transaction. * * If the transaction pointer is NULL, make this just a normal * read_buf() call. */intxfs_trans_read_buf(	xfs_mount_t	*mp,	xfs_trans_t	*tp,	xfs_buftarg_t	*target,	xfs_daddr_t	blkno,	int		len,	uint		flags,	xfs_buf_t	**bpp){	xfs_buf_t		*bp;	xfs_buf_log_item_t	*bip;	int			error;	if (flags == 0)		flags = XFS_BUF_LOCK | XFS_BUF_MAPPED;	/*	 * Default to a normal get_buf() call if the tp is NULL.	 */	if (tp == NULL) {		bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY);		if (!bp)			return XFS_ERROR(ENOMEM);		if ((bp != NULL) && (XFS_BUF_GETERROR(bp) != 0)) {			xfs_ioerror_alert("xfs_trans_read_buf", mp,					  bp, blkno);			error = XFS_BUF_GETERROR(bp);			xfs_buf_relse(bp);			return error;		}#ifdef DEBUG		if (xfs_do_error && (bp != NULL)) {			if (xfs_error_target == target) {				if (((xfs_req_num++) % xfs_error_mod) == 0) {					xfs_buf_relse(bp);					printk("Returning error!\n");					return XFS_ERROR(EIO);				}			}		}#endif		if (XFS_FORCED_SHUTDOWN(mp))			goto shutdown_abort;		*bpp = bp;		return 0;	}	/*	 * If we find the buffer in the cache with this transaction	 * pointer in its b_fsprivate2 field, then we know we already	 * have it locked.  If it is already read in we just increment	 * the lock recursion count and return the buffer to the caller.	 * If the buffer is not yet read in, then we read it in, increment	 * the lock recursion count, and return it to the caller.	 */	if (tp->t_items.lic_next == NULL) {		bp = xfs_trans_buf_item_match(tp, target, blkno, len);	} else {		bp = xfs_trans_buf_item_match_all(tp, target, blkno, len);	}	if (bp != NULL) {		ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);		ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);		ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);		ASSERT((XFS_BUF_ISERROR(bp)) == 0);		if (!(XFS_BUF_ISDONE(bp))) {			xfs_buftrace("READ_BUF_INCORE !DONE", bp);			ASSERT(!XFS_BUF_ISASYNC(bp));			XFS_BUF_READ(bp);			xfsbdstrat(tp->t_mountp, bp);			xfs_iowait(bp);			if (XFS_BUF_GETERROR(bp) != 0) {				xfs_ioerror_alert("xfs_trans_read_buf", mp,

⌨️ 快捷键说明

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