11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 51da177e4SLinus Torvalds * under the terms of version 2 of the GNU General Public License as 61da177e4SLinus Torvalds * published by the Free Software Foundation. 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * This program is distributed in the hope that it would be useful, but 91da177e4SLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 101da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * Further, this software is distributed without any warranty that it is 131da177e4SLinus Torvalds * free of the rightful claim of any third person regarding infringement 141da177e4SLinus Torvalds * or the like. Any license provided herein, whether implied or 151da177e4SLinus Torvalds * otherwise, applies only to this software file. Patent licenses, if 161da177e4SLinus Torvalds * any, provided herein do not apply to combinations of this program with 171da177e4SLinus Torvalds * other software, or any other product whatsoever. 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License along 201da177e4SLinus Torvalds * with this program; if not, write the Free Software Foundation, Inc., 59 211da177e4SLinus Torvalds * Temple Place - Suite 330, Boston MA 02111-1307, USA. 221da177e4SLinus Torvalds * 231da177e4SLinus Torvalds * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 241da177e4SLinus Torvalds * Mountain View, CA 94043, or: 251da177e4SLinus Torvalds * 261da177e4SLinus Torvalds * http://www.sgi.com 271da177e4SLinus Torvalds * 281da177e4SLinus Torvalds * For further information regarding this notice, see: 291da177e4SLinus Torvalds * 301da177e4SLinus Torvalds * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 311da177e4SLinus Torvalds */ 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds #include "xfs.h" 341da177e4SLinus Torvalds #include "xfs_macros.h" 351da177e4SLinus Torvalds #include "xfs_types.h" 361da177e4SLinus Torvalds #include "xfs_inum.h" 371da177e4SLinus Torvalds #include "xfs_log.h" 381da177e4SLinus Torvalds #include "xfs_trans.h" 391da177e4SLinus Torvalds #include "xfs_buf_item.h" 401da177e4SLinus Torvalds #include "xfs_sb.h" 411da177e4SLinus Torvalds #include "xfs_ag.h" 421da177e4SLinus Torvalds #include "xfs_dir.h" 431da177e4SLinus Torvalds #include "xfs_dmapi.h" 441da177e4SLinus Torvalds #include "xfs_mount.h" 451da177e4SLinus Torvalds #include "xfs_trans_priv.h" 461da177e4SLinus Torvalds #include "xfs_error.h" 471da177e4SLinus Torvalds #include "xfs_rw.h" 481da177e4SLinus Torvalds 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds STATIC xfs_buf_t *xfs_trans_buf_item_match(xfs_trans_t *, xfs_buftarg_t *, 511da177e4SLinus Torvalds xfs_daddr_t, int); 521da177e4SLinus Torvalds STATIC xfs_buf_t *xfs_trans_buf_item_match_all(xfs_trans_t *, xfs_buftarg_t *, 531da177e4SLinus Torvalds xfs_daddr_t, int); 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds /* 571da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 581da177e4SLinus Torvalds * locked within the given transaction. If it is already locked 591da177e4SLinus Torvalds * within the transaction, just increment its lock recursion count 601da177e4SLinus Torvalds * and return a pointer to it. 611da177e4SLinus Torvalds * 621da177e4SLinus Torvalds * Use the fast path function xfs_trans_buf_item_match() or the buffer 631da177e4SLinus Torvalds * cache routine incore_match() to find the buffer 641da177e4SLinus Torvalds * if it is already owned by this transaction. 651da177e4SLinus Torvalds * 661da177e4SLinus Torvalds * If we don't already own the buffer, use get_buf() to get it. 671da177e4SLinus Torvalds * If it doesn't yet have an associated xfs_buf_log_item structure, 681da177e4SLinus Torvalds * then allocate one and add the item to this transaction. 691da177e4SLinus Torvalds * 701da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 711da177e4SLinus Torvalds * get_buf() call. 721da177e4SLinus Torvalds */ 731da177e4SLinus Torvalds xfs_buf_t * 741da177e4SLinus Torvalds xfs_trans_get_buf(xfs_trans_t *tp, 751da177e4SLinus Torvalds xfs_buftarg_t *target_dev, 761da177e4SLinus Torvalds xfs_daddr_t blkno, 771da177e4SLinus Torvalds int len, 781da177e4SLinus Torvalds uint flags) 791da177e4SLinus Torvalds { 801da177e4SLinus Torvalds xfs_buf_t *bp; 811da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds if (flags == 0) 841da177e4SLinus Torvalds flags = XFS_BUF_LOCK | XFS_BUF_MAPPED; 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds /* 871da177e4SLinus Torvalds * Default to a normal get_buf() call if the tp is NULL. 881da177e4SLinus Torvalds */ 891da177e4SLinus Torvalds if (tp == NULL) { 901da177e4SLinus Torvalds bp = xfs_buf_get_flags(target_dev, blkno, len, 911da177e4SLinus Torvalds flags | BUF_BUSY); 921da177e4SLinus Torvalds return(bp); 931da177e4SLinus Torvalds } 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds /* 961da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 971da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 981da177e4SLinus Torvalds * have it locked. In this case we just increment the lock 991da177e4SLinus Torvalds * recursion count and return the buffer to the caller. 1001da177e4SLinus Torvalds */ 1011da177e4SLinus Torvalds if (tp->t_items.lic_next == NULL) { 1021da177e4SLinus Torvalds bp = xfs_trans_buf_item_match(tp, target_dev, blkno, len); 1031da177e4SLinus Torvalds } else { 1041da177e4SLinus Torvalds bp = xfs_trans_buf_item_match_all(tp, target_dev, blkno, len); 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds if (bp != NULL) { 1071da177e4SLinus Torvalds ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); 1081da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) { 1091da177e4SLinus Torvalds xfs_buftrace("TRANS GET RECUR SHUT", bp); 1101da177e4SLinus Torvalds XFS_BUF_SUPER_STALE(bp); 1111da177e4SLinus Torvalds } 1121da177e4SLinus Torvalds /* 1131da177e4SLinus Torvalds * If the buffer is stale then it was binval'ed 1141da177e4SLinus Torvalds * since last read. This doesn't matter since the 1151da177e4SLinus Torvalds * caller isn't allowed to use the data anyway. 1161da177e4SLinus Torvalds */ 1171da177e4SLinus Torvalds else if (XFS_BUF_ISSTALE(bp)) { 1181da177e4SLinus Torvalds xfs_buftrace("TRANS GET RECUR STALE", bp); 1191da177e4SLinus Torvalds ASSERT(!XFS_BUF_ISDELAYWRITE(bp)); 1201da177e4SLinus Torvalds } 1211da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 1221da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 1231da177e4SLinus Torvalds ASSERT(bip != NULL); 1241da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 1251da177e4SLinus Torvalds bip->bli_recur++; 1261da177e4SLinus Torvalds xfs_buftrace("TRANS GET RECUR", bp); 1271da177e4SLinus Torvalds xfs_buf_item_trace("GET RECUR", bip); 1281da177e4SLinus Torvalds return (bp); 1291da177e4SLinus Torvalds } 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds /* 1321da177e4SLinus Torvalds * We always specify the BUF_BUSY flag within a transaction so 1331da177e4SLinus Torvalds * that get_buf does not try to push out a delayed write buffer 1341da177e4SLinus Torvalds * which might cause another transaction to take place (if the 1351da177e4SLinus Torvalds * buffer was delayed alloc). Such recursive transactions can 1361da177e4SLinus Torvalds * easily deadlock with our current transaction as well as cause 1371da177e4SLinus Torvalds * us to run out of stack space. 1381da177e4SLinus Torvalds */ 1391da177e4SLinus Torvalds bp = xfs_buf_get_flags(target_dev, blkno, len, flags | BUF_BUSY); 1401da177e4SLinus Torvalds if (bp == NULL) { 1411da177e4SLinus Torvalds return NULL; 1421da177e4SLinus Torvalds } 1431da177e4SLinus Torvalds 1441da177e4SLinus Torvalds ASSERT(!XFS_BUF_GETERROR(bp)); 1451da177e4SLinus Torvalds 1461da177e4SLinus Torvalds /* 1471da177e4SLinus Torvalds * The xfs_buf_log_item pointer is stored in b_fsprivate. If 1481da177e4SLinus Torvalds * it doesn't have one yet, then allocate one and initialize it. 1491da177e4SLinus Torvalds * The checks to see if one is there are in xfs_buf_item_init(). 1501da177e4SLinus Torvalds */ 1511da177e4SLinus Torvalds xfs_buf_item_init(bp, tp->t_mountp); 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds /* 1541da177e4SLinus Torvalds * Set the recursion count for the buffer within this transaction 1551da177e4SLinus Torvalds * to 0. 1561da177e4SLinus Torvalds */ 1571da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); 1581da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 1591da177e4SLinus Torvalds ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); 1601da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 1611da177e4SLinus Torvalds bip->bli_recur = 0; 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds /* 1641da177e4SLinus Torvalds * Take a reference for this transaction on the buf item. 1651da177e4SLinus Torvalds */ 1661da177e4SLinus Torvalds atomic_inc(&bip->bli_refcount); 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* 1691da177e4SLinus Torvalds * Get a log_item_desc to point at the new item. 1701da177e4SLinus Torvalds */ 1711da177e4SLinus Torvalds (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip); 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /* 1741da177e4SLinus Torvalds * Initialize b_fsprivate2 so we can find it with incore_match() 1751da177e4SLinus Torvalds * above. 1761da177e4SLinus Torvalds */ 1771da177e4SLinus Torvalds XFS_BUF_SET_FSPRIVATE2(bp, tp); 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds xfs_buftrace("TRANS GET", bp); 1801da177e4SLinus Torvalds xfs_buf_item_trace("GET", bip); 1811da177e4SLinus Torvalds return (bp); 1821da177e4SLinus Torvalds } 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds /* 1851da177e4SLinus Torvalds * Get and lock the superblock buffer of this file system for the 1861da177e4SLinus Torvalds * given transaction. 1871da177e4SLinus Torvalds * 1881da177e4SLinus Torvalds * We don't need to use incore_match() here, because the superblock 1891da177e4SLinus Torvalds * buffer is a private buffer which we keep a pointer to in the 1901da177e4SLinus Torvalds * mount structure. 1911da177e4SLinus Torvalds */ 1921da177e4SLinus Torvalds xfs_buf_t * 1931da177e4SLinus Torvalds xfs_trans_getsb(xfs_trans_t *tp, 1941da177e4SLinus Torvalds struct xfs_mount *mp, 1951da177e4SLinus Torvalds int flags) 1961da177e4SLinus Torvalds { 1971da177e4SLinus Torvalds xfs_buf_t *bp; 1981da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 1991da177e4SLinus Torvalds 2001da177e4SLinus Torvalds /* 2011da177e4SLinus Torvalds * Default to just trying to lock the superblock buffer 2021da177e4SLinus Torvalds * if tp is NULL. 2031da177e4SLinus Torvalds */ 2041da177e4SLinus Torvalds if (tp == NULL) { 2051da177e4SLinus Torvalds return (xfs_getsb(mp, flags)); 2061da177e4SLinus Torvalds } 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds /* 2091da177e4SLinus Torvalds * If the superblock buffer already has this transaction 2101da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 2111da177e4SLinus Torvalds * have it locked. In this case we just increment the lock 2121da177e4SLinus Torvalds * recursion count and return the buffer to the caller. 2131da177e4SLinus Torvalds */ 2141da177e4SLinus Torvalds bp = mp->m_sb_bp; 2151da177e4SLinus Torvalds if (XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp) { 2161da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); 2171da177e4SLinus Torvalds ASSERT(bip != NULL); 2181da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 2191da177e4SLinus Torvalds bip->bli_recur++; 2201da177e4SLinus Torvalds xfs_buf_item_trace("GETSB RECUR", bip); 2211da177e4SLinus Torvalds return (bp); 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds bp = xfs_getsb(mp, flags); 2251da177e4SLinus Torvalds if (bp == NULL) { 2261da177e4SLinus Torvalds return NULL; 2271da177e4SLinus Torvalds } 2281da177e4SLinus Torvalds 2291da177e4SLinus Torvalds /* 2301da177e4SLinus Torvalds * The xfs_buf_log_item pointer is stored in b_fsprivate. If 2311da177e4SLinus Torvalds * it doesn't have one yet, then allocate one and initialize it. 2321da177e4SLinus Torvalds * The checks to see if one is there are in xfs_buf_item_init(). 2331da177e4SLinus Torvalds */ 2341da177e4SLinus Torvalds xfs_buf_item_init(bp, mp); 2351da177e4SLinus Torvalds 2361da177e4SLinus Torvalds /* 2371da177e4SLinus Torvalds * Set the recursion count for the buffer within this transaction 2381da177e4SLinus Torvalds * to 0. 2391da177e4SLinus Torvalds */ 2401da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); 2411da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 2421da177e4SLinus Torvalds ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); 2431da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 2441da177e4SLinus Torvalds bip->bli_recur = 0; 2451da177e4SLinus Torvalds 2461da177e4SLinus Torvalds /* 2471da177e4SLinus Torvalds * Take a reference for this transaction on the buf item. 2481da177e4SLinus Torvalds */ 2491da177e4SLinus Torvalds atomic_inc(&bip->bli_refcount); 2501da177e4SLinus Torvalds 2511da177e4SLinus Torvalds /* 2521da177e4SLinus Torvalds * Get a log_item_desc to point at the new item. 2531da177e4SLinus Torvalds */ 2541da177e4SLinus Torvalds (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip); 2551da177e4SLinus Torvalds 2561da177e4SLinus Torvalds /* 2571da177e4SLinus Torvalds * Initialize b_fsprivate2 so we can find it with incore_match() 2581da177e4SLinus Torvalds * above. 2591da177e4SLinus Torvalds */ 2601da177e4SLinus Torvalds XFS_BUF_SET_FSPRIVATE2(bp, tp); 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds xfs_buf_item_trace("GETSB", bip); 2631da177e4SLinus Torvalds return (bp); 2641da177e4SLinus Torvalds } 2651da177e4SLinus Torvalds 2661da177e4SLinus Torvalds #ifdef DEBUG 2671da177e4SLinus Torvalds xfs_buftarg_t *xfs_error_target; 2681da177e4SLinus Torvalds int xfs_do_error; 2691da177e4SLinus Torvalds int xfs_req_num; 2701da177e4SLinus Torvalds int xfs_error_mod = 33; 2711da177e4SLinus Torvalds #endif 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds /* 2741da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 2751da177e4SLinus Torvalds * locked within the given transaction. If it has not yet been 2761da177e4SLinus Torvalds * read in, read it from disk. If it is already locked 2771da177e4SLinus Torvalds * within the transaction and already read in, just increment its 2781da177e4SLinus Torvalds * lock recursion count and return a pointer to it. 2791da177e4SLinus Torvalds * 2801da177e4SLinus Torvalds * Use the fast path function xfs_trans_buf_item_match() or the buffer 2811da177e4SLinus Torvalds * cache routine incore_match() to find the buffer 2821da177e4SLinus Torvalds * if it is already owned by this transaction. 2831da177e4SLinus Torvalds * 2841da177e4SLinus Torvalds * If we don't already own the buffer, use read_buf() to get it. 2851da177e4SLinus Torvalds * If it doesn't yet have an associated xfs_buf_log_item structure, 2861da177e4SLinus Torvalds * then allocate one and add the item to this transaction. 2871da177e4SLinus Torvalds * 2881da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 2891da177e4SLinus Torvalds * read_buf() call. 2901da177e4SLinus Torvalds */ 2911da177e4SLinus Torvalds int 2921da177e4SLinus Torvalds xfs_trans_read_buf( 2931da177e4SLinus Torvalds xfs_mount_t *mp, 2941da177e4SLinus Torvalds xfs_trans_t *tp, 2951da177e4SLinus Torvalds xfs_buftarg_t *target, 2961da177e4SLinus Torvalds xfs_daddr_t blkno, 2971da177e4SLinus Torvalds int len, 2981da177e4SLinus Torvalds uint flags, 2991da177e4SLinus Torvalds xfs_buf_t **bpp) 3001da177e4SLinus Torvalds { 3011da177e4SLinus Torvalds xfs_buf_t *bp; 3021da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 3031da177e4SLinus Torvalds int error; 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds if (flags == 0) 3061da177e4SLinus Torvalds flags = XFS_BUF_LOCK | XFS_BUF_MAPPED; 3071da177e4SLinus Torvalds 3081da177e4SLinus Torvalds /* 3091da177e4SLinus Torvalds * Default to a normal get_buf() call if the tp is NULL. 3101da177e4SLinus Torvalds */ 3111da177e4SLinus Torvalds if (tp == NULL) { 3121da177e4SLinus Torvalds bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY); 3131da177e4SLinus Torvalds if (!bp) 3141da177e4SLinus Torvalds return XFS_ERROR(ENOMEM); 3151da177e4SLinus Torvalds 3161da177e4SLinus Torvalds if ((bp != NULL) && (XFS_BUF_GETERROR(bp) != 0)) { 3171da177e4SLinus Torvalds xfs_ioerror_alert("xfs_trans_read_buf", mp, 3181da177e4SLinus Torvalds bp, blkno); 3191da177e4SLinus Torvalds error = XFS_BUF_GETERROR(bp); 3201da177e4SLinus Torvalds xfs_buf_relse(bp); 3211da177e4SLinus Torvalds return error; 3221da177e4SLinus Torvalds } 3231da177e4SLinus Torvalds #ifdef DEBUG 3241da177e4SLinus Torvalds if (xfs_do_error && (bp != NULL)) { 3251da177e4SLinus Torvalds if (xfs_error_target == target) { 3261da177e4SLinus Torvalds if (((xfs_req_num++) % xfs_error_mod) == 0) { 3271da177e4SLinus Torvalds xfs_buf_relse(bp); 3281da177e4SLinus Torvalds printk("Returning error!\n"); 3291da177e4SLinus Torvalds return XFS_ERROR(EIO); 3301da177e4SLinus Torvalds } 3311da177e4SLinus Torvalds } 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds #endif 3341da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) 3351da177e4SLinus Torvalds goto shutdown_abort; 3361da177e4SLinus Torvalds *bpp = bp; 3371da177e4SLinus Torvalds return 0; 3381da177e4SLinus Torvalds } 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds /* 3411da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 3421da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 3431da177e4SLinus Torvalds * have it locked. If it is already read in we just increment 3441da177e4SLinus Torvalds * the lock recursion count and return the buffer to the caller. 3451da177e4SLinus Torvalds * If the buffer is not yet read in, then we read it in, increment 3461da177e4SLinus Torvalds * the lock recursion count, and return it to the caller. 3471da177e4SLinus Torvalds */ 3481da177e4SLinus Torvalds if (tp->t_items.lic_next == NULL) { 3491da177e4SLinus Torvalds bp = xfs_trans_buf_item_match(tp, target, blkno, len); 3501da177e4SLinus Torvalds } else { 3511da177e4SLinus Torvalds bp = xfs_trans_buf_item_match_all(tp, target, blkno, len); 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds if (bp != NULL) { 3541da177e4SLinus Torvalds ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); 3551da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 3561da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 3571da177e4SLinus Torvalds ASSERT((XFS_BUF_ISERROR(bp)) == 0); 3581da177e4SLinus Torvalds if (!(XFS_BUF_ISDONE(bp))) { 3591da177e4SLinus Torvalds xfs_buftrace("READ_BUF_INCORE !DONE", bp); 3601da177e4SLinus Torvalds ASSERT(!XFS_BUF_ISASYNC(bp)); 3611da177e4SLinus Torvalds XFS_BUF_READ(bp); 3621da177e4SLinus Torvalds xfsbdstrat(tp->t_mountp, bp); 3631da177e4SLinus Torvalds xfs_iowait(bp); 3641da177e4SLinus Torvalds if (XFS_BUF_GETERROR(bp) != 0) { 3651da177e4SLinus Torvalds xfs_ioerror_alert("xfs_trans_read_buf", mp, 3661da177e4SLinus Torvalds bp, blkno); 3671da177e4SLinus Torvalds error = XFS_BUF_GETERROR(bp); 3681da177e4SLinus Torvalds xfs_buf_relse(bp); 3691da177e4SLinus Torvalds /* 3701da177e4SLinus Torvalds * We can gracefully recover from most 3711da177e4SLinus Torvalds * read errors. Ones we can't are those 3721da177e4SLinus Torvalds * that happen after the transaction's 3731da177e4SLinus Torvalds * already dirty. 3741da177e4SLinus Torvalds */ 3751da177e4SLinus Torvalds if (tp->t_flags & XFS_TRANS_DIRTY) 3761da177e4SLinus Torvalds xfs_force_shutdown(tp->t_mountp, 3771da177e4SLinus Torvalds XFS_METADATA_IO_ERROR); 3781da177e4SLinus Torvalds return error; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds } 3811da177e4SLinus Torvalds /* 3821da177e4SLinus Torvalds * We never locked this buf ourselves, so we shouldn't 3831da177e4SLinus Torvalds * brelse it either. Just get out. 3841da177e4SLinus Torvalds */ 3851da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) { 3861da177e4SLinus Torvalds xfs_buftrace("READ_BUF_INCORE XFSSHUTDN", bp); 3871da177e4SLinus Torvalds *bpp = NULL; 3881da177e4SLinus Torvalds return XFS_ERROR(EIO); 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); 3931da177e4SLinus Torvalds bip->bli_recur++; 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 3961da177e4SLinus Torvalds xfs_buf_item_trace("READ RECUR", bip); 3971da177e4SLinus Torvalds *bpp = bp; 3981da177e4SLinus Torvalds return 0; 3991da177e4SLinus Torvalds } 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds /* 4021da177e4SLinus Torvalds * We always specify the BUF_BUSY flag within a transaction so 4031da177e4SLinus Torvalds * that get_buf does not try to push out a delayed write buffer 4041da177e4SLinus Torvalds * which might cause another transaction to take place (if the 4051da177e4SLinus Torvalds * buffer was delayed alloc). Such recursive transactions can 4061da177e4SLinus Torvalds * easily deadlock with our current transaction as well as cause 4071da177e4SLinus Torvalds * us to run out of stack space. 4081da177e4SLinus Torvalds */ 4091da177e4SLinus Torvalds bp = xfs_buf_read_flags(target, blkno, len, flags | BUF_BUSY); 4101da177e4SLinus Torvalds if (bp == NULL) { 4111da177e4SLinus Torvalds *bpp = NULL; 4121da177e4SLinus Torvalds return 0; 4131da177e4SLinus Torvalds } 4141da177e4SLinus Torvalds if (XFS_BUF_GETERROR(bp) != 0) { 4151da177e4SLinus Torvalds XFS_BUF_SUPER_STALE(bp); 4161da177e4SLinus Torvalds xfs_buftrace("READ ERROR", bp); 4171da177e4SLinus Torvalds error = XFS_BUF_GETERROR(bp); 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds xfs_ioerror_alert("xfs_trans_read_buf", mp, 4201da177e4SLinus Torvalds bp, blkno); 4211da177e4SLinus Torvalds if (tp->t_flags & XFS_TRANS_DIRTY) 4221da177e4SLinus Torvalds xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR); 4231da177e4SLinus Torvalds xfs_buf_relse(bp); 4241da177e4SLinus Torvalds return error; 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds #ifdef DEBUG 4271da177e4SLinus Torvalds if (xfs_do_error && !(tp->t_flags & XFS_TRANS_DIRTY)) { 4281da177e4SLinus Torvalds if (xfs_error_target == target) { 4291da177e4SLinus Torvalds if (((xfs_req_num++) % xfs_error_mod) == 0) { 4301da177e4SLinus Torvalds xfs_force_shutdown(tp->t_mountp, 4311da177e4SLinus Torvalds XFS_METADATA_IO_ERROR); 4321da177e4SLinus Torvalds xfs_buf_relse(bp); 4331da177e4SLinus Torvalds printk("Returning error in trans!\n"); 4341da177e4SLinus Torvalds return XFS_ERROR(EIO); 4351da177e4SLinus Torvalds } 4361da177e4SLinus Torvalds } 4371da177e4SLinus Torvalds } 4381da177e4SLinus Torvalds #endif 4391da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) 4401da177e4SLinus Torvalds goto shutdown_abort; 4411da177e4SLinus Torvalds 4421da177e4SLinus Torvalds /* 4431da177e4SLinus Torvalds * The xfs_buf_log_item pointer is stored in b_fsprivate. If 4441da177e4SLinus Torvalds * it doesn't have one yet, then allocate one and initialize it. 4451da177e4SLinus Torvalds * The checks to see if one is there are in xfs_buf_item_init(). 4461da177e4SLinus Torvalds */ 4471da177e4SLinus Torvalds xfs_buf_item_init(bp, tp->t_mountp); 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds /* 4501da177e4SLinus Torvalds * Set the recursion count for the buffer within this transaction 4511da177e4SLinus Torvalds * to 0. 4521da177e4SLinus Torvalds */ 4531da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*); 4541da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 4551da177e4SLinus Torvalds ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); 4561da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 4571da177e4SLinus Torvalds bip->bli_recur = 0; 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds /* 4601da177e4SLinus Torvalds * Take a reference for this transaction on the buf item. 4611da177e4SLinus Torvalds */ 4621da177e4SLinus Torvalds atomic_inc(&bip->bli_refcount); 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds /* 4651da177e4SLinus Torvalds * Get a log_item_desc to point at the new item. 4661da177e4SLinus Torvalds */ 4671da177e4SLinus Torvalds (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip); 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds /* 4701da177e4SLinus Torvalds * Initialize b_fsprivate2 so we can find it with incore_match() 4711da177e4SLinus Torvalds * above. 4721da177e4SLinus Torvalds */ 4731da177e4SLinus Torvalds XFS_BUF_SET_FSPRIVATE2(bp, tp); 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds xfs_buftrace("TRANS READ", bp); 4761da177e4SLinus Torvalds xfs_buf_item_trace("READ", bip); 4771da177e4SLinus Torvalds *bpp = bp; 4781da177e4SLinus Torvalds return 0; 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds shutdown_abort: 4811da177e4SLinus Torvalds /* 4821da177e4SLinus Torvalds * the theory here is that buffer is good but we're 4831da177e4SLinus Torvalds * bailing out because the filesystem is being forcibly 4841da177e4SLinus Torvalds * shut down. So we should leave the b_flags alone since 4851da177e4SLinus Torvalds * the buffer's not staled and just get out. 4861da177e4SLinus Torvalds */ 4871da177e4SLinus Torvalds #if defined(DEBUG) 4881da177e4SLinus Torvalds if (XFS_BUF_ISSTALE(bp) && XFS_BUF_ISDELAYWRITE(bp)) 4891da177e4SLinus Torvalds cmn_err(CE_NOTE, "about to pop assert, bp == 0x%p", bp); 4901da177e4SLinus Torvalds #endif 4911da177e4SLinus Torvalds ASSERT((XFS_BUF_BFLAGS(bp) & (XFS_B_STALE|XFS_B_DELWRI)) != 4921da177e4SLinus Torvalds (XFS_B_STALE|XFS_B_DELWRI)); 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds xfs_buftrace("READ_BUF XFSSHUTDN", bp); 4951da177e4SLinus Torvalds xfs_buf_relse(bp); 4961da177e4SLinus Torvalds *bpp = NULL; 4971da177e4SLinus Torvalds return XFS_ERROR(EIO); 4981da177e4SLinus Torvalds } 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds /* 5021da177e4SLinus Torvalds * Release the buffer bp which was previously acquired with one of the 5031da177e4SLinus Torvalds * xfs_trans_... buffer allocation routines if the buffer has not 5041da177e4SLinus Torvalds * been modified within this transaction. If the buffer is modified 5051da177e4SLinus Torvalds * within this transaction, do decrement the recursion count but do 5061da177e4SLinus Torvalds * not release the buffer even if the count goes to 0. If the buffer is not 5071da177e4SLinus Torvalds * modified within the transaction, decrement the recursion count and 5081da177e4SLinus Torvalds * release the buffer if the recursion count goes to 0. 5091da177e4SLinus Torvalds * 5101da177e4SLinus Torvalds * If the buffer is to be released and it was not modified before 5111da177e4SLinus Torvalds * this transaction began, then free the buf_log_item associated with it. 5121da177e4SLinus Torvalds * 5131da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 5141da177e4SLinus Torvalds * brelse() call. 5151da177e4SLinus Torvalds */ 5161da177e4SLinus Torvalds void 5171da177e4SLinus Torvalds xfs_trans_brelse(xfs_trans_t *tp, 5181da177e4SLinus Torvalds xfs_buf_t *bp) 5191da177e4SLinus Torvalds { 5201da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 5211da177e4SLinus Torvalds xfs_log_item_t *lip; 5221da177e4SLinus Torvalds xfs_log_item_desc_t *lidp; 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds /* 5251da177e4SLinus Torvalds * Default to a normal brelse() call if the tp is NULL. 5261da177e4SLinus Torvalds */ 5271da177e4SLinus Torvalds if (tp == NULL) { 5281da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); 5291da177e4SLinus Torvalds /* 5301da177e4SLinus Torvalds * If there's a buf log item attached to the buffer, 5311da177e4SLinus Torvalds * then let the AIL know that the buffer is being 5321da177e4SLinus Torvalds * unlocked. 5331da177e4SLinus Torvalds */ 5341da177e4SLinus Torvalds if (XFS_BUF_FSPRIVATE(bp, void *) != NULL) { 5351da177e4SLinus Torvalds lip = XFS_BUF_FSPRIVATE(bp, xfs_log_item_t *); 5361da177e4SLinus Torvalds if (lip->li_type == XFS_LI_BUF) { 5371da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*); 5381da177e4SLinus Torvalds xfs_trans_unlocked_item( 5391da177e4SLinus Torvalds bip->bli_item.li_mountp, 5401da177e4SLinus Torvalds lip); 5411da177e4SLinus Torvalds } 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds xfs_buf_relse(bp); 5441da177e4SLinus Torvalds return; 5451da177e4SLinus Torvalds } 5461da177e4SLinus Torvalds 5471da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 5481da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 5491da177e4SLinus Torvalds ASSERT(bip->bli_item.li_type == XFS_LI_BUF); 5501da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 5511da177e4SLinus Torvalds ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); 5521da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 5531da177e4SLinus Torvalds 5541da177e4SLinus Torvalds /* 5551da177e4SLinus Torvalds * Find the item descriptor pointing to this buffer's 5561da177e4SLinus Torvalds * log item. It must be there. 5571da177e4SLinus Torvalds */ 5581da177e4SLinus Torvalds lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); 5591da177e4SLinus Torvalds ASSERT(lidp != NULL); 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds /* 5621da177e4SLinus Torvalds * If the release is just for a recursive lock, 5631da177e4SLinus Torvalds * then decrement the count and return. 5641da177e4SLinus Torvalds */ 5651da177e4SLinus Torvalds if (bip->bli_recur > 0) { 5661da177e4SLinus Torvalds bip->bli_recur--; 5671da177e4SLinus Torvalds xfs_buf_item_trace("RELSE RECUR", bip); 5681da177e4SLinus Torvalds return; 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds /* 5721da177e4SLinus Torvalds * If the buffer is dirty within this transaction, we can't 5731da177e4SLinus Torvalds * release it until we commit. 5741da177e4SLinus Torvalds */ 5751da177e4SLinus Torvalds if (lidp->lid_flags & XFS_LID_DIRTY) { 5761da177e4SLinus Torvalds xfs_buf_item_trace("RELSE DIRTY", bip); 5771da177e4SLinus Torvalds return; 5781da177e4SLinus Torvalds } 5791da177e4SLinus Torvalds 5801da177e4SLinus Torvalds /* 5811da177e4SLinus Torvalds * If the buffer has been invalidated, then we can't release 5821da177e4SLinus Torvalds * it until the transaction commits to disk unless it is re-dirtied 5831da177e4SLinus Torvalds * as part of this transaction. This prevents us from pulling 5841da177e4SLinus Torvalds * the item from the AIL before we should. 5851da177e4SLinus Torvalds */ 5861da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 5871da177e4SLinus Torvalds xfs_buf_item_trace("RELSE STALE", bip); 5881da177e4SLinus Torvalds return; 5891da177e4SLinus Torvalds } 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 5921da177e4SLinus Torvalds xfs_buf_item_trace("RELSE", bip); 5931da177e4SLinus Torvalds 5941da177e4SLinus Torvalds /* 5951da177e4SLinus Torvalds * Free up the log item descriptor tracking the released item. 5961da177e4SLinus Torvalds */ 5971da177e4SLinus Torvalds xfs_trans_free_item(tp, lidp); 5981da177e4SLinus Torvalds 5991da177e4SLinus Torvalds /* 6001da177e4SLinus Torvalds * Clear the hold flag in the buf log item if it is set. 6011da177e4SLinus Torvalds * We wouldn't want the next user of the buffer to 6021da177e4SLinus Torvalds * get confused. 6031da177e4SLinus Torvalds */ 6041da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_HOLD) { 6051da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_HOLD; 6061da177e4SLinus Torvalds } 6071da177e4SLinus Torvalds 6081da177e4SLinus Torvalds /* 6091da177e4SLinus Torvalds * Drop our reference to the buf log item. 6101da177e4SLinus Torvalds */ 6111da177e4SLinus Torvalds atomic_dec(&bip->bli_refcount); 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds /* 6141da177e4SLinus Torvalds * If the buf item is not tracking data in the log, then 6151da177e4SLinus Torvalds * we must free it before releasing the buffer back to the 6161da177e4SLinus Torvalds * free pool. Before releasing the buffer to the free pool, 6171da177e4SLinus Torvalds * clear the transaction pointer in b_fsprivate2 to dissolve 6181da177e4SLinus Torvalds * its relation to this transaction. 6191da177e4SLinus Torvalds */ 6201da177e4SLinus Torvalds if (!xfs_buf_item_dirty(bip)) { 6211da177e4SLinus Torvalds /*** 6221da177e4SLinus Torvalds ASSERT(bp->b_pincount == 0); 6231da177e4SLinus Torvalds ***/ 6241da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) == 0); 6251da177e4SLinus Torvalds ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL)); 6261da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF)); 6271da177e4SLinus Torvalds xfs_buf_item_relse(bp); 6281da177e4SLinus Torvalds bip = NULL; 6291da177e4SLinus Torvalds } 6301da177e4SLinus Torvalds XFS_BUF_SET_FSPRIVATE2(bp, NULL); 6311da177e4SLinus Torvalds 6321da177e4SLinus Torvalds /* 6331da177e4SLinus Torvalds * If we've still got a buf log item on the buffer, then 6341da177e4SLinus Torvalds * tell the AIL that the buffer is being unlocked. 6351da177e4SLinus Torvalds */ 6361da177e4SLinus Torvalds if (bip != NULL) { 6371da177e4SLinus Torvalds xfs_trans_unlocked_item(bip->bli_item.li_mountp, 6381da177e4SLinus Torvalds (xfs_log_item_t*)bip); 6391da177e4SLinus Torvalds } 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds xfs_buf_relse(bp); 6421da177e4SLinus Torvalds return; 6431da177e4SLinus Torvalds } 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds /* 6461da177e4SLinus Torvalds * Add the locked buffer to the transaction. 6471da177e4SLinus Torvalds * The buffer must be locked, and it cannot be associated with any 6481da177e4SLinus Torvalds * transaction. 6491da177e4SLinus Torvalds * 6501da177e4SLinus Torvalds * If the buffer does not yet have a buf log item associated with it, 6511da177e4SLinus Torvalds * then allocate one for it. Then add the buf item to the transaction. 6521da177e4SLinus Torvalds */ 6531da177e4SLinus Torvalds void 6541da177e4SLinus Torvalds xfs_trans_bjoin(xfs_trans_t *tp, 6551da177e4SLinus Torvalds xfs_buf_t *bp) 6561da177e4SLinus Torvalds { 6571da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 6601da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL); 6611da177e4SLinus Torvalds 6621da177e4SLinus Torvalds /* 6631da177e4SLinus Torvalds * The xfs_buf_log_item pointer is stored in b_fsprivate. If 6641da177e4SLinus Torvalds * it doesn't have one yet, then allocate one and initialize it. 6651da177e4SLinus Torvalds * The checks to see if one is there are in xfs_buf_item_init(). 6661da177e4SLinus Torvalds */ 6671da177e4SLinus Torvalds xfs_buf_item_init(bp, tp->t_mountp); 6681da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 6691da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 6701da177e4SLinus Torvalds ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); 6711da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds /* 6741da177e4SLinus Torvalds * Take a reference for this transaction on the buf item. 6751da177e4SLinus Torvalds */ 6761da177e4SLinus Torvalds atomic_inc(&bip->bli_refcount); 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds /* 6791da177e4SLinus Torvalds * Get a log_item_desc to point at the new item. 6801da177e4SLinus Torvalds */ 6811da177e4SLinus Torvalds (void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip); 6821da177e4SLinus Torvalds 6831da177e4SLinus Torvalds /* 6841da177e4SLinus Torvalds * Initialize b_fsprivate2 so we can find it with incore_match() 6851da177e4SLinus Torvalds * in xfs_trans_get_buf() and friends above. 6861da177e4SLinus Torvalds */ 6871da177e4SLinus Torvalds XFS_BUF_SET_FSPRIVATE2(bp, tp); 6881da177e4SLinus Torvalds 6891da177e4SLinus Torvalds xfs_buf_item_trace("BJOIN", bip); 6901da177e4SLinus Torvalds } 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds /* 6931da177e4SLinus Torvalds * Mark the buffer as not needing to be unlocked when the buf item's 6941da177e4SLinus Torvalds * IOP_UNLOCK() routine is called. The buffer must already be locked 6951da177e4SLinus Torvalds * and associated with the given transaction. 6961da177e4SLinus Torvalds */ 6971da177e4SLinus Torvalds /* ARGSUSED */ 6981da177e4SLinus Torvalds void 6991da177e4SLinus Torvalds xfs_trans_bhold(xfs_trans_t *tp, 7001da177e4SLinus Torvalds xfs_buf_t *bp) 7011da177e4SLinus Torvalds { 7021da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 7031da177e4SLinus Torvalds 7041da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 7051da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 7061da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 7091da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 7101da177e4SLinus Torvalds ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); 7111da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 7121da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_HOLD; 7131da177e4SLinus Torvalds xfs_buf_item_trace("BHOLD", bip); 7141da177e4SLinus Torvalds } 7151da177e4SLinus Torvalds 7161da177e4SLinus Torvalds /* 717*efa092f3STim Shimmin * Cancel the previous buffer hold request made on this buffer 718*efa092f3STim Shimmin * for this transaction. 719*efa092f3STim Shimmin */ 720*efa092f3STim Shimmin void 721*efa092f3STim Shimmin xfs_trans_bhold_release(xfs_trans_t *tp, 722*efa092f3STim Shimmin xfs_buf_t *bp) 723*efa092f3STim Shimmin { 724*efa092f3STim Shimmin xfs_buf_log_item_t *bip; 725*efa092f3STim Shimmin 726*efa092f3STim Shimmin ASSERT(XFS_BUF_ISBUSY(bp)); 727*efa092f3STim Shimmin ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 728*efa092f3STim Shimmin ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 729*efa092f3STim Shimmin 730*efa092f3STim Shimmin bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 731*efa092f3STim Shimmin ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 732*efa092f3STim Shimmin ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL)); 733*efa092f3STim Shimmin ASSERT(atomic_read(&bip->bli_refcount) > 0); 734*efa092f3STim Shimmin ASSERT(bip->bli_flags & XFS_BLI_HOLD); 735*efa092f3STim Shimmin bip->bli_flags &= ~XFS_BLI_HOLD; 736*efa092f3STim Shimmin xfs_buf_item_trace("BHOLD RELEASE", bip); 737*efa092f3STim Shimmin } 738*efa092f3STim Shimmin 739*efa092f3STim Shimmin /* 7401da177e4SLinus Torvalds * This is called to mark bytes first through last inclusive of the given 7411da177e4SLinus Torvalds * buffer as needing to be logged when the transaction is committed. 7421da177e4SLinus Torvalds * The buffer must already be associated with the given transaction. 7431da177e4SLinus Torvalds * 7441da177e4SLinus Torvalds * First and last are numbers relative to the beginning of this buffer, 7451da177e4SLinus Torvalds * so the first byte in the buffer is numbered 0 regardless of the 7461da177e4SLinus Torvalds * value of b_blkno. 7471da177e4SLinus Torvalds */ 7481da177e4SLinus Torvalds void 7491da177e4SLinus Torvalds xfs_trans_log_buf(xfs_trans_t *tp, 7501da177e4SLinus Torvalds xfs_buf_t *bp, 7511da177e4SLinus Torvalds uint first, 7521da177e4SLinus Torvalds uint last) 7531da177e4SLinus Torvalds { 7541da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 7551da177e4SLinus Torvalds xfs_log_item_desc_t *lidp; 7561da177e4SLinus Torvalds 7571da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 7581da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 7591da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 7601da177e4SLinus Torvalds ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp))); 7611da177e4SLinus Torvalds ASSERT((XFS_BUF_IODONE_FUNC(bp) == NULL) || 7621da177e4SLinus Torvalds (XFS_BUF_IODONE_FUNC(bp) == xfs_buf_iodone_callbacks)); 7631da177e4SLinus Torvalds 7641da177e4SLinus Torvalds /* 7651da177e4SLinus Torvalds * Mark the buffer as needing to be written out eventually, 7661da177e4SLinus Torvalds * and set its iodone function to remove the buffer's buf log 7671da177e4SLinus Torvalds * item from the AIL and free it when the buffer is flushed 7681da177e4SLinus Torvalds * to disk. See xfs_buf_attach_iodone() for more details 7691da177e4SLinus Torvalds * on li_cb and xfs_buf_iodone_callbacks(). 7701da177e4SLinus Torvalds * If we end up aborting this transaction, we trap this buffer 7711da177e4SLinus Torvalds * inside the b_bdstrat callback so that this won't get written to 7721da177e4SLinus Torvalds * disk. 7731da177e4SLinus Torvalds */ 7741da177e4SLinus Torvalds XFS_BUF_DELAYWRITE(bp); 7751da177e4SLinus Torvalds XFS_BUF_DONE(bp); 7761da177e4SLinus Torvalds 7771da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 7781da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 7791da177e4SLinus Torvalds XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); 7801da177e4SLinus Torvalds bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*))xfs_buf_iodone; 7811da177e4SLinus Torvalds 7821da177e4SLinus Torvalds /* 7831da177e4SLinus Torvalds * If we invalidated the buffer within this transaction, then 7841da177e4SLinus Torvalds * cancel the invalidation now that we're dirtying the buffer 7851da177e4SLinus Torvalds * again. There are no races with the code in xfs_buf_item_unpin(), 7861da177e4SLinus Torvalds * because we have a reference to the buffer this entire time. 7871da177e4SLinus Torvalds */ 7881da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 7891da177e4SLinus Torvalds xfs_buf_item_trace("BLOG UNSTALE", bip); 7901da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_STALE; 7911da177e4SLinus Torvalds ASSERT(XFS_BUF_ISSTALE(bp)); 7921da177e4SLinus Torvalds XFS_BUF_UNSTALE(bp); 7931da177e4SLinus Torvalds bip->bli_format.blf_flags &= ~XFS_BLI_CANCEL; 7941da177e4SLinus Torvalds } 7951da177e4SLinus Torvalds 7961da177e4SLinus Torvalds lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); 7971da177e4SLinus Torvalds ASSERT(lidp != NULL); 7981da177e4SLinus Torvalds 7991da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 8001da177e4SLinus Torvalds lidp->lid_flags |= XFS_LID_DIRTY; 8011da177e4SLinus Torvalds lidp->lid_flags &= ~XFS_LID_BUF_STALE; 8021da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_LOGGED; 8031da177e4SLinus Torvalds xfs_buf_item_log(bip, first, last); 8041da177e4SLinus Torvalds xfs_buf_item_trace("BLOG", bip); 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds /* 8091da177e4SLinus Torvalds * This called to invalidate a buffer that is being used within 8101da177e4SLinus Torvalds * a transaction. Typically this is because the blocks in the 8111da177e4SLinus Torvalds * buffer are being freed, so we need to prevent it from being 8121da177e4SLinus Torvalds * written out when we're done. Allowing it to be written again 8131da177e4SLinus Torvalds * might overwrite data in the free blocks if they are reallocated 8141da177e4SLinus Torvalds * to a file. 8151da177e4SLinus Torvalds * 8161da177e4SLinus Torvalds * We prevent the buffer from being written out by clearing the 8171da177e4SLinus Torvalds * B_DELWRI flag. We can't always 8181da177e4SLinus Torvalds * get rid of the buf log item at this point, though, because 8191da177e4SLinus Torvalds * the buffer may still be pinned by another transaction. If that 8201da177e4SLinus Torvalds * is the case, then we'll wait until the buffer is committed to 8211da177e4SLinus Torvalds * disk for the last time (we can tell by the ref count) and 8221da177e4SLinus Torvalds * free it in xfs_buf_item_unpin(). Until it is cleaned up we 8231da177e4SLinus Torvalds * will keep the buffer locked so that the buffer and buf log item 8241da177e4SLinus Torvalds * are not reused. 8251da177e4SLinus Torvalds */ 8261da177e4SLinus Torvalds void 8271da177e4SLinus Torvalds xfs_trans_binval( 8281da177e4SLinus Torvalds xfs_trans_t *tp, 8291da177e4SLinus Torvalds xfs_buf_t *bp) 8301da177e4SLinus Torvalds { 8311da177e4SLinus Torvalds xfs_log_item_desc_t *lidp; 8321da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 8331da177e4SLinus Torvalds 8341da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 8351da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 8361da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 8371da177e4SLinus Torvalds 8381da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 8391da177e4SLinus Torvalds lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); 8401da177e4SLinus Torvalds ASSERT(lidp != NULL); 8411da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 8421da177e4SLinus Torvalds 8431da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 8441da177e4SLinus Torvalds /* 8451da177e4SLinus Torvalds * If the buffer is already invalidated, then 8461da177e4SLinus Torvalds * just return. 8471da177e4SLinus Torvalds */ 8481da177e4SLinus Torvalds ASSERT(!(XFS_BUF_ISDELAYWRITE(bp))); 8491da177e4SLinus Torvalds ASSERT(XFS_BUF_ISSTALE(bp)); 8501da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); 8511da177e4SLinus Torvalds ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_INODE_BUF)); 8521da177e4SLinus Torvalds ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL); 8531da177e4SLinus Torvalds ASSERT(lidp->lid_flags & XFS_LID_DIRTY); 8541da177e4SLinus Torvalds ASSERT(tp->t_flags & XFS_TRANS_DIRTY); 8551da177e4SLinus Torvalds xfs_buftrace("XFS_BINVAL RECUR", bp); 8561da177e4SLinus Torvalds xfs_buf_item_trace("BINVAL RECUR", bip); 8571da177e4SLinus Torvalds return; 8581da177e4SLinus Torvalds } 8591da177e4SLinus Torvalds 8601da177e4SLinus Torvalds /* 8611da177e4SLinus Torvalds * Clear the dirty bit in the buffer and set the STALE flag 8621da177e4SLinus Torvalds * in the buf log item. The STALE flag will be used in 8631da177e4SLinus Torvalds * xfs_buf_item_unpin() to determine if it should clean up 8641da177e4SLinus Torvalds * when the last reference to the buf item is given up. 8651da177e4SLinus Torvalds * We set the XFS_BLI_CANCEL flag in the buf log format structure 8661da177e4SLinus Torvalds * and log the buf item. This will be used at recovery time 8671da177e4SLinus Torvalds * to determine that copies of the buffer in the log before 8681da177e4SLinus Torvalds * this should not be replayed. 8691da177e4SLinus Torvalds * We mark the item descriptor and the transaction dirty so 8701da177e4SLinus Torvalds * that we'll hold the buffer until after the commit. 8711da177e4SLinus Torvalds * 8721da177e4SLinus Torvalds * Since we're invalidating the buffer, we also clear the state 8731da177e4SLinus Torvalds * about which parts of the buffer have been logged. We also 8741da177e4SLinus Torvalds * clear the flag indicating that this is an inode buffer since 8751da177e4SLinus Torvalds * the data in the buffer will no longer be valid. 8761da177e4SLinus Torvalds * 8771da177e4SLinus Torvalds * We set the stale bit in the buffer as well since we're getting 8781da177e4SLinus Torvalds * rid of it. 8791da177e4SLinus Torvalds */ 8801da177e4SLinus Torvalds XFS_BUF_UNDELAYWRITE(bp); 8811da177e4SLinus Torvalds XFS_BUF_STALE(bp); 8821da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE; 8831da177e4SLinus Torvalds bip->bli_flags &= ~(XFS_BLI_LOGGED | XFS_BLI_DIRTY); 8841da177e4SLinus Torvalds bip->bli_format.blf_flags &= ~XFS_BLI_INODE_BUF; 8851da177e4SLinus Torvalds bip->bli_format.blf_flags |= XFS_BLI_CANCEL; 8861da177e4SLinus Torvalds memset((char *)(bip->bli_format.blf_data_map), 0, 8871da177e4SLinus Torvalds (bip->bli_format.blf_map_size * sizeof(uint))); 8881da177e4SLinus Torvalds lidp->lid_flags |= XFS_LID_DIRTY|XFS_LID_BUF_STALE; 8891da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 8901da177e4SLinus Torvalds xfs_buftrace("XFS_BINVAL", bp); 8911da177e4SLinus Torvalds xfs_buf_item_trace("BINVAL", bip); 8921da177e4SLinus Torvalds } 8931da177e4SLinus Torvalds 8941da177e4SLinus Torvalds /* 8951da177e4SLinus Torvalds * This call is used to indicate that the buffer contains on-disk 8961da177e4SLinus Torvalds * inodes which must be handled specially during recovery. They 8971da177e4SLinus Torvalds * require special handling because only the di_next_unlinked from 8981da177e4SLinus Torvalds * the inodes in the buffer should be recovered. The rest of the 8991da177e4SLinus Torvalds * data in the buffer is logged via the inodes themselves. 9001da177e4SLinus Torvalds * 9011da177e4SLinus Torvalds * All we do is set the XFS_BLI_INODE_BUF flag in the buffer's log 9021da177e4SLinus Torvalds * format structure so that we'll know what to do at recovery time. 9031da177e4SLinus Torvalds */ 9041da177e4SLinus Torvalds /* ARGSUSED */ 9051da177e4SLinus Torvalds void 9061da177e4SLinus Torvalds xfs_trans_inode_buf( 9071da177e4SLinus Torvalds xfs_trans_t *tp, 9081da177e4SLinus Torvalds xfs_buf_t *bp) 9091da177e4SLinus Torvalds { 9101da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 9111da177e4SLinus Torvalds 9121da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 9131da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 9141da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 9151da177e4SLinus Torvalds 9161da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 9171da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 9181da177e4SLinus Torvalds 9191da177e4SLinus Torvalds bip->bli_format.blf_flags |= XFS_BLI_INODE_BUF; 9201da177e4SLinus Torvalds } 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds /* 9231da177e4SLinus Torvalds * This call is used to indicate that the buffer is going to 9241da177e4SLinus Torvalds * be staled and was an inode buffer. This means it gets 9251da177e4SLinus Torvalds * special processing during unpin - where any inodes 9261da177e4SLinus Torvalds * associated with the buffer should be removed from ail. 9271da177e4SLinus Torvalds * There is also special processing during recovery, 9281da177e4SLinus Torvalds * any replay of the inodes in the buffer needs to be 9291da177e4SLinus Torvalds * prevented as the buffer may have been reused. 9301da177e4SLinus Torvalds */ 9311da177e4SLinus Torvalds void 9321da177e4SLinus Torvalds xfs_trans_stale_inode_buf( 9331da177e4SLinus Torvalds xfs_trans_t *tp, 9341da177e4SLinus Torvalds xfs_buf_t *bp) 9351da177e4SLinus Torvalds { 9361da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 9371da177e4SLinus Torvalds 9381da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 9391da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 9401da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 9411da177e4SLinus Torvalds 9421da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 9431da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 9441da177e4SLinus Torvalds 9451da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE_INODE; 9461da177e4SLinus Torvalds bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) 9471da177e4SLinus Torvalds xfs_buf_iodone; 9481da177e4SLinus Torvalds } 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds 9511da177e4SLinus Torvalds 9521da177e4SLinus Torvalds /* 9531da177e4SLinus Torvalds * Mark the buffer as being one which contains newly allocated 9541da177e4SLinus Torvalds * inodes. We need to make sure that even if this buffer is 9551da177e4SLinus Torvalds * relogged as an 'inode buf' we still recover all of the inode 9561da177e4SLinus Torvalds * images in the face of a crash. This works in coordination with 9571da177e4SLinus Torvalds * xfs_buf_item_committed() to ensure that the buffer remains in the 9581da177e4SLinus Torvalds * AIL at its original location even after it has been relogged. 9591da177e4SLinus Torvalds */ 9601da177e4SLinus Torvalds /* ARGSUSED */ 9611da177e4SLinus Torvalds void 9621da177e4SLinus Torvalds xfs_trans_inode_alloc_buf( 9631da177e4SLinus Torvalds xfs_trans_t *tp, 9641da177e4SLinus Torvalds xfs_buf_t *bp) 9651da177e4SLinus Torvalds { 9661da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 9671da177e4SLinus Torvalds 9681da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 9691da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 9701da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 9731da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 9741da177e4SLinus Torvalds 9751da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; 9761da177e4SLinus Torvalds } 9771da177e4SLinus Torvalds 9781da177e4SLinus Torvalds 9791da177e4SLinus Torvalds /* 9801da177e4SLinus Torvalds * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of 9811da177e4SLinus Torvalds * dquots. However, unlike in inode buffer recovery, dquot buffers get 9821da177e4SLinus Torvalds * recovered in their entirety. (Hence, no XFS_BLI_DQUOT_ALLOC_BUF flag). 9831da177e4SLinus Torvalds * The only thing that makes dquot buffers different from regular 9841da177e4SLinus Torvalds * buffers is that we must not replay dquot bufs when recovering 9851da177e4SLinus Torvalds * if a _corresponding_ quotaoff has happened. We also have to distinguish 9861da177e4SLinus Torvalds * between usr dquot bufs and grp dquot bufs, because usr and grp quotas 9871da177e4SLinus Torvalds * can be turned off independently. 9881da177e4SLinus Torvalds */ 9891da177e4SLinus Torvalds /* ARGSUSED */ 9901da177e4SLinus Torvalds void 9911da177e4SLinus Torvalds xfs_trans_dquot_buf( 9921da177e4SLinus Torvalds xfs_trans_t *tp, 9931da177e4SLinus Torvalds xfs_buf_t *bp, 9941da177e4SLinus Torvalds uint type) 9951da177e4SLinus Torvalds { 9961da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 9971da177e4SLinus Torvalds 9981da177e4SLinus Torvalds ASSERT(XFS_BUF_ISBUSY(bp)); 9991da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 10001da177e4SLinus Torvalds ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 10011da177e4SLinus Torvalds ASSERT(type == XFS_BLI_UDQUOT_BUF || 1002c8ad20ffSNathan Scott type == XFS_BLI_PDQUOT_BUF || 10031da177e4SLinus Torvalds type == XFS_BLI_GDQUOT_BUF); 10041da177e4SLinus Torvalds 10051da177e4SLinus Torvalds bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 10061da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 10071da177e4SLinus Torvalds 10081da177e4SLinus Torvalds bip->bli_format.blf_flags |= type; 10091da177e4SLinus Torvalds } 10101da177e4SLinus Torvalds 10111da177e4SLinus Torvalds /* 10121da177e4SLinus Torvalds * Check to see if a buffer matching the given parameters is already 10131da177e4SLinus Torvalds * a part of the given transaction. Only check the first, embedded 10141da177e4SLinus Torvalds * chunk, since we don't want to spend all day scanning large transactions. 10151da177e4SLinus Torvalds */ 10161da177e4SLinus Torvalds STATIC xfs_buf_t * 10171da177e4SLinus Torvalds xfs_trans_buf_item_match( 10181da177e4SLinus Torvalds xfs_trans_t *tp, 10191da177e4SLinus Torvalds xfs_buftarg_t *target, 10201da177e4SLinus Torvalds xfs_daddr_t blkno, 10211da177e4SLinus Torvalds int len) 10221da177e4SLinus Torvalds { 10231da177e4SLinus Torvalds xfs_log_item_chunk_t *licp; 10241da177e4SLinus Torvalds xfs_log_item_desc_t *lidp; 10251da177e4SLinus Torvalds xfs_buf_log_item_t *blip; 10261da177e4SLinus Torvalds xfs_buf_t *bp; 10271da177e4SLinus Torvalds int i; 10281da177e4SLinus Torvalds 10291da177e4SLinus Torvalds bp = NULL; 10301da177e4SLinus Torvalds len = BBTOB(len); 10311da177e4SLinus Torvalds licp = &tp->t_items; 10321da177e4SLinus Torvalds if (!XFS_LIC_ARE_ALL_FREE(licp)) { 10331da177e4SLinus Torvalds for (i = 0; i < licp->lic_unused; i++) { 10341da177e4SLinus Torvalds /* 10351da177e4SLinus Torvalds * Skip unoccupied slots. 10361da177e4SLinus Torvalds */ 10371da177e4SLinus Torvalds if (XFS_LIC_ISFREE(licp, i)) { 10381da177e4SLinus Torvalds continue; 10391da177e4SLinus Torvalds } 10401da177e4SLinus Torvalds 10411da177e4SLinus Torvalds lidp = XFS_LIC_SLOT(licp, i); 10421da177e4SLinus Torvalds blip = (xfs_buf_log_item_t *)lidp->lid_item; 10431da177e4SLinus Torvalds if (blip->bli_item.li_type != XFS_LI_BUF) { 10441da177e4SLinus Torvalds continue; 10451da177e4SLinus Torvalds } 10461da177e4SLinus Torvalds 10471da177e4SLinus Torvalds bp = blip->bli_buf; 10481da177e4SLinus Torvalds if ((XFS_BUF_TARGET(bp) == target) && 10491da177e4SLinus Torvalds (XFS_BUF_ADDR(bp) == blkno) && 10501da177e4SLinus Torvalds (XFS_BUF_COUNT(bp) == len)) { 10511da177e4SLinus Torvalds /* 10521da177e4SLinus Torvalds * We found it. Break out and 10531da177e4SLinus Torvalds * return the pointer to the buffer. 10541da177e4SLinus Torvalds */ 10551da177e4SLinus Torvalds break; 10561da177e4SLinus Torvalds } else { 10571da177e4SLinus Torvalds bp = NULL; 10581da177e4SLinus Torvalds } 10591da177e4SLinus Torvalds } 10601da177e4SLinus Torvalds } 10611da177e4SLinus Torvalds return bp; 10621da177e4SLinus Torvalds } 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds /* 10651da177e4SLinus Torvalds * Check to see if a buffer matching the given parameters is already 10661da177e4SLinus Torvalds * a part of the given transaction. Check all the chunks, we 10671da177e4SLinus Torvalds * want to be thorough. 10681da177e4SLinus Torvalds */ 10691da177e4SLinus Torvalds STATIC xfs_buf_t * 10701da177e4SLinus Torvalds xfs_trans_buf_item_match_all( 10711da177e4SLinus Torvalds xfs_trans_t *tp, 10721da177e4SLinus Torvalds xfs_buftarg_t *target, 10731da177e4SLinus Torvalds xfs_daddr_t blkno, 10741da177e4SLinus Torvalds int len) 10751da177e4SLinus Torvalds { 10761da177e4SLinus Torvalds xfs_log_item_chunk_t *licp; 10771da177e4SLinus Torvalds xfs_log_item_desc_t *lidp; 10781da177e4SLinus Torvalds xfs_buf_log_item_t *blip; 10791da177e4SLinus Torvalds xfs_buf_t *bp; 10801da177e4SLinus Torvalds int i; 10811da177e4SLinus Torvalds 10821da177e4SLinus Torvalds bp = NULL; 10831da177e4SLinus Torvalds len = BBTOB(len); 10841da177e4SLinus Torvalds for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) { 10851da177e4SLinus Torvalds if (XFS_LIC_ARE_ALL_FREE(licp)) { 10861da177e4SLinus Torvalds ASSERT(licp == &tp->t_items); 10871da177e4SLinus Torvalds ASSERT(licp->lic_next == NULL); 10881da177e4SLinus Torvalds return NULL; 10891da177e4SLinus Torvalds } 10901da177e4SLinus Torvalds for (i = 0; i < licp->lic_unused; i++) { 10911da177e4SLinus Torvalds /* 10921da177e4SLinus Torvalds * Skip unoccupied slots. 10931da177e4SLinus Torvalds */ 10941da177e4SLinus Torvalds if (XFS_LIC_ISFREE(licp, i)) { 10951da177e4SLinus Torvalds continue; 10961da177e4SLinus Torvalds } 10971da177e4SLinus Torvalds 10981da177e4SLinus Torvalds lidp = XFS_LIC_SLOT(licp, i); 10991da177e4SLinus Torvalds blip = (xfs_buf_log_item_t *)lidp->lid_item; 11001da177e4SLinus Torvalds if (blip->bli_item.li_type != XFS_LI_BUF) { 11011da177e4SLinus Torvalds continue; 11021da177e4SLinus Torvalds } 11031da177e4SLinus Torvalds 11041da177e4SLinus Torvalds bp = blip->bli_buf; 11051da177e4SLinus Torvalds if ((XFS_BUF_TARGET(bp) == target) && 11061da177e4SLinus Torvalds (XFS_BUF_ADDR(bp) == blkno) && 11071da177e4SLinus Torvalds (XFS_BUF_COUNT(bp) == len)) { 11081da177e4SLinus Torvalds /* 11091da177e4SLinus Torvalds * We found it. Break out and 11101da177e4SLinus Torvalds * return the pointer to the buffer. 11111da177e4SLinus Torvalds */ 11121da177e4SLinus Torvalds return bp; 11131da177e4SLinus Torvalds } 11141da177e4SLinus Torvalds } 11151da177e4SLinus Torvalds } 11161da177e4SLinus Torvalds return NULL; 11171da177e4SLinus Torvalds } 1118