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

📄 xfs_trans_buf.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2000-2002,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_dir2.h"#include "xfs_dmapi.h"#include "xfs_mount.h"#include "xfs_bmap_btree.h"#include "xfs_alloc_btree.h"#include "xfs_ialloc_btree.h"#include "xfs_dir2_sf.h"#include "xfs_attr_sf.h"#include "xfs_dinode.h"#include "xfs_inode.h"#include "xfs_buf_item.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);					cmn_err(CE_DEBUG, "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,						  bp, blkno);				error = XFS_BUF_GETERROR(bp);				xfs_buf_relse(bp);				/*				 * We can gracefully recover from most				 * read errors. Ones we can't are those				 * that happen after the transaction's				 * already dirty.				 */				if (tp->t_flags & XFS_TRANS_DIRTY)					xfs_force_shutdown(tp->t_mountp,							SHUTDOWN_META_IO_ERROR);				return error;

⌨️ 快捷键说明

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