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 + -
显示快捷键?