11da177e4SLinus Torvalds /* 27b718769SNathan Scott * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 37b718769SNathan Scott * All Rights Reserved. 41da177e4SLinus Torvalds * 57b718769SNathan Scott * This program is free software; you can redistribute it and/or 67b718769SNathan Scott * modify it under the terms of the GNU General Public License as 71da177e4SLinus Torvalds * published by the Free Software Foundation. 81da177e4SLinus Torvalds * 97b718769SNathan Scott * This program is distributed in the hope that it would be useful, 107b718769SNathan Scott * but WITHOUT ANY WARRANTY; without even the implied warranty of 117b718769SNathan Scott * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 127b718769SNathan Scott * GNU General Public License for more details. 131da177e4SLinus Torvalds * 147b718769SNathan Scott * You should have received a copy of the GNU General Public License 157b718769SNathan Scott * along with this program; if not, write the Free Software Foundation, 167b718769SNathan Scott * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 171da177e4SLinus Torvalds */ 181da177e4SLinus Torvalds #include "xfs.h" 19a844f451SNathan Scott #include "xfs_fs.h" 2070a9883cSDave Chinner #include "xfs_shared.h" 21a4fbe6abSDave Chinner #include "xfs_format.h" 22239880efSDave Chinner #include "xfs_log_format.h" 23239880efSDave Chinner #include "xfs_trans_resv.h" 241da177e4SLinus Torvalds #include "xfs_sb.h" 251da177e4SLinus Torvalds #include "xfs_ag.h" 261da177e4SLinus Torvalds #include "xfs_mount.h" 27a844f451SNathan Scott #include "xfs_inode.h" 28239880efSDave Chinner #include "xfs_trans.h" 29a844f451SNathan Scott #include "xfs_buf_item.h" 301da177e4SLinus Torvalds #include "xfs_trans_priv.h" 311da177e4SLinus Torvalds #include "xfs_error.h" 320b1b213fSChristoph Hellwig #include "xfs_trace.h" 331da177e4SLinus Torvalds 344a5224d7SChristoph Hellwig /* 354a5224d7SChristoph Hellwig * Check to see if a buffer matching the given parameters is already 364a5224d7SChristoph Hellwig * a part of the given transaction. 374a5224d7SChristoph Hellwig */ 384a5224d7SChristoph Hellwig STATIC struct xfs_buf * 394a5224d7SChristoph Hellwig xfs_trans_buf_item_match( 404a5224d7SChristoph Hellwig struct xfs_trans *tp, 414a5224d7SChristoph Hellwig struct xfs_buftarg *target, 42de2a4f59SDave Chinner struct xfs_buf_map *map, 43de2a4f59SDave Chinner int nmaps) 444a5224d7SChristoph Hellwig { 45e98c414fSChristoph Hellwig struct xfs_log_item_desc *lidp; 46e98c414fSChristoph Hellwig struct xfs_buf_log_item *blip; 47de2a4f59SDave Chinner int len = 0; 48de2a4f59SDave Chinner int i; 491da177e4SLinus Torvalds 50de2a4f59SDave Chinner for (i = 0; i < nmaps; i++) 51de2a4f59SDave Chinner len += map[i].bm_len; 52de2a4f59SDave Chinner 53e98c414fSChristoph Hellwig list_for_each_entry(lidp, &tp->t_items, lid_trans) { 54e98c414fSChristoph Hellwig blip = (struct xfs_buf_log_item *)lidp->lid_item; 55e98c414fSChristoph Hellwig if (blip->bli_item.li_type == XFS_LI_BUF && 5649074c06SChandra Seetharaman blip->bli_buf->b_target == target && 57de2a4f59SDave Chinner XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn && 58de2a4f59SDave Chinner blip->bli_buf->b_length == len) { 59de2a4f59SDave Chinner ASSERT(blip->bli_buf->b_map_count == nmaps); 604a5224d7SChristoph Hellwig return blip->bli_buf; 614a5224d7SChristoph Hellwig } 62de2a4f59SDave Chinner } 634a5224d7SChristoph Hellwig 644a5224d7SChristoph Hellwig return NULL; 654a5224d7SChristoph Hellwig } 661da177e4SLinus Torvalds 67d7e84f41SChristoph Hellwig /* 68d7e84f41SChristoph Hellwig * Add the locked buffer to the transaction. 69d7e84f41SChristoph Hellwig * 70d7e84f41SChristoph Hellwig * The buffer must be locked, and it cannot be associated with any 71d7e84f41SChristoph Hellwig * transaction. 72d7e84f41SChristoph Hellwig * 73d7e84f41SChristoph Hellwig * If the buffer does not yet have a buf log item associated with it, 74d7e84f41SChristoph Hellwig * then allocate one for it. Then add the buf item to the transaction. 75d7e84f41SChristoph Hellwig */ 76d7e84f41SChristoph Hellwig STATIC void 77d7e84f41SChristoph Hellwig _xfs_trans_bjoin( 78d7e84f41SChristoph Hellwig struct xfs_trans *tp, 79d7e84f41SChristoph Hellwig struct xfs_buf *bp, 80d7e84f41SChristoph Hellwig int reset_recur) 81d7e84f41SChristoph Hellwig { 82d7e84f41SChristoph Hellwig struct xfs_buf_log_item *bip; 83d7e84f41SChristoph Hellwig 84bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == NULL); 85d7e84f41SChristoph Hellwig 86d7e84f41SChristoph Hellwig /* 87d7e84f41SChristoph Hellwig * The xfs_buf_log_item pointer is stored in b_fsprivate. If 88d7e84f41SChristoph Hellwig * it doesn't have one yet, then allocate one and initialize it. 89d7e84f41SChristoph Hellwig * The checks to see if one is there are in xfs_buf_item_init(). 90d7e84f41SChristoph Hellwig */ 91d7e84f41SChristoph Hellwig xfs_buf_item_init(bp, tp->t_mountp); 92adadbeefSChristoph Hellwig bip = bp->b_fspriv; 93d7e84f41SChristoph Hellwig ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 940f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 95d7e84f41SChristoph Hellwig ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 96d7e84f41SChristoph Hellwig if (reset_recur) 97d7e84f41SChristoph Hellwig bip->bli_recur = 0; 98d7e84f41SChristoph Hellwig 99d7e84f41SChristoph Hellwig /* 100d7e84f41SChristoph Hellwig * Take a reference for this transaction on the buf item. 101d7e84f41SChristoph Hellwig */ 102d7e84f41SChristoph Hellwig atomic_inc(&bip->bli_refcount); 103d7e84f41SChristoph Hellwig 104d7e84f41SChristoph Hellwig /* 105d7e84f41SChristoph Hellwig * Get a log_item_desc to point at the new item. 106d7e84f41SChristoph Hellwig */ 107e98c414fSChristoph Hellwig xfs_trans_add_item(tp, &bip->bli_item); 108d7e84f41SChristoph Hellwig 109d7e84f41SChristoph Hellwig /* 110d7e84f41SChristoph Hellwig * Initialize b_fsprivate2 so we can find it with incore_match() 111d7e84f41SChristoph Hellwig * in xfs_trans_get_buf() and friends above. 112d7e84f41SChristoph Hellwig */ 113bf9d9013SChristoph Hellwig bp->b_transp = tp; 114d7e84f41SChristoph Hellwig 115d7e84f41SChristoph Hellwig } 116d7e84f41SChristoph Hellwig 117d7e84f41SChristoph Hellwig void 118d7e84f41SChristoph Hellwig xfs_trans_bjoin( 119d7e84f41SChristoph Hellwig struct xfs_trans *tp, 120d7e84f41SChristoph Hellwig struct xfs_buf *bp) 121d7e84f41SChristoph Hellwig { 122d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 0); 123d7e84f41SChristoph Hellwig trace_xfs_trans_bjoin(bp->b_fspriv); 124d7e84f41SChristoph Hellwig } 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds /* 1271da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 1281da177e4SLinus Torvalds * locked within the given transaction. If it is already locked 1291da177e4SLinus Torvalds * within the transaction, just increment its lock recursion count 1301da177e4SLinus Torvalds * and return a pointer to it. 1311da177e4SLinus Torvalds * 1321da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 1331da177e4SLinus Torvalds * get_buf() call. 1341da177e4SLinus Torvalds */ 135de2a4f59SDave Chinner struct xfs_buf * 136de2a4f59SDave Chinner xfs_trans_get_buf_map( 137de2a4f59SDave Chinner struct xfs_trans *tp, 138de2a4f59SDave Chinner struct xfs_buftarg *target, 139de2a4f59SDave Chinner struct xfs_buf_map *map, 140de2a4f59SDave Chinner int nmaps, 141de2a4f59SDave Chinner xfs_buf_flags_t flags) 1421da177e4SLinus Torvalds { 1431da177e4SLinus Torvalds xfs_buf_t *bp; 1441da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 1451da177e4SLinus Torvalds 146de2a4f59SDave Chinner if (!tp) 147de2a4f59SDave Chinner return xfs_buf_get_map(target, map, nmaps, flags); 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds /* 1501da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 1511da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 1521da177e4SLinus Torvalds * have it locked. In this case we just increment the lock 1531da177e4SLinus Torvalds * recursion count and return the buffer to the caller. 1541da177e4SLinus Torvalds */ 155de2a4f59SDave Chinner bp = xfs_trans_buf_item_match(tp, target, map, nmaps); 1561da177e4SLinus Torvalds if (bp != NULL) { 1570c842ad4SChristoph Hellwig ASSERT(xfs_buf_islocked(bp)); 158c867cb61SChristoph Hellwig if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) { 159c867cb61SChristoph Hellwig xfs_buf_stale(bp); 160c867cb61SChristoph Hellwig XFS_BUF_DONE(bp); 161c867cb61SChristoph Hellwig } 1620b1b213fSChristoph Hellwig 163bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 164adadbeefSChristoph Hellwig bip = bp->b_fspriv; 1651da177e4SLinus Torvalds ASSERT(bip != NULL); 1661da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 1671da177e4SLinus Torvalds bip->bli_recur++; 1680b1b213fSChristoph Hellwig trace_xfs_trans_get_buf_recur(bip); 1691da177e4SLinus Torvalds return (bp); 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 172de2a4f59SDave Chinner bp = xfs_buf_get_map(target, map, nmaps, flags); 1731da177e4SLinus Torvalds if (bp == NULL) { 1741da177e4SLinus Torvalds return NULL; 1751da177e4SLinus Torvalds } 1761da177e4SLinus Torvalds 1775a52c2a5SChandra Seetharaman ASSERT(!bp->b_error); 1781da177e4SLinus Torvalds 179d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 180d7e84f41SChristoph Hellwig trace_xfs_trans_get_buf(bp->b_fspriv); 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; 215bf9d9013SChristoph Hellwig if (bp->b_transp == tp) { 216adadbeefSChristoph Hellwig bip = bp->b_fspriv; 2171da177e4SLinus Torvalds ASSERT(bip != NULL); 2181da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 2191da177e4SLinus Torvalds bip->bli_recur++; 2200b1b213fSChristoph Hellwig trace_xfs_trans_getsb_recur(bip); 2211da177e4SLinus Torvalds return (bp); 2221da177e4SLinus Torvalds } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds bp = xfs_getsb(mp, flags); 225d7e84f41SChristoph Hellwig if (bp == NULL) 2261da177e4SLinus Torvalds return NULL; 2271da177e4SLinus Torvalds 228d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 229d7e84f41SChristoph Hellwig trace_xfs_trans_getsb(bp->b_fspriv); 2301da177e4SLinus Torvalds return (bp); 2311da177e4SLinus Torvalds } 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds #ifdef DEBUG 2341da177e4SLinus Torvalds xfs_buftarg_t *xfs_error_target; 2351da177e4SLinus Torvalds int xfs_do_error; 2361da177e4SLinus Torvalds int xfs_req_num; 2371da177e4SLinus Torvalds int xfs_error_mod = 33; 2381da177e4SLinus Torvalds #endif 2391da177e4SLinus Torvalds 2401da177e4SLinus Torvalds /* 2411da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 2421da177e4SLinus Torvalds * locked within the given transaction. If it has not yet been 2431da177e4SLinus Torvalds * read in, read it from disk. If it is already locked 2441da177e4SLinus Torvalds * within the transaction and already read in, just increment its 2451da177e4SLinus Torvalds * lock recursion count and return a pointer to it. 2461da177e4SLinus Torvalds * 2471da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 2481da177e4SLinus Torvalds * read_buf() call. 2491da177e4SLinus Torvalds */ 2501da177e4SLinus Torvalds int 251de2a4f59SDave Chinner xfs_trans_read_buf_map( 252de2a4f59SDave Chinner struct xfs_mount *mp, 253de2a4f59SDave Chinner struct xfs_trans *tp, 254de2a4f59SDave Chinner struct xfs_buftarg *target, 255de2a4f59SDave Chinner struct xfs_buf_map *map, 256de2a4f59SDave Chinner int nmaps, 257de2a4f59SDave Chinner xfs_buf_flags_t flags, 258c3f8fc73SDave Chinner struct xfs_buf **bpp, 2591813dd64SDave Chinner const struct xfs_buf_ops *ops) 2601da177e4SLinus Torvalds { 2611da177e4SLinus Torvalds xfs_buf_t *bp; 2621da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 2631da177e4SLinus Torvalds int error; 2641da177e4SLinus Torvalds 2657ca790a5SDave Chinner *bpp = NULL; 266de2a4f59SDave Chinner if (!tp) { 2671813dd64SDave Chinner bp = xfs_buf_read_map(target, map, nmaps, flags, ops); 2681da177e4SLinus Torvalds if (!bp) 2690cadda1cSChristoph Hellwig return (flags & XBF_TRYLOCK) ? 270a3f74ffbSDavid Chinner EAGAIN : XFS_ERROR(ENOMEM); 2711da177e4SLinus Torvalds 2725a52c2a5SChandra Seetharaman if (bp->b_error) { 2735a52c2a5SChandra Seetharaman error = bp->b_error; 274901796afSChristoph Hellwig xfs_buf_ioerror_alert(bp, __func__); 2757ca790a5SDave Chinner XFS_BUF_UNDONE(bp); 2767ca790a5SDave Chinner xfs_buf_stale(bp); 2771da177e4SLinus Torvalds xfs_buf_relse(bp); 2781da177e4SLinus Torvalds return error; 2791da177e4SLinus Torvalds } 2801da177e4SLinus Torvalds #ifdef DEBUG 281a0f7bfd3SJulia Lawall if (xfs_do_error) { 2821da177e4SLinus Torvalds if (xfs_error_target == target) { 2831da177e4SLinus Torvalds if (((xfs_req_num++) % xfs_error_mod) == 0) { 2841da177e4SLinus Torvalds xfs_buf_relse(bp); 2850b932cccSDave Chinner xfs_debug(mp, "Returning error!"); 2861da177e4SLinus Torvalds return XFS_ERROR(EIO); 2871da177e4SLinus Torvalds } 2881da177e4SLinus Torvalds } 2891da177e4SLinus Torvalds } 2901da177e4SLinus Torvalds #endif 2911da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) 2921da177e4SLinus Torvalds goto shutdown_abort; 2931da177e4SLinus Torvalds *bpp = bp; 2941da177e4SLinus Torvalds return 0; 2951da177e4SLinus Torvalds } 2961da177e4SLinus Torvalds 2971da177e4SLinus Torvalds /* 2981da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 2991da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 3001da177e4SLinus Torvalds * have it locked. If it is already read in we just increment 3011da177e4SLinus Torvalds * the lock recursion count and return the buffer to the caller. 3021da177e4SLinus Torvalds * If the buffer is not yet read in, then we read it in, increment 3031da177e4SLinus Torvalds * the lock recursion count, and return it to the caller. 3041da177e4SLinus Torvalds */ 305de2a4f59SDave Chinner bp = xfs_trans_buf_item_match(tp, target, map, nmaps); 3061da177e4SLinus Torvalds if (bp != NULL) { 3070c842ad4SChristoph Hellwig ASSERT(xfs_buf_islocked(bp)); 308bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 309adadbeefSChristoph Hellwig ASSERT(bp->b_fspriv != NULL); 3105a52c2a5SChandra Seetharaman ASSERT(!bp->b_error); 3111da177e4SLinus Torvalds if (!(XFS_BUF_ISDONE(bp))) { 3120b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_io(bp, _RET_IP_); 3131da177e4SLinus Torvalds ASSERT(!XFS_BUF_ISASYNC(bp)); 314c3f8fc73SDave Chinner ASSERT(bp->b_iodone == NULL); 3151da177e4SLinus Torvalds XFS_BUF_READ(bp); 3161813dd64SDave Chinner bp->b_ops = ops; 317*83a0adc3SChristoph Hellwig 318*83a0adc3SChristoph Hellwig /* 319*83a0adc3SChristoph Hellwig * XXX(hch): clean up the error handling here to be less 320*83a0adc3SChristoph Hellwig * of a mess.. 321*83a0adc3SChristoph Hellwig */ 322*83a0adc3SChristoph Hellwig if (XFS_FORCED_SHUTDOWN(mp)) { 323*83a0adc3SChristoph Hellwig trace_xfs_bdstrat_shut(bp, _RET_IP_); 324*83a0adc3SChristoph Hellwig xfs_bioerror_relse(bp); 325*83a0adc3SChristoph Hellwig } else { 326*83a0adc3SChristoph Hellwig xfs_buf_iorequest(bp); 327*83a0adc3SChristoph Hellwig } 328*83a0adc3SChristoph Hellwig 3291a1a3e97SChristoph Hellwig error = xfs_buf_iowait(bp); 330d64e31a2SDavid Chinner if (error) { 331901796afSChristoph Hellwig xfs_buf_ioerror_alert(bp, __func__); 3321da177e4SLinus Torvalds xfs_buf_relse(bp); 3331da177e4SLinus Torvalds /* 334d64e31a2SDavid Chinner * We can gracefully recover from most read 335d64e31a2SDavid Chinner * errors. Ones we can't are those that happen 336d64e31a2SDavid Chinner * after the transaction's already dirty. 3371da177e4SLinus Torvalds */ 3381da177e4SLinus Torvalds if (tp->t_flags & XFS_TRANS_DIRTY) 3391da177e4SLinus Torvalds xfs_force_shutdown(tp->t_mountp, 3407d04a335SNathan Scott SHUTDOWN_META_IO_ERROR); 3411da177e4SLinus Torvalds return error; 3421da177e4SLinus Torvalds } 3431da177e4SLinus Torvalds } 3441da177e4SLinus Torvalds /* 3451da177e4SLinus Torvalds * We never locked this buf ourselves, so we shouldn't 3461da177e4SLinus Torvalds * brelse it either. Just get out. 3471da177e4SLinus Torvalds */ 3481da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) { 3490b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_shut(bp, _RET_IP_); 3501da177e4SLinus Torvalds *bpp = NULL; 3511da177e4SLinus Torvalds return XFS_ERROR(EIO); 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds 3541da177e4SLinus Torvalds 355adadbeefSChristoph Hellwig bip = bp->b_fspriv; 3561da177e4SLinus Torvalds bip->bli_recur++; 3571da177e4SLinus Torvalds 3581da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 3590b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_recur(bip); 3601da177e4SLinus Torvalds *bpp = bp; 3611da177e4SLinus Torvalds return 0; 3621da177e4SLinus Torvalds } 3631da177e4SLinus Torvalds 3641813dd64SDave Chinner bp = xfs_buf_read_map(target, map, nmaps, flags, ops); 3651da177e4SLinus Torvalds if (bp == NULL) { 3661da177e4SLinus Torvalds *bpp = NULL; 3677401aafdSDave Chinner return (flags & XBF_TRYLOCK) ? 3687401aafdSDave Chinner 0 : XFS_ERROR(ENOMEM); 3691da177e4SLinus Torvalds } 3705a52c2a5SChandra Seetharaman if (bp->b_error) { 3715a52c2a5SChandra Seetharaman error = bp->b_error; 372c867cb61SChristoph Hellwig xfs_buf_stale(bp); 373c867cb61SChristoph Hellwig XFS_BUF_DONE(bp); 374901796afSChristoph Hellwig xfs_buf_ioerror_alert(bp, __func__); 3751da177e4SLinus Torvalds if (tp->t_flags & XFS_TRANS_DIRTY) 3767d04a335SNathan Scott xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); 3771da177e4SLinus Torvalds xfs_buf_relse(bp); 3781da177e4SLinus Torvalds return error; 3791da177e4SLinus Torvalds } 3801da177e4SLinus Torvalds #ifdef DEBUG 3811da177e4SLinus Torvalds if (xfs_do_error && !(tp->t_flags & XFS_TRANS_DIRTY)) { 3821da177e4SLinus Torvalds if (xfs_error_target == target) { 3831da177e4SLinus Torvalds if (((xfs_req_num++) % xfs_error_mod) == 0) { 3841da177e4SLinus Torvalds xfs_force_shutdown(tp->t_mountp, 3857d04a335SNathan Scott SHUTDOWN_META_IO_ERROR); 3861da177e4SLinus Torvalds xfs_buf_relse(bp); 3870b932cccSDave Chinner xfs_debug(mp, "Returning trans error!"); 3881da177e4SLinus Torvalds return XFS_ERROR(EIO); 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds } 3921da177e4SLinus Torvalds #endif 3931da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) 3941da177e4SLinus Torvalds goto shutdown_abort; 3951da177e4SLinus Torvalds 396d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 397d7e84f41SChristoph Hellwig trace_xfs_trans_read_buf(bp->b_fspriv); 3981da177e4SLinus Torvalds 3991da177e4SLinus Torvalds *bpp = bp; 4001da177e4SLinus Torvalds return 0; 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds shutdown_abort: 4030b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_shut(bp, _RET_IP_); 4041da177e4SLinus Torvalds xfs_buf_relse(bp); 4051da177e4SLinus Torvalds *bpp = NULL; 4061da177e4SLinus Torvalds return XFS_ERROR(EIO); 4071da177e4SLinus Torvalds } 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds /* 4101da177e4SLinus Torvalds * Release the buffer bp which was previously acquired with one of the 4111da177e4SLinus Torvalds * xfs_trans_... buffer allocation routines if the buffer has not 4121da177e4SLinus Torvalds * been modified within this transaction. If the buffer is modified 4131da177e4SLinus Torvalds * within this transaction, do decrement the recursion count but do 4141da177e4SLinus Torvalds * not release the buffer even if the count goes to 0. If the buffer is not 4151da177e4SLinus Torvalds * modified within the transaction, decrement the recursion count and 4161da177e4SLinus Torvalds * release the buffer if the recursion count goes to 0. 4171da177e4SLinus Torvalds * 4181da177e4SLinus Torvalds * If the buffer is to be released and it was not modified before 4191da177e4SLinus Torvalds * this transaction began, then free the buf_log_item associated with it. 4201da177e4SLinus Torvalds * 4211da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 4221da177e4SLinus Torvalds * brelse() call. 4231da177e4SLinus Torvalds */ 4241da177e4SLinus Torvalds void 4251da177e4SLinus Torvalds xfs_trans_brelse(xfs_trans_t *tp, 4261da177e4SLinus Torvalds xfs_buf_t *bp) 4271da177e4SLinus Torvalds { 4281da177e4SLinus Torvalds xfs_buf_log_item_t *bip; 4291da177e4SLinus Torvalds 4301da177e4SLinus Torvalds /* 4311da177e4SLinus Torvalds * Default to a normal brelse() call if the tp is NULL. 4321da177e4SLinus Torvalds */ 4331da177e4SLinus Torvalds if (tp == NULL) { 434bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == NULL); 4351da177e4SLinus Torvalds xfs_buf_relse(bp); 4361da177e4SLinus Torvalds return; 4371da177e4SLinus Torvalds } 4381da177e4SLinus Torvalds 439bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 440adadbeefSChristoph Hellwig bip = bp->b_fspriv; 4411da177e4SLinus Torvalds ASSERT(bip->bli_item.li_type == XFS_LI_BUF); 4421da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 4430f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 4441da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 4451da177e4SLinus Torvalds 4460b1b213fSChristoph Hellwig trace_xfs_trans_brelse(bip); 4470b1b213fSChristoph Hellwig 4481da177e4SLinus Torvalds /* 4491da177e4SLinus Torvalds * If the release is just for a recursive lock, 4501da177e4SLinus Torvalds * then decrement the count and return. 4511da177e4SLinus Torvalds */ 4521da177e4SLinus Torvalds if (bip->bli_recur > 0) { 4531da177e4SLinus Torvalds bip->bli_recur--; 4541da177e4SLinus Torvalds return; 4551da177e4SLinus Torvalds } 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds /* 4581da177e4SLinus Torvalds * If the buffer is dirty within this transaction, we can't 4591da177e4SLinus Torvalds * release it until we commit. 4601da177e4SLinus Torvalds */ 461e98c414fSChristoph Hellwig if (bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY) 4621da177e4SLinus Torvalds return; 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds /* 4651da177e4SLinus Torvalds * If the buffer has been invalidated, then we can't release 4661da177e4SLinus Torvalds * it until the transaction commits to disk unless it is re-dirtied 4671da177e4SLinus Torvalds * as part of this transaction. This prevents us from pulling 4681da177e4SLinus Torvalds * the item from the AIL before we should. 4691da177e4SLinus Torvalds */ 4700b1b213fSChristoph Hellwig if (bip->bli_flags & XFS_BLI_STALE) 4711da177e4SLinus Torvalds return; 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds /* 4761da177e4SLinus Torvalds * Free up the log item descriptor tracking the released item. 4771da177e4SLinus Torvalds */ 478e98c414fSChristoph Hellwig xfs_trans_del_item(&bip->bli_item); 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds /* 4811da177e4SLinus Torvalds * Clear the hold flag in the buf log item if it is set. 4821da177e4SLinus Torvalds * We wouldn't want the next user of the buffer to 4831da177e4SLinus Torvalds * get confused. 4841da177e4SLinus Torvalds */ 4851da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_HOLD) { 4861da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_HOLD; 4871da177e4SLinus Torvalds } 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds /* 4901da177e4SLinus Torvalds * Drop our reference to the buf log item. 4911da177e4SLinus Torvalds */ 4921da177e4SLinus Torvalds atomic_dec(&bip->bli_refcount); 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds /* 4951da177e4SLinus Torvalds * If the buf item is not tracking data in the log, then 4961da177e4SLinus Torvalds * we must free it before releasing the buffer back to the 4971da177e4SLinus Torvalds * free pool. Before releasing the buffer to the free pool, 4981da177e4SLinus Torvalds * clear the transaction pointer in b_fsprivate2 to dissolve 4991da177e4SLinus Torvalds * its relation to this transaction. 5001da177e4SLinus Torvalds */ 5011da177e4SLinus Torvalds if (!xfs_buf_item_dirty(bip)) { 5021da177e4SLinus Torvalds /*** 5031da177e4SLinus Torvalds ASSERT(bp->b_pincount == 0); 5041da177e4SLinus Torvalds ***/ 5051da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) == 0); 5061da177e4SLinus Torvalds ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL)); 5071da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF)); 5081da177e4SLinus Torvalds xfs_buf_item_relse(bp); 5091da177e4SLinus Torvalds } 5105b03ff1bSChristoph Hellwig 511bf9d9013SChristoph Hellwig bp->b_transp = NULL; 5121da177e4SLinus Torvalds xfs_buf_relse(bp); 5131da177e4SLinus Torvalds } 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds /* 5161da177e4SLinus Torvalds * Mark the buffer as not needing to be unlocked when the buf item's 517904c17e6SDave Chinner * iop_unlock() routine is called. The buffer must already be locked 5181da177e4SLinus Torvalds * and associated with the given transaction. 5191da177e4SLinus Torvalds */ 5201da177e4SLinus Torvalds /* ARGSUSED */ 5211da177e4SLinus Torvalds void 5221da177e4SLinus Torvalds xfs_trans_bhold(xfs_trans_t *tp, 5231da177e4SLinus Torvalds xfs_buf_t *bp) 5241da177e4SLinus Torvalds { 525adadbeefSChristoph Hellwig xfs_buf_log_item_t *bip = bp->b_fspriv; 5261da177e4SLinus Torvalds 527bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 528adadbeefSChristoph Hellwig ASSERT(bip != NULL); 5291da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 5300f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 5311da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 532adadbeefSChristoph Hellwig 5331da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_HOLD; 5340b1b213fSChristoph Hellwig trace_xfs_trans_bhold(bip); 5351da177e4SLinus Torvalds } 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds /* 538efa092f3STim Shimmin * Cancel the previous buffer hold request made on this buffer 539efa092f3STim Shimmin * for this transaction. 540efa092f3STim Shimmin */ 541efa092f3STim Shimmin void 542efa092f3STim Shimmin xfs_trans_bhold_release(xfs_trans_t *tp, 543efa092f3STim Shimmin xfs_buf_t *bp) 544efa092f3STim Shimmin { 545adadbeefSChristoph Hellwig xfs_buf_log_item_t *bip = bp->b_fspriv; 546efa092f3STim Shimmin 547bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 548adadbeefSChristoph Hellwig ASSERT(bip != NULL); 549efa092f3STim Shimmin ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 5500f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 551efa092f3STim Shimmin ASSERT(atomic_read(&bip->bli_refcount) > 0); 552efa092f3STim Shimmin ASSERT(bip->bli_flags & XFS_BLI_HOLD); 5530b1b213fSChristoph Hellwig 554adadbeefSChristoph Hellwig bip->bli_flags &= ~XFS_BLI_HOLD; 5550b1b213fSChristoph Hellwig trace_xfs_trans_bhold_release(bip); 556efa092f3STim Shimmin } 557efa092f3STim Shimmin 558efa092f3STim Shimmin /* 5591da177e4SLinus Torvalds * This is called to mark bytes first through last inclusive of the given 5601da177e4SLinus Torvalds * buffer as needing to be logged when the transaction is committed. 5611da177e4SLinus Torvalds * The buffer must already be associated with the given transaction. 5621da177e4SLinus Torvalds * 5631da177e4SLinus Torvalds * First and last are numbers relative to the beginning of this buffer, 5641da177e4SLinus Torvalds * so the first byte in the buffer is numbered 0 regardless of the 5651da177e4SLinus Torvalds * value of b_blkno. 5661da177e4SLinus Torvalds */ 5671da177e4SLinus Torvalds void 5681da177e4SLinus Torvalds xfs_trans_log_buf(xfs_trans_t *tp, 5691da177e4SLinus Torvalds xfs_buf_t *bp, 5701da177e4SLinus Torvalds uint first, 5711da177e4SLinus Torvalds uint last) 5721da177e4SLinus Torvalds { 573adadbeefSChristoph Hellwig xfs_buf_log_item_t *bip = bp->b_fspriv; 5741da177e4SLinus Torvalds 575bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 576adadbeefSChristoph Hellwig ASSERT(bip != NULL); 577aa0e8833SDave Chinner ASSERT(first <= last && last < BBTOB(bp->b_length)); 578cb669ca5SChristoph Hellwig ASSERT(bp->b_iodone == NULL || 579cb669ca5SChristoph Hellwig bp->b_iodone == xfs_buf_iodone_callbacks); 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds /* 5821da177e4SLinus Torvalds * Mark the buffer as needing to be written out eventually, 5831da177e4SLinus Torvalds * and set its iodone function to remove the buffer's buf log 5841da177e4SLinus Torvalds * item from the AIL and free it when the buffer is flushed 5851da177e4SLinus Torvalds * to disk. See xfs_buf_attach_iodone() for more details 5861da177e4SLinus Torvalds * on li_cb and xfs_buf_iodone_callbacks(). 5871da177e4SLinus Torvalds * If we end up aborting this transaction, we trap this buffer 5881da177e4SLinus Torvalds * inside the b_bdstrat callback so that this won't get written to 5891da177e4SLinus Torvalds * disk. 5901da177e4SLinus Torvalds */ 5911da177e4SLinus Torvalds XFS_BUF_DONE(bp); 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 594cb669ca5SChristoph Hellwig bp->b_iodone = xfs_buf_iodone_callbacks; 595ca30b2a7SChristoph Hellwig bip->bli_item.li_cb = xfs_buf_iodone; 5961da177e4SLinus Torvalds 5970b1b213fSChristoph Hellwig trace_xfs_trans_log_buf(bip); 5980b1b213fSChristoph Hellwig 5991da177e4SLinus Torvalds /* 6001da177e4SLinus Torvalds * If we invalidated the buffer within this transaction, then 6011da177e4SLinus Torvalds * cancel the invalidation now that we're dirtying the buffer 6021da177e4SLinus Torvalds * again. There are no races with the code in xfs_buf_item_unpin(), 6031da177e4SLinus Torvalds * because we have a reference to the buffer this entire time. 6041da177e4SLinus Torvalds */ 6051da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 6061da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_STALE; 6071da177e4SLinus Torvalds ASSERT(XFS_BUF_ISSTALE(bp)); 6081da177e4SLinus Torvalds XFS_BUF_UNSTALE(bp); 6090f22f9d0SMark Tinguely bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL; 6101da177e4SLinus Torvalds } 6111da177e4SLinus Torvalds 6121da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 613e98c414fSChristoph Hellwig bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; 6145f6bed76SDave Chinner 6155f6bed76SDave Chinner /* 6165f6bed76SDave Chinner * If we have an ordered buffer we are not logging any dirty range but 6175f6bed76SDave Chinner * it still needs to be marked dirty and that it has been logged. 6185f6bed76SDave Chinner */ 6195f6bed76SDave Chinner bip->bli_flags |= XFS_BLI_DIRTY | XFS_BLI_LOGGED; 6205f6bed76SDave Chinner if (!(bip->bli_flags & XFS_BLI_ORDERED)) 6211da177e4SLinus Torvalds xfs_buf_item_log(bip, first, last); 6221da177e4SLinus Torvalds } 6231da177e4SLinus Torvalds 6241da177e4SLinus Torvalds 6251da177e4SLinus Torvalds /* 62643ff2122SChristoph Hellwig * Invalidate a buffer that is being used within a transaction. 6271da177e4SLinus Torvalds * 62843ff2122SChristoph Hellwig * Typically this is because the blocks in the buffer are being freed, so we 62943ff2122SChristoph Hellwig * need to prevent it from being written out when we're done. Allowing it 63043ff2122SChristoph Hellwig * to be written again might overwrite data in the free blocks if they are 63143ff2122SChristoph Hellwig * reallocated to a file. 63243ff2122SChristoph Hellwig * 63343ff2122SChristoph Hellwig * We prevent the buffer from being written out by marking it stale. We can't 63443ff2122SChristoph Hellwig * get rid of the buf log item at this point because the buffer may still be 63543ff2122SChristoph Hellwig * pinned by another transaction. If that is the case, then we'll wait until 63643ff2122SChristoph Hellwig * the buffer is committed to disk for the last time (we can tell by the ref 63743ff2122SChristoph Hellwig * count) and free it in xfs_buf_item_unpin(). Until that happens we will 63843ff2122SChristoph Hellwig * keep the buffer locked so that the buffer and buf log item are not reused. 63943ff2122SChristoph Hellwig * 64043ff2122SChristoph Hellwig * We also set the XFS_BLF_CANCEL flag in the buf log format structure and log 64143ff2122SChristoph Hellwig * the buf item. This will be used at recovery time to determine that copies 64243ff2122SChristoph Hellwig * of the buffer in the log before this should not be replayed. 64343ff2122SChristoph Hellwig * 64443ff2122SChristoph Hellwig * We mark the item descriptor and the transaction dirty so that we'll hold 64543ff2122SChristoph Hellwig * the buffer until after the commit. 64643ff2122SChristoph Hellwig * 64743ff2122SChristoph Hellwig * Since we're invalidating the buffer, we also clear the state about which 64843ff2122SChristoph Hellwig * parts of the buffer have been logged. We also clear the flag indicating 64943ff2122SChristoph Hellwig * that this is an inode buffer since the data in the buffer will no longer 65043ff2122SChristoph Hellwig * be valid. 65143ff2122SChristoph Hellwig * 65243ff2122SChristoph Hellwig * We set the stale bit in the buffer as well since we're getting rid of it. 6531da177e4SLinus Torvalds */ 6541da177e4SLinus Torvalds void 6551da177e4SLinus Torvalds xfs_trans_binval( 6561da177e4SLinus Torvalds xfs_trans_t *tp, 6571da177e4SLinus Torvalds xfs_buf_t *bp) 6581da177e4SLinus Torvalds { 659adadbeefSChristoph Hellwig xfs_buf_log_item_t *bip = bp->b_fspriv; 66091e4bac0SMark Tinguely int i; 6611da177e4SLinus Torvalds 662bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 663adadbeefSChristoph Hellwig ASSERT(bip != NULL); 6641da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 6651da177e4SLinus Torvalds 6660b1b213fSChristoph Hellwig trace_xfs_trans_binval(bip); 6670b1b213fSChristoph Hellwig 6681da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 6691da177e4SLinus Torvalds /* 6701da177e4SLinus Torvalds * If the buffer is already invalidated, then 6711da177e4SLinus Torvalds * just return. 6721da177e4SLinus Torvalds */ 6731da177e4SLinus Torvalds ASSERT(XFS_BUF_ISSTALE(bp)); 6741da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); 6750f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF)); 67661fe135cSDave Chinner ASSERT(!(bip->__bli_format.blf_flags & XFS_BLFT_MASK)); 6770f22f9d0SMark Tinguely ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); 678e98c414fSChristoph Hellwig ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY); 6791da177e4SLinus Torvalds ASSERT(tp->t_flags & XFS_TRANS_DIRTY); 6801da177e4SLinus Torvalds return; 6811da177e4SLinus Torvalds } 6821da177e4SLinus Torvalds 683c867cb61SChristoph Hellwig xfs_buf_stale(bp); 68443ff2122SChristoph Hellwig 6851da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE; 686ccf7c23fSDave Chinner bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); 6870f22f9d0SMark Tinguely bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; 6880f22f9d0SMark Tinguely bip->__bli_format.blf_flags |= XFS_BLF_CANCEL; 68961fe135cSDave Chinner bip->__bli_format.blf_flags &= ~XFS_BLFT_MASK; 69091e4bac0SMark Tinguely for (i = 0; i < bip->bli_format_count; i++) { 69191e4bac0SMark Tinguely memset(bip->bli_formats[i].blf_data_map, 0, 69291e4bac0SMark Tinguely (bip->bli_formats[i].blf_map_size * sizeof(uint))); 69391e4bac0SMark Tinguely } 694e98c414fSChristoph Hellwig bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; 6951da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 6961da177e4SLinus Torvalds } 6971da177e4SLinus Torvalds 6981da177e4SLinus Torvalds /* 699ccf7c23fSDave Chinner * This call is used to indicate that the buffer contains on-disk inodes which 700ccf7c23fSDave Chinner * must be handled specially during recovery. They require special handling 701ccf7c23fSDave Chinner * because only the di_next_unlinked from the inodes in the buffer should be 702ccf7c23fSDave Chinner * recovered. The rest of the data in the buffer is logged via the inodes 703ccf7c23fSDave Chinner * themselves. 7041da177e4SLinus Torvalds * 705ccf7c23fSDave Chinner * All we do is set the XFS_BLI_INODE_BUF flag in the items flags so it can be 706ccf7c23fSDave Chinner * transferred to the buffer's log format structure so that we'll know what to 707ccf7c23fSDave Chinner * do at recovery time. 7081da177e4SLinus Torvalds */ 7091da177e4SLinus Torvalds void 7101da177e4SLinus Torvalds xfs_trans_inode_buf( 7111da177e4SLinus Torvalds xfs_trans_t *tp, 7121da177e4SLinus Torvalds xfs_buf_t *bp) 7131da177e4SLinus Torvalds { 714adadbeefSChristoph Hellwig xfs_buf_log_item_t *bip = bp->b_fspriv; 7151da177e4SLinus Torvalds 716bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 717adadbeefSChristoph Hellwig ASSERT(bip != NULL); 7181da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 7191da177e4SLinus Torvalds 720ccf7c23fSDave Chinner bip->bli_flags |= XFS_BLI_INODE_BUF; 72161fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 7221da177e4SLinus Torvalds } 7231da177e4SLinus Torvalds 7241da177e4SLinus Torvalds /* 7251da177e4SLinus Torvalds * This call is used to indicate that the buffer is going to 7261da177e4SLinus Torvalds * be staled and was an inode buffer. This means it gets 7271da177e4SLinus Torvalds * special processing during unpin - where any inodes 7281da177e4SLinus Torvalds * associated with the buffer should be removed from ail. 7291da177e4SLinus Torvalds * There is also special processing during recovery, 7301da177e4SLinus Torvalds * any replay of the inodes in the buffer needs to be 7311da177e4SLinus Torvalds * prevented as the buffer may have been reused. 7321da177e4SLinus Torvalds */ 7331da177e4SLinus Torvalds void 7341da177e4SLinus Torvalds xfs_trans_stale_inode_buf( 7351da177e4SLinus Torvalds xfs_trans_t *tp, 7361da177e4SLinus Torvalds xfs_buf_t *bp) 7371da177e4SLinus Torvalds { 738adadbeefSChristoph Hellwig xfs_buf_log_item_t *bip = bp->b_fspriv; 7391da177e4SLinus Torvalds 740bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 741adadbeefSChristoph Hellwig ASSERT(bip != NULL); 7421da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE_INODE; 745ca30b2a7SChristoph Hellwig bip->bli_item.li_cb = xfs_buf_iodone; 74661fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 7471da177e4SLinus Torvalds } 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds /* 7501da177e4SLinus Torvalds * Mark the buffer as being one which contains newly allocated 7511da177e4SLinus Torvalds * inodes. We need to make sure that even if this buffer is 7521da177e4SLinus Torvalds * relogged as an 'inode buf' we still recover all of the inode 7531da177e4SLinus Torvalds * images in the face of a crash. This works in coordination with 7541da177e4SLinus Torvalds * xfs_buf_item_committed() to ensure that the buffer remains in the 7551da177e4SLinus Torvalds * AIL at its original location even after it has been relogged. 7561da177e4SLinus Torvalds */ 7571da177e4SLinus Torvalds /* ARGSUSED */ 7581da177e4SLinus Torvalds void 7591da177e4SLinus Torvalds xfs_trans_inode_alloc_buf( 7601da177e4SLinus Torvalds xfs_trans_t *tp, 7611da177e4SLinus Torvalds xfs_buf_t *bp) 7621da177e4SLinus Torvalds { 763adadbeefSChristoph Hellwig xfs_buf_log_item_t *bip = bp->b_fspriv; 7641da177e4SLinus Torvalds 765bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 766adadbeefSChristoph Hellwig ASSERT(bip != NULL); 7671da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 7681da177e4SLinus Torvalds 7691da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; 77061fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 7711da177e4SLinus Torvalds } 7721da177e4SLinus Torvalds 773ee1a47abSChristoph Hellwig /* 7745f6bed76SDave Chinner * Mark the buffer as ordered for this transaction. This means 7755f6bed76SDave Chinner * that the contents of the buffer are not recorded in the transaction 7765f6bed76SDave Chinner * but it is tracked in the AIL as though it was. This allows us 7775f6bed76SDave Chinner * to record logical changes in transactions rather than the physical 7785f6bed76SDave Chinner * changes we make to the buffer without changing writeback ordering 7795f6bed76SDave Chinner * constraints of metadata buffers. 7805f6bed76SDave Chinner */ 7815f6bed76SDave Chinner void 7825f6bed76SDave Chinner xfs_trans_ordered_buf( 7835f6bed76SDave Chinner struct xfs_trans *tp, 7845f6bed76SDave Chinner struct xfs_buf *bp) 7855f6bed76SDave Chinner { 7865f6bed76SDave Chinner struct xfs_buf_log_item *bip = bp->b_fspriv; 7875f6bed76SDave Chinner 7885f6bed76SDave Chinner ASSERT(bp->b_transp == tp); 7895f6bed76SDave Chinner ASSERT(bip != NULL); 7905f6bed76SDave Chinner ASSERT(atomic_read(&bip->bli_refcount) > 0); 7915f6bed76SDave Chinner 7925f6bed76SDave Chinner bip->bli_flags |= XFS_BLI_ORDERED; 7935f6bed76SDave Chinner trace_xfs_buf_item_ordered(bip); 7945f6bed76SDave Chinner } 7955f6bed76SDave Chinner 7965f6bed76SDave Chinner /* 797ee1a47abSChristoph Hellwig * Set the type of the buffer for log recovery so that it can correctly identify 798ee1a47abSChristoph Hellwig * and hence attach the correct buffer ops to the buffer after replay. 799ee1a47abSChristoph Hellwig */ 800ee1a47abSChristoph Hellwig void 801ee1a47abSChristoph Hellwig xfs_trans_buf_set_type( 802ee1a47abSChristoph Hellwig struct xfs_trans *tp, 803ee1a47abSChristoph Hellwig struct xfs_buf *bp, 80461fe135cSDave Chinner enum xfs_blft type) 805ee1a47abSChristoph Hellwig { 806ee1a47abSChristoph Hellwig struct xfs_buf_log_item *bip = bp->b_fspriv; 807ee1a47abSChristoph Hellwig 808d75afeb3SDave Chinner if (!tp) 809d75afeb3SDave Chinner return; 810d75afeb3SDave Chinner 811ee1a47abSChristoph Hellwig ASSERT(bp->b_transp == tp); 812ee1a47abSChristoph Hellwig ASSERT(bip != NULL); 813ee1a47abSChristoph Hellwig ASSERT(atomic_read(&bip->bli_refcount) > 0); 814ee1a47abSChristoph Hellwig 81561fe135cSDave Chinner xfs_blft_to_flags(&bip->__bli_format, type); 816ee1a47abSChristoph Hellwig } 8171da177e4SLinus Torvalds 818d75afeb3SDave Chinner void 819d75afeb3SDave Chinner xfs_trans_buf_copy_type( 820d75afeb3SDave Chinner struct xfs_buf *dst_bp, 821d75afeb3SDave Chinner struct xfs_buf *src_bp) 822d75afeb3SDave Chinner { 823d75afeb3SDave Chinner struct xfs_buf_log_item *sbip = src_bp->b_fspriv; 824d75afeb3SDave Chinner struct xfs_buf_log_item *dbip = dst_bp->b_fspriv; 82561fe135cSDave Chinner enum xfs_blft type; 826d75afeb3SDave Chinner 82761fe135cSDave Chinner type = xfs_blft_from_flags(&sbip->__bli_format); 82861fe135cSDave Chinner xfs_blft_to_flags(&dbip->__bli_format, type); 829d75afeb3SDave Chinner } 830d75afeb3SDave Chinner 8311da177e4SLinus Torvalds /* 8321da177e4SLinus Torvalds * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of 8331da177e4SLinus Torvalds * dquots. However, unlike in inode buffer recovery, dquot buffers get 8341da177e4SLinus Torvalds * recovered in their entirety. (Hence, no XFS_BLI_DQUOT_ALLOC_BUF flag). 8351da177e4SLinus Torvalds * The only thing that makes dquot buffers different from regular 8361da177e4SLinus Torvalds * buffers is that we must not replay dquot bufs when recovering 8371da177e4SLinus Torvalds * if a _corresponding_ quotaoff has happened. We also have to distinguish 8381da177e4SLinus Torvalds * between usr dquot bufs and grp dquot bufs, because usr and grp quotas 8391da177e4SLinus Torvalds * can be turned off independently. 8401da177e4SLinus Torvalds */ 8411da177e4SLinus Torvalds /* ARGSUSED */ 8421da177e4SLinus Torvalds void 8431da177e4SLinus Torvalds xfs_trans_dquot_buf( 8441da177e4SLinus Torvalds xfs_trans_t *tp, 8451da177e4SLinus Torvalds xfs_buf_t *bp, 8461da177e4SLinus Torvalds uint type) 8471da177e4SLinus Torvalds { 84861fe135cSDave Chinner struct xfs_buf_log_item *bip = bp->b_fspriv; 84961fe135cSDave Chinner 850c1155410SDave Chinner ASSERT(type == XFS_BLF_UDQUOT_BUF || 851c1155410SDave Chinner type == XFS_BLF_PDQUOT_BUF || 852c1155410SDave Chinner type == XFS_BLF_GDQUOT_BUF); 8531da177e4SLinus Torvalds 85461fe135cSDave Chinner bip->__bli_format.blf_flags |= type; 85561fe135cSDave Chinner 85661fe135cSDave Chinner switch (type) { 85761fe135cSDave Chinner case XFS_BLF_UDQUOT_BUF: 85861fe135cSDave Chinner type = XFS_BLFT_UDQUOT_BUF; 85961fe135cSDave Chinner break; 86061fe135cSDave Chinner case XFS_BLF_PDQUOT_BUF: 86161fe135cSDave Chinner type = XFS_BLFT_PDQUOT_BUF; 86261fe135cSDave Chinner break; 86361fe135cSDave Chinner case XFS_BLF_GDQUOT_BUF: 86461fe135cSDave Chinner type = XFS_BLFT_GDQUOT_BUF; 86561fe135cSDave Chinner break; 86661fe135cSDave Chinner default: 86761fe135cSDave Chinner type = XFS_BLFT_UNKNOWN_BUF; 86861fe135cSDave Chinner break; 86961fe135cSDave Chinner } 87061fe135cSDave Chinner 871ee1a47abSChristoph Hellwig xfs_trans_buf_set_type(tp, bp, type); 8721da177e4SLinus Torvalds } 873