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_mount.h" 25a844f451SNathan Scott #include "xfs_inode.h" 26239880efSDave Chinner #include "xfs_trans.h" 27a844f451SNathan Scott #include "xfs_buf_item.h" 281da177e4SLinus Torvalds #include "xfs_trans_priv.h" 291da177e4SLinus Torvalds #include "xfs_error.h" 300b1b213fSChristoph Hellwig #include "xfs_trace.h" 311da177e4SLinus Torvalds 324a5224d7SChristoph Hellwig /* 334a5224d7SChristoph Hellwig * Check to see if a buffer matching the given parameters is already 344a5224d7SChristoph Hellwig * a part of the given transaction. 354a5224d7SChristoph Hellwig */ 364a5224d7SChristoph Hellwig STATIC struct xfs_buf * 374a5224d7SChristoph Hellwig xfs_trans_buf_item_match( 384a5224d7SChristoph Hellwig struct xfs_trans *tp, 394a5224d7SChristoph Hellwig struct xfs_buftarg *target, 40de2a4f59SDave Chinner struct xfs_buf_map *map, 41de2a4f59SDave Chinner int nmaps) 424a5224d7SChristoph Hellwig { 43e98c414fSChristoph Hellwig struct xfs_log_item_desc *lidp; 44e98c414fSChristoph Hellwig struct xfs_buf_log_item *blip; 45de2a4f59SDave Chinner int len = 0; 46de2a4f59SDave Chinner int i; 471da177e4SLinus Torvalds 48de2a4f59SDave Chinner for (i = 0; i < nmaps; i++) 49de2a4f59SDave Chinner len += map[i].bm_len; 50de2a4f59SDave Chinner 51e98c414fSChristoph Hellwig list_for_each_entry(lidp, &tp->t_items, lid_trans) { 52e98c414fSChristoph Hellwig blip = (struct xfs_buf_log_item *)lidp->lid_item; 53e98c414fSChristoph Hellwig if (blip->bli_item.li_type == XFS_LI_BUF && 5449074c06SChandra Seetharaman blip->bli_buf->b_target == target && 55de2a4f59SDave Chinner XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn && 56de2a4f59SDave Chinner blip->bli_buf->b_length == len) { 57de2a4f59SDave Chinner ASSERT(blip->bli_buf->b_map_count == nmaps); 584a5224d7SChristoph Hellwig return blip->bli_buf; 594a5224d7SChristoph Hellwig } 60de2a4f59SDave Chinner } 614a5224d7SChristoph Hellwig 624a5224d7SChristoph Hellwig return NULL; 634a5224d7SChristoph Hellwig } 641da177e4SLinus Torvalds 65d7e84f41SChristoph Hellwig /* 66d7e84f41SChristoph Hellwig * Add the locked buffer to the transaction. 67d7e84f41SChristoph Hellwig * 68d7e84f41SChristoph Hellwig * The buffer must be locked, and it cannot be associated with any 69d7e84f41SChristoph Hellwig * transaction. 70d7e84f41SChristoph Hellwig * 71d7e84f41SChristoph Hellwig * If the buffer does not yet have a buf log item associated with it, 72d7e84f41SChristoph Hellwig * then allocate one for it. Then add the buf item to the transaction. 73d7e84f41SChristoph Hellwig */ 74d7e84f41SChristoph Hellwig STATIC void 75d7e84f41SChristoph Hellwig _xfs_trans_bjoin( 76d7e84f41SChristoph Hellwig struct xfs_trans *tp, 77d7e84f41SChristoph Hellwig struct xfs_buf *bp, 78d7e84f41SChristoph Hellwig int reset_recur) 79d7e84f41SChristoph Hellwig { 80d7e84f41SChristoph Hellwig struct xfs_buf_log_item *bip; 81d7e84f41SChristoph Hellwig 82bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == NULL); 83d7e84f41SChristoph Hellwig 84d7e84f41SChristoph Hellwig /* 85d7e84f41SChristoph Hellwig * The xfs_buf_log_item pointer is stored in b_fsprivate. If 86d7e84f41SChristoph Hellwig * it doesn't have one yet, then allocate one and initialize it. 87d7e84f41SChristoph Hellwig * The checks to see if one is there are in xfs_buf_item_init(). 88d7e84f41SChristoph Hellwig */ 89d7e84f41SChristoph Hellwig xfs_buf_item_init(bp, tp->t_mountp); 90adadbeefSChristoph Hellwig bip = bp->b_fspriv; 91d7e84f41SChristoph Hellwig ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 920f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 93d7e84f41SChristoph Hellwig ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 94d7e84f41SChristoph Hellwig if (reset_recur) 95d7e84f41SChristoph Hellwig bip->bli_recur = 0; 96d7e84f41SChristoph Hellwig 97d7e84f41SChristoph Hellwig /* 98d7e84f41SChristoph Hellwig * Take a reference for this transaction on the buf item. 99d7e84f41SChristoph Hellwig */ 100d7e84f41SChristoph Hellwig atomic_inc(&bip->bli_refcount); 101d7e84f41SChristoph Hellwig 102d7e84f41SChristoph Hellwig /* 103d7e84f41SChristoph Hellwig * Get a log_item_desc to point at the new item. 104d7e84f41SChristoph Hellwig */ 105e98c414fSChristoph Hellwig xfs_trans_add_item(tp, &bip->bli_item); 106d7e84f41SChristoph Hellwig 107d7e84f41SChristoph Hellwig /* 108d7e84f41SChristoph Hellwig * Initialize b_fsprivate2 so we can find it with incore_match() 109d7e84f41SChristoph Hellwig * in xfs_trans_get_buf() and friends above. 110d7e84f41SChristoph Hellwig */ 111bf9d9013SChristoph Hellwig bp->b_transp = tp; 112d7e84f41SChristoph Hellwig 113d7e84f41SChristoph Hellwig } 114d7e84f41SChristoph Hellwig 115d7e84f41SChristoph Hellwig void 116d7e84f41SChristoph Hellwig xfs_trans_bjoin( 117d7e84f41SChristoph Hellwig struct xfs_trans *tp, 118d7e84f41SChristoph Hellwig struct xfs_buf *bp) 119d7e84f41SChristoph Hellwig { 120d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 0); 121d7e84f41SChristoph Hellwig trace_xfs_trans_bjoin(bp->b_fspriv); 122d7e84f41SChristoph Hellwig } 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds /* 1251da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 1261da177e4SLinus Torvalds * locked within the given transaction. If it is already locked 1271da177e4SLinus Torvalds * within the transaction, just increment its lock recursion count 1281da177e4SLinus Torvalds * and return a pointer to it. 1291da177e4SLinus Torvalds * 1301da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 1311da177e4SLinus Torvalds * get_buf() call. 1321da177e4SLinus Torvalds */ 133de2a4f59SDave Chinner struct xfs_buf * 134de2a4f59SDave Chinner xfs_trans_get_buf_map( 135de2a4f59SDave Chinner struct xfs_trans *tp, 136de2a4f59SDave Chinner struct xfs_buftarg *target, 137de2a4f59SDave Chinner struct xfs_buf_map *map, 138de2a4f59SDave Chinner int nmaps, 139de2a4f59SDave Chinner xfs_buf_flags_t flags) 1401da177e4SLinus Torvalds { 1411da177e4SLinus Torvalds xfs_buf_t *bp; 142*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip; 1431da177e4SLinus Torvalds 144de2a4f59SDave Chinner if (!tp) 145de2a4f59SDave Chinner return xfs_buf_get_map(target, map, nmaps, flags); 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds /* 1481da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 1491da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 1501da177e4SLinus Torvalds * have it locked. In this case we just increment the lock 1511da177e4SLinus Torvalds * recursion count and return the buffer to the caller. 1521da177e4SLinus Torvalds */ 153de2a4f59SDave Chinner bp = xfs_trans_buf_item_match(tp, target, map, nmaps); 1541da177e4SLinus Torvalds if (bp != NULL) { 1550c842ad4SChristoph Hellwig ASSERT(xfs_buf_islocked(bp)); 156c867cb61SChristoph Hellwig if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) { 157c867cb61SChristoph Hellwig xfs_buf_stale(bp); 158b0388bf1SDave Chinner bp->b_flags |= XBF_DONE; 159c867cb61SChristoph Hellwig } 1600b1b213fSChristoph Hellwig 161bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 162adadbeefSChristoph Hellwig bip = bp->b_fspriv; 1631da177e4SLinus Torvalds ASSERT(bip != NULL); 1641da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 1651da177e4SLinus Torvalds bip->bli_recur++; 1660b1b213fSChristoph Hellwig trace_xfs_trans_get_buf_recur(bip); 167d99831ffSEric Sandeen return bp; 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds 170de2a4f59SDave Chinner bp = xfs_buf_get_map(target, map, nmaps, flags); 1711da177e4SLinus Torvalds if (bp == NULL) { 1721da177e4SLinus Torvalds return NULL; 1731da177e4SLinus Torvalds } 1741da177e4SLinus Torvalds 1755a52c2a5SChandra Seetharaman ASSERT(!bp->b_error); 1761da177e4SLinus Torvalds 177d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 178d7e84f41SChristoph Hellwig trace_xfs_trans_get_buf(bp->b_fspriv); 179d99831ffSEric Sandeen return bp; 1801da177e4SLinus Torvalds } 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds /* 1831da177e4SLinus Torvalds * Get and lock the superblock buffer of this file system for the 1841da177e4SLinus Torvalds * given transaction. 1851da177e4SLinus Torvalds * 1861da177e4SLinus Torvalds * We don't need to use incore_match() here, because the superblock 1871da177e4SLinus Torvalds * buffer is a private buffer which we keep a pointer to in the 1881da177e4SLinus Torvalds * mount structure. 1891da177e4SLinus Torvalds */ 1901da177e4SLinus Torvalds xfs_buf_t * 191*70a20655SCarlos Maiolino xfs_trans_getsb( 192*70a20655SCarlos Maiolino xfs_trans_t *tp, 1931da177e4SLinus Torvalds struct xfs_mount *mp, 1941da177e4SLinus Torvalds int flags) 1951da177e4SLinus Torvalds { 1961da177e4SLinus Torvalds xfs_buf_t *bp; 197*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip; 1981da177e4SLinus Torvalds 1991da177e4SLinus Torvalds /* 2001da177e4SLinus Torvalds * Default to just trying to lock the superblock buffer 2011da177e4SLinus Torvalds * if tp is NULL. 2021da177e4SLinus Torvalds */ 203d99831ffSEric Sandeen if (tp == NULL) 204d99831ffSEric Sandeen return xfs_getsb(mp, flags); 2051da177e4SLinus Torvalds 2061da177e4SLinus Torvalds /* 2071da177e4SLinus Torvalds * If the superblock buffer already has this transaction 2081da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 2091da177e4SLinus Torvalds * have it locked. In this case we just increment the lock 2101da177e4SLinus Torvalds * recursion count and return the buffer to the caller. 2111da177e4SLinus Torvalds */ 2121da177e4SLinus Torvalds bp = mp->m_sb_bp; 213bf9d9013SChristoph Hellwig if (bp->b_transp == tp) { 214adadbeefSChristoph Hellwig bip = bp->b_fspriv; 2151da177e4SLinus Torvalds ASSERT(bip != NULL); 2161da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 2171da177e4SLinus Torvalds bip->bli_recur++; 2180b1b213fSChristoph Hellwig trace_xfs_trans_getsb_recur(bip); 219d99831ffSEric Sandeen return bp; 2201da177e4SLinus Torvalds } 2211da177e4SLinus Torvalds 2221da177e4SLinus Torvalds bp = xfs_getsb(mp, flags); 223d7e84f41SChristoph Hellwig if (bp == NULL) 2241da177e4SLinus Torvalds return NULL; 2251da177e4SLinus Torvalds 226d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 227d7e84f41SChristoph Hellwig trace_xfs_trans_getsb(bp->b_fspriv); 228d99831ffSEric Sandeen return bp; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds /* 2321da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 2331da177e4SLinus Torvalds * locked within the given transaction. If it has not yet been 2341da177e4SLinus Torvalds * read in, read it from disk. If it is already locked 2351da177e4SLinus Torvalds * within the transaction and already read in, just increment its 2361da177e4SLinus Torvalds * lock recursion count and return a pointer to it. 2371da177e4SLinus Torvalds * 2381da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 2391da177e4SLinus Torvalds * read_buf() call. 2401da177e4SLinus Torvalds */ 2411da177e4SLinus Torvalds int 242de2a4f59SDave Chinner xfs_trans_read_buf_map( 243de2a4f59SDave Chinner struct xfs_mount *mp, 244de2a4f59SDave Chinner struct xfs_trans *tp, 245de2a4f59SDave Chinner struct xfs_buftarg *target, 246de2a4f59SDave Chinner struct xfs_buf_map *map, 247de2a4f59SDave Chinner int nmaps, 248de2a4f59SDave Chinner xfs_buf_flags_t flags, 249c3f8fc73SDave Chinner struct xfs_buf **bpp, 2501813dd64SDave Chinner const struct xfs_buf_ops *ops) 2511da177e4SLinus Torvalds { 2522d3d0c53SDave Chinner struct xfs_buf *bp = NULL; 2532d3d0c53SDave Chinner struct xfs_buf_log_item *bip; 2541da177e4SLinus Torvalds int error; 2551da177e4SLinus Torvalds 2567ca790a5SDave Chinner *bpp = NULL; 2571da177e4SLinus Torvalds /* 2581da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 2591da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 2601da177e4SLinus Torvalds * have it locked. If it is already read in we just increment 2611da177e4SLinus Torvalds * the lock recursion count and return the buffer to the caller. 2621da177e4SLinus Torvalds * If the buffer is not yet read in, then we read it in, increment 2631da177e4SLinus Torvalds * the lock recursion count, and return it to the caller. 2641da177e4SLinus Torvalds */ 2652d3d0c53SDave Chinner if (tp) 266de2a4f59SDave Chinner bp = xfs_trans_buf_item_match(tp, target, map, nmaps); 2672d3d0c53SDave Chinner if (bp) { 2680c842ad4SChristoph Hellwig ASSERT(xfs_buf_islocked(bp)); 269bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 270adadbeefSChristoph Hellwig ASSERT(bp->b_fspriv != NULL); 2715a52c2a5SChandra Seetharaman ASSERT(!bp->b_error); 2722d3d0c53SDave Chinner ASSERT(bp->b_flags & XBF_DONE); 27383a0adc3SChristoph Hellwig 2741da177e4SLinus Torvalds /* 2751da177e4SLinus Torvalds * We never locked this buf ourselves, so we shouldn't 2761da177e4SLinus Torvalds * brelse it either. Just get out. 2771da177e4SLinus Torvalds */ 2781da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) { 2790b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_shut(bp, _RET_IP_); 2802451337dSDave Chinner return -EIO; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 283adadbeefSChristoph Hellwig bip = bp->b_fspriv; 2841da177e4SLinus Torvalds bip->bli_recur++; 2851da177e4SLinus Torvalds 2861da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 2870b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_recur(bip); 2881da177e4SLinus Torvalds *bpp = bp; 2891da177e4SLinus Torvalds return 0; 2901da177e4SLinus Torvalds } 2911da177e4SLinus Torvalds 2921813dd64SDave Chinner bp = xfs_buf_read_map(target, map, nmaps, flags, ops); 2932d3d0c53SDave Chinner if (!bp) { 2942d3d0c53SDave Chinner if (!(flags & XBF_TRYLOCK)) 2952d3d0c53SDave Chinner return -ENOMEM; 2962d3d0c53SDave Chinner return tp ? 0 : -EAGAIN; 2971da177e4SLinus Torvalds } 2982d3d0c53SDave Chinner 2992d3d0c53SDave Chinner /* 3002d3d0c53SDave Chinner * If we've had a read error, then the contents of the buffer are 3012d3d0c53SDave Chinner * invalid and should not be used. To ensure that a followup read tries 3022d3d0c53SDave Chinner * to pull the buffer from disk again, we clear the XBF_DONE flag and 3032d3d0c53SDave Chinner * mark the buffer stale. This ensures that anyone who has a current 3042d3d0c53SDave Chinner * reference to the buffer will interpret it's contents correctly and 3052d3d0c53SDave Chinner * future cache lookups will also treat it as an empty, uninitialised 3062d3d0c53SDave Chinner * buffer. 3072d3d0c53SDave Chinner */ 3085a52c2a5SChandra Seetharaman if (bp->b_error) { 3095a52c2a5SChandra Seetharaman error = bp->b_error; 3102d3d0c53SDave Chinner if (!XFS_FORCED_SHUTDOWN(mp)) 311901796afSChristoph Hellwig xfs_buf_ioerror_alert(bp, __func__); 3122d3d0c53SDave Chinner bp->b_flags &= ~XBF_DONE; 3132d3d0c53SDave Chinner xfs_buf_stale(bp); 3142d3d0c53SDave Chinner 3152d3d0c53SDave Chinner if (tp && (tp->t_flags & XFS_TRANS_DIRTY)) 3167d04a335SNathan Scott xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); 3171da177e4SLinus Torvalds xfs_buf_relse(bp); 318ac75a1f7SDave Chinner 319ac75a1f7SDave Chinner /* bad CRC means corrupted metadata */ 3202451337dSDave Chinner if (error == -EFSBADCRC) 3212451337dSDave Chinner error = -EFSCORRUPTED; 3221da177e4SLinus Torvalds return error; 3231da177e4SLinus Torvalds } 3242d3d0c53SDave Chinner 3252d3d0c53SDave Chinner if (XFS_FORCED_SHUTDOWN(mp)) { 3261da177e4SLinus Torvalds xfs_buf_relse(bp); 3272d3d0c53SDave Chinner trace_xfs_trans_read_buf_shut(bp, _RET_IP_); 3282451337dSDave Chinner return -EIO; 3291da177e4SLinus Torvalds } 3301da177e4SLinus Torvalds 331e9892d3cSDave Chinner if (tp) { 332d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 333d7e84f41SChristoph Hellwig trace_xfs_trans_read_buf(bp->b_fspriv); 334e9892d3cSDave Chinner } 3351da177e4SLinus Torvalds *bpp = bp; 3361da177e4SLinus Torvalds return 0; 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds } 3391da177e4SLinus Torvalds 3401da177e4SLinus Torvalds /* 3411da177e4SLinus Torvalds * Release the buffer bp which was previously acquired with one of the 3421da177e4SLinus Torvalds * xfs_trans_... buffer allocation routines if the buffer has not 3431da177e4SLinus Torvalds * been modified within this transaction. If the buffer is modified 3441da177e4SLinus Torvalds * within this transaction, do decrement the recursion count but do 3451da177e4SLinus Torvalds * not release the buffer even if the count goes to 0. If the buffer is not 3461da177e4SLinus Torvalds * modified within the transaction, decrement the recursion count and 3471da177e4SLinus Torvalds * release the buffer if the recursion count goes to 0. 3481da177e4SLinus Torvalds * 3491da177e4SLinus Torvalds * If the buffer is to be released and it was not modified before 3501da177e4SLinus Torvalds * this transaction began, then free the buf_log_item associated with it. 3511da177e4SLinus Torvalds * 3521da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 3531da177e4SLinus Torvalds * brelse() call. 3541da177e4SLinus Torvalds */ 3551da177e4SLinus Torvalds void 356*70a20655SCarlos Maiolino xfs_trans_brelse( 357*70a20655SCarlos Maiolino xfs_trans_t *tp, 3581da177e4SLinus Torvalds xfs_buf_t *bp) 3591da177e4SLinus Torvalds { 360*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip; 36179e641ceSBrian Foster int freed; 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds /* 3641da177e4SLinus Torvalds * Default to a normal brelse() call if the tp is NULL. 3651da177e4SLinus Torvalds */ 3661da177e4SLinus Torvalds if (tp == NULL) { 367bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == NULL); 3681da177e4SLinus Torvalds xfs_buf_relse(bp); 3691da177e4SLinus Torvalds return; 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds 372bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 373adadbeefSChristoph Hellwig bip = bp->b_fspriv; 3741da177e4SLinus Torvalds ASSERT(bip->bli_item.li_type == XFS_LI_BUF); 3751da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 3760f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 3771da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 3781da177e4SLinus Torvalds 3790b1b213fSChristoph Hellwig trace_xfs_trans_brelse(bip); 3800b1b213fSChristoph Hellwig 3811da177e4SLinus Torvalds /* 3821da177e4SLinus Torvalds * If the release is just for a recursive lock, 3831da177e4SLinus Torvalds * then decrement the count and return. 3841da177e4SLinus Torvalds */ 3851da177e4SLinus Torvalds if (bip->bli_recur > 0) { 3861da177e4SLinus Torvalds bip->bli_recur--; 3871da177e4SLinus Torvalds return; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds /* 3911da177e4SLinus Torvalds * If the buffer is dirty within this transaction, we can't 3921da177e4SLinus Torvalds * release it until we commit. 3931da177e4SLinus Torvalds */ 394e98c414fSChristoph Hellwig if (bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY) 3951da177e4SLinus Torvalds return; 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds /* 3981da177e4SLinus Torvalds * If the buffer has been invalidated, then we can't release 3991da177e4SLinus Torvalds * it until the transaction commits to disk unless it is re-dirtied 4001da177e4SLinus Torvalds * as part of this transaction. This prevents us from pulling 4011da177e4SLinus Torvalds * the item from the AIL before we should. 4021da177e4SLinus Torvalds */ 4030b1b213fSChristoph Hellwig if (bip->bli_flags & XFS_BLI_STALE) 4041da177e4SLinus Torvalds return; 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds /* 4091da177e4SLinus Torvalds * Free up the log item descriptor tracking the released item. 4101da177e4SLinus Torvalds */ 411e98c414fSChristoph Hellwig xfs_trans_del_item(&bip->bli_item); 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds /* 4141da177e4SLinus Torvalds * Clear the hold flag in the buf log item if it is set. 4151da177e4SLinus Torvalds * We wouldn't want the next user of the buffer to 4161da177e4SLinus Torvalds * get confused. 4171da177e4SLinus Torvalds */ 4181da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_HOLD) { 4191da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_HOLD; 4201da177e4SLinus Torvalds } 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds /* 4231da177e4SLinus Torvalds * Drop our reference to the buf log item. 4241da177e4SLinus Torvalds */ 42579e641ceSBrian Foster freed = atomic_dec_and_test(&bip->bli_refcount); 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds /* 42879e641ceSBrian Foster * If the buf item is not tracking data in the log, then we must free it 42979e641ceSBrian Foster * before releasing the buffer back to the free pool. 43079e641ceSBrian Foster * 43179e641ceSBrian Foster * If the fs has shutdown and we dropped the last reference, it may fall 43279e641ceSBrian Foster * on us to release a (possibly dirty) bli if it never made it to the 43379e641ceSBrian Foster * AIL (e.g., the aborted unpin already happened and didn't release it 43479e641ceSBrian Foster * due to our reference). Since we're already shutdown and need xa_lock, 43579e641ceSBrian Foster * just force remove from the AIL and release the bli here. 4361da177e4SLinus Torvalds */ 43779e641ceSBrian Foster if (XFS_FORCED_SHUTDOWN(tp->t_mountp) && freed) { 43879e641ceSBrian Foster xfs_trans_ail_remove(&bip->bli_item, SHUTDOWN_LOG_IO_ERROR); 43979e641ceSBrian Foster xfs_buf_item_relse(bp); 440a4f6cf6bSBrian Foster } else if (!(bip->bli_flags & XFS_BLI_DIRTY)) { 4411da177e4SLinus Torvalds /*** 4421da177e4SLinus Torvalds ASSERT(bp->b_pincount == 0); 4431da177e4SLinus Torvalds ***/ 4441da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) == 0); 4451da177e4SLinus Torvalds ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL)); 4461da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF)); 4471da177e4SLinus Torvalds xfs_buf_item_relse(bp); 4481da177e4SLinus Torvalds } 4495b03ff1bSChristoph Hellwig 450bf9d9013SChristoph Hellwig bp->b_transp = NULL; 4511da177e4SLinus Torvalds xfs_buf_relse(bp); 4521da177e4SLinus Torvalds } 4531da177e4SLinus Torvalds 4541da177e4SLinus Torvalds /* 4551da177e4SLinus Torvalds * Mark the buffer as not needing to be unlocked when the buf item's 456904c17e6SDave Chinner * iop_unlock() routine is called. The buffer must already be locked 4571da177e4SLinus Torvalds * and associated with the given transaction. 4581da177e4SLinus Torvalds */ 4591da177e4SLinus Torvalds /* ARGSUSED */ 4601da177e4SLinus Torvalds void 461*70a20655SCarlos Maiolino xfs_trans_bhold( 462*70a20655SCarlos Maiolino xfs_trans_t *tp, 4631da177e4SLinus Torvalds xfs_buf_t *bp) 4641da177e4SLinus Torvalds { 465*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_fspriv; 4661da177e4SLinus Torvalds 467bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 468adadbeefSChristoph Hellwig ASSERT(bip != NULL); 4691da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 4700f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 4711da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 472adadbeefSChristoph Hellwig 4731da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_HOLD; 4740b1b213fSChristoph Hellwig trace_xfs_trans_bhold(bip); 4751da177e4SLinus Torvalds } 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds /* 478efa092f3STim Shimmin * Cancel the previous buffer hold request made on this buffer 479efa092f3STim Shimmin * for this transaction. 480efa092f3STim Shimmin */ 481efa092f3STim Shimmin void 482*70a20655SCarlos Maiolino xfs_trans_bhold_release( 483*70a20655SCarlos Maiolino xfs_trans_t *tp, 484efa092f3STim Shimmin xfs_buf_t *bp) 485efa092f3STim Shimmin { 486*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_fspriv; 487efa092f3STim Shimmin 488bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 489adadbeefSChristoph Hellwig ASSERT(bip != NULL); 490efa092f3STim Shimmin ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 4910f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 492efa092f3STim Shimmin ASSERT(atomic_read(&bip->bli_refcount) > 0); 493efa092f3STim Shimmin ASSERT(bip->bli_flags & XFS_BLI_HOLD); 4940b1b213fSChristoph Hellwig 495adadbeefSChristoph Hellwig bip->bli_flags &= ~XFS_BLI_HOLD; 4960b1b213fSChristoph Hellwig trace_xfs_trans_bhold_release(bip); 497efa092f3STim Shimmin } 498efa092f3STim Shimmin 499efa092f3STim Shimmin /* 5009684010dSBrian Foster * Mark a buffer dirty in the transaction. 5011da177e4SLinus Torvalds */ 5021da177e4SLinus Torvalds void 5039684010dSBrian Foster xfs_trans_dirty_buf( 5049684010dSBrian Foster struct xfs_trans *tp, 5059684010dSBrian Foster struct xfs_buf *bp) 5061da177e4SLinus Torvalds { 5079684010dSBrian Foster struct xfs_buf_log_item *bip = bp->b_fspriv; 5081da177e4SLinus Torvalds 509bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 510adadbeefSChristoph Hellwig ASSERT(bip != NULL); 511cb669ca5SChristoph Hellwig ASSERT(bp->b_iodone == NULL || 512cb669ca5SChristoph Hellwig bp->b_iodone == xfs_buf_iodone_callbacks); 5131da177e4SLinus Torvalds 5141da177e4SLinus Torvalds /* 5151da177e4SLinus Torvalds * Mark the buffer as needing to be written out eventually, 5161da177e4SLinus Torvalds * and set its iodone function to remove the buffer's buf log 5171da177e4SLinus Torvalds * item from the AIL and free it when the buffer is flushed 5181da177e4SLinus Torvalds * to disk. See xfs_buf_attach_iodone() for more details 5191da177e4SLinus Torvalds * on li_cb and xfs_buf_iodone_callbacks(). 5201da177e4SLinus Torvalds * If we end up aborting this transaction, we trap this buffer 5211da177e4SLinus Torvalds * inside the b_bdstrat callback so that this won't get written to 5221da177e4SLinus Torvalds * disk. 5231da177e4SLinus Torvalds */ 524b0388bf1SDave Chinner bp->b_flags |= XBF_DONE; 5251da177e4SLinus Torvalds 5261da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 527cb669ca5SChristoph Hellwig bp->b_iodone = xfs_buf_iodone_callbacks; 528ca30b2a7SChristoph Hellwig bip->bli_item.li_cb = xfs_buf_iodone; 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds /* 5311da177e4SLinus Torvalds * If we invalidated the buffer within this transaction, then 5321da177e4SLinus Torvalds * cancel the invalidation now that we're dirtying the buffer 5331da177e4SLinus Torvalds * again. There are no races with the code in xfs_buf_item_unpin(), 5341da177e4SLinus Torvalds * because we have a reference to the buffer this entire time. 5351da177e4SLinus Torvalds */ 5361da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 5371da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_STALE; 5385cfd28b6SDave Chinner ASSERT(bp->b_flags & XBF_STALE); 5395cfd28b6SDave Chinner bp->b_flags &= ~XBF_STALE; 5400f22f9d0SMark Tinguely bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL; 5411da177e4SLinus Torvalds } 5429684010dSBrian Foster bip->bli_flags |= XFS_BLI_DIRTY | XFS_BLI_LOGGED; 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 545e98c414fSChristoph Hellwig bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; 5469684010dSBrian Foster } 5479684010dSBrian Foster 5489684010dSBrian Foster /* 5499684010dSBrian Foster * This is called to mark bytes first through last inclusive of the given 5509684010dSBrian Foster * buffer as needing to be logged when the transaction is committed. 5519684010dSBrian Foster * The buffer must already be associated with the given transaction. 5529684010dSBrian Foster * 5539684010dSBrian Foster * First and last are numbers relative to the beginning of this buffer, 5549684010dSBrian Foster * so the first byte in the buffer is numbered 0 regardless of the 5559684010dSBrian Foster * value of b_blkno. 5569684010dSBrian Foster */ 5579684010dSBrian Foster void 5589684010dSBrian Foster xfs_trans_log_buf( 5599684010dSBrian Foster struct xfs_trans *tp, 5609684010dSBrian Foster struct xfs_buf *bp, 5619684010dSBrian Foster uint first, 5629684010dSBrian Foster uint last) 5639684010dSBrian Foster { 5649684010dSBrian Foster struct xfs_buf_log_item *bip = bp->b_fspriv; 5659684010dSBrian Foster 5669684010dSBrian Foster ASSERT(first <= last && last < BBTOB(bp->b_length)); 5678dc518dfSBrian Foster ASSERT(!(bip->bli_flags & XFS_BLI_ORDERED)); 5689684010dSBrian Foster 5699684010dSBrian Foster xfs_trans_dirty_buf(tp, bp); 5705f6bed76SDave Chinner 5719684010dSBrian Foster trace_xfs_trans_log_buf(bip); 5721da177e4SLinus Torvalds xfs_buf_item_log(bip, first, last); 5731da177e4SLinus Torvalds } 5741da177e4SLinus Torvalds 5751da177e4SLinus Torvalds 5761da177e4SLinus Torvalds /* 57743ff2122SChristoph Hellwig * Invalidate a buffer that is being used within a transaction. 5781da177e4SLinus Torvalds * 57943ff2122SChristoph Hellwig * Typically this is because the blocks in the buffer are being freed, so we 58043ff2122SChristoph Hellwig * need to prevent it from being written out when we're done. Allowing it 58143ff2122SChristoph Hellwig * to be written again might overwrite data in the free blocks if they are 58243ff2122SChristoph Hellwig * reallocated to a file. 58343ff2122SChristoph Hellwig * 58443ff2122SChristoph Hellwig * We prevent the buffer from being written out by marking it stale. We can't 58543ff2122SChristoph Hellwig * get rid of the buf log item at this point because the buffer may still be 58643ff2122SChristoph Hellwig * pinned by another transaction. If that is the case, then we'll wait until 58743ff2122SChristoph Hellwig * the buffer is committed to disk for the last time (we can tell by the ref 58843ff2122SChristoph Hellwig * count) and free it in xfs_buf_item_unpin(). Until that happens we will 58943ff2122SChristoph Hellwig * keep the buffer locked so that the buffer and buf log item are not reused. 59043ff2122SChristoph Hellwig * 59143ff2122SChristoph Hellwig * We also set the XFS_BLF_CANCEL flag in the buf log format structure and log 59243ff2122SChristoph Hellwig * the buf item. This will be used at recovery time to determine that copies 59343ff2122SChristoph Hellwig * of the buffer in the log before this should not be replayed. 59443ff2122SChristoph Hellwig * 59543ff2122SChristoph Hellwig * We mark the item descriptor and the transaction dirty so that we'll hold 59643ff2122SChristoph Hellwig * the buffer until after the commit. 59743ff2122SChristoph Hellwig * 59843ff2122SChristoph Hellwig * Since we're invalidating the buffer, we also clear the state about which 59943ff2122SChristoph Hellwig * parts of the buffer have been logged. We also clear the flag indicating 60043ff2122SChristoph Hellwig * that this is an inode buffer since the data in the buffer will no longer 60143ff2122SChristoph Hellwig * be valid. 60243ff2122SChristoph Hellwig * 60343ff2122SChristoph Hellwig * We set the stale bit in the buffer as well since we're getting rid of it. 6041da177e4SLinus Torvalds */ 6051da177e4SLinus Torvalds void 6061da177e4SLinus Torvalds xfs_trans_binval( 6071da177e4SLinus Torvalds xfs_trans_t *tp, 6081da177e4SLinus Torvalds xfs_buf_t *bp) 6091da177e4SLinus Torvalds { 610*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_fspriv; 61191e4bac0SMark Tinguely int i; 6121da177e4SLinus Torvalds 613bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 614adadbeefSChristoph Hellwig ASSERT(bip != NULL); 6151da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 6161da177e4SLinus Torvalds 6170b1b213fSChristoph Hellwig trace_xfs_trans_binval(bip); 6180b1b213fSChristoph Hellwig 6191da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 6201da177e4SLinus Torvalds /* 6211da177e4SLinus Torvalds * If the buffer is already invalidated, then 6221da177e4SLinus Torvalds * just return. 6231da177e4SLinus Torvalds */ 6245cfd28b6SDave Chinner ASSERT(bp->b_flags & XBF_STALE); 6251da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); 6260f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF)); 62761fe135cSDave Chinner ASSERT(!(bip->__bli_format.blf_flags & XFS_BLFT_MASK)); 6280f22f9d0SMark Tinguely ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); 629e98c414fSChristoph Hellwig ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY); 6301da177e4SLinus Torvalds ASSERT(tp->t_flags & XFS_TRANS_DIRTY); 6311da177e4SLinus Torvalds return; 6321da177e4SLinus Torvalds } 6331da177e4SLinus Torvalds 634c867cb61SChristoph Hellwig xfs_buf_stale(bp); 63543ff2122SChristoph Hellwig 6361da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE; 637ccf7c23fSDave Chinner bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); 6380f22f9d0SMark Tinguely bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; 6390f22f9d0SMark Tinguely bip->__bli_format.blf_flags |= XFS_BLF_CANCEL; 64061fe135cSDave Chinner bip->__bli_format.blf_flags &= ~XFS_BLFT_MASK; 64191e4bac0SMark Tinguely for (i = 0; i < bip->bli_format_count; i++) { 64291e4bac0SMark Tinguely memset(bip->bli_formats[i].blf_data_map, 0, 64391e4bac0SMark Tinguely (bip->bli_formats[i].blf_map_size * sizeof(uint))); 64491e4bac0SMark Tinguely } 645e98c414fSChristoph Hellwig bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY; 6461da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds 6491da177e4SLinus Torvalds /* 650ccf7c23fSDave Chinner * This call is used to indicate that the buffer contains on-disk inodes which 651ccf7c23fSDave Chinner * must be handled specially during recovery. They require special handling 652ccf7c23fSDave Chinner * because only the di_next_unlinked from the inodes in the buffer should be 653ccf7c23fSDave Chinner * recovered. The rest of the data in the buffer is logged via the inodes 654ccf7c23fSDave Chinner * themselves. 6551da177e4SLinus Torvalds * 656ccf7c23fSDave Chinner * All we do is set the XFS_BLI_INODE_BUF flag in the items flags so it can be 657ccf7c23fSDave Chinner * transferred to the buffer's log format structure so that we'll know what to 658ccf7c23fSDave Chinner * do at recovery time. 6591da177e4SLinus Torvalds */ 6601da177e4SLinus Torvalds void 6611da177e4SLinus Torvalds xfs_trans_inode_buf( 6621da177e4SLinus Torvalds xfs_trans_t *tp, 6631da177e4SLinus Torvalds xfs_buf_t *bp) 6641da177e4SLinus Torvalds { 665*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_fspriv; 6661da177e4SLinus Torvalds 667bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 668adadbeefSChristoph Hellwig ASSERT(bip != NULL); 6691da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 6701da177e4SLinus Torvalds 671ccf7c23fSDave Chinner bip->bli_flags |= XFS_BLI_INODE_BUF; 67261fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 6731da177e4SLinus Torvalds } 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds /* 6761da177e4SLinus Torvalds * This call is used to indicate that the buffer is going to 6771da177e4SLinus Torvalds * be staled and was an inode buffer. This means it gets 6781da177e4SLinus Torvalds * special processing during unpin - where any inodes 6791da177e4SLinus Torvalds * associated with the buffer should be removed from ail. 6801da177e4SLinus Torvalds * There is also special processing during recovery, 6811da177e4SLinus Torvalds * any replay of the inodes in the buffer needs to be 6821da177e4SLinus Torvalds * prevented as the buffer may have been reused. 6831da177e4SLinus Torvalds */ 6841da177e4SLinus Torvalds void 6851da177e4SLinus Torvalds xfs_trans_stale_inode_buf( 6861da177e4SLinus Torvalds xfs_trans_t *tp, 6871da177e4SLinus Torvalds xfs_buf_t *bp) 6881da177e4SLinus Torvalds { 689*70a20655SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_fspriv; 6901da177e4SLinus Torvalds 691bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 692adadbeefSChristoph Hellwig ASSERT(bip != NULL); 6931da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE_INODE; 696ca30b2a7SChristoph Hellwig bip->bli_item.li_cb = xfs_buf_iodone; 69761fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 6981da177e4SLinus Torvalds } 6991da177e4SLinus Torvalds 7001da177e4SLinus Torvalds /* 7011da177e4SLinus Torvalds * Mark the buffer as being one which contains newly allocated 7021da177e4SLinus Torvalds * inodes. We need to make sure that even if this buffer is 7031da177e4SLinus Torvalds * relogged as an 'inode buf' we still recover all of the inode 7041da177e4SLinus Torvalds * images in the face of a crash. This works in coordination with 7051da177e4SLinus Torvalds * xfs_buf_item_committed() to ensure that the buffer remains in the 7061da177e4SLinus Torvalds * AIL at its original location even after it has been relogged. 7071da177e4SLinus Torvalds */ 7081da177e4SLinus Torvalds /* ARGSUSED */ 7091da177e4SLinus Torvalds void 7101da177e4SLinus Torvalds xfs_trans_inode_alloc_buf( 7111da177e4SLinus Torvalds xfs_trans_t *tp, 7121da177e4SLinus Torvalds xfs_buf_t *bp) 7131da177e4SLinus Torvalds { 714*70a20655SCarlos Maiolino struct xfs_buf_log_item *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 7201da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; 72161fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 7221da177e4SLinus Torvalds } 7231da177e4SLinus Torvalds 724ee1a47abSChristoph Hellwig /* 7258dc518dfSBrian Foster * Mark the buffer as ordered for this transaction. This means that the contents 7268dc518dfSBrian Foster * of the buffer are not recorded in the transaction but it is tracked in the 7278dc518dfSBrian Foster * AIL as though it was. This allows us to record logical changes in 7288dc518dfSBrian Foster * transactions rather than the physical changes we make to the buffer without 7298dc518dfSBrian Foster * changing writeback ordering constraints of metadata buffers. 7305f6bed76SDave Chinner */ 731a5814bceSBrian Foster bool 7325f6bed76SDave Chinner xfs_trans_ordered_buf( 7335f6bed76SDave Chinner struct xfs_trans *tp, 7345f6bed76SDave Chinner struct xfs_buf *bp) 7355f6bed76SDave Chinner { 7365f6bed76SDave Chinner struct xfs_buf_log_item *bip = bp->b_fspriv; 7375f6bed76SDave Chinner 7385f6bed76SDave Chinner ASSERT(bp->b_transp == tp); 7395f6bed76SDave Chinner ASSERT(bip != NULL); 7405f6bed76SDave Chinner ASSERT(atomic_read(&bip->bli_refcount) > 0); 741a5814bceSBrian Foster 742a5814bceSBrian Foster if (xfs_buf_item_dirty_format(bip)) 743a5814bceSBrian Foster return false; 7445f6bed76SDave Chinner 7455f6bed76SDave Chinner bip->bli_flags |= XFS_BLI_ORDERED; 7465f6bed76SDave Chinner trace_xfs_buf_item_ordered(bip); 7478dc518dfSBrian Foster 7488dc518dfSBrian Foster /* 7498dc518dfSBrian Foster * We don't log a dirty range of an ordered buffer but it still needs 7508dc518dfSBrian Foster * to be marked dirty and that it has been logged. 7518dc518dfSBrian Foster */ 7528dc518dfSBrian Foster xfs_trans_dirty_buf(tp, bp); 753a5814bceSBrian Foster return true; 7545f6bed76SDave Chinner } 7555f6bed76SDave Chinner 7565f6bed76SDave Chinner /* 757ee1a47abSChristoph Hellwig * Set the type of the buffer for log recovery so that it can correctly identify 758ee1a47abSChristoph Hellwig * and hence attach the correct buffer ops to the buffer after replay. 759ee1a47abSChristoph Hellwig */ 760ee1a47abSChristoph Hellwig void 761ee1a47abSChristoph Hellwig xfs_trans_buf_set_type( 762ee1a47abSChristoph Hellwig struct xfs_trans *tp, 763ee1a47abSChristoph Hellwig struct xfs_buf *bp, 76461fe135cSDave Chinner enum xfs_blft type) 765ee1a47abSChristoph Hellwig { 766ee1a47abSChristoph Hellwig struct xfs_buf_log_item *bip = bp->b_fspriv; 767ee1a47abSChristoph Hellwig 768d75afeb3SDave Chinner if (!tp) 769d75afeb3SDave Chinner return; 770d75afeb3SDave Chinner 771ee1a47abSChristoph Hellwig ASSERT(bp->b_transp == tp); 772ee1a47abSChristoph Hellwig ASSERT(bip != NULL); 773ee1a47abSChristoph Hellwig ASSERT(atomic_read(&bip->bli_refcount) > 0); 774ee1a47abSChristoph Hellwig 77561fe135cSDave Chinner xfs_blft_to_flags(&bip->__bli_format, type); 776ee1a47abSChristoph Hellwig } 7771da177e4SLinus Torvalds 778d75afeb3SDave Chinner void 779d75afeb3SDave Chinner xfs_trans_buf_copy_type( 780d75afeb3SDave Chinner struct xfs_buf *dst_bp, 781d75afeb3SDave Chinner struct xfs_buf *src_bp) 782d75afeb3SDave Chinner { 783d75afeb3SDave Chinner struct xfs_buf_log_item *sbip = src_bp->b_fspriv; 784d75afeb3SDave Chinner struct xfs_buf_log_item *dbip = dst_bp->b_fspriv; 78561fe135cSDave Chinner enum xfs_blft type; 786d75afeb3SDave Chinner 78761fe135cSDave Chinner type = xfs_blft_from_flags(&sbip->__bli_format); 78861fe135cSDave Chinner xfs_blft_to_flags(&dbip->__bli_format, type); 789d75afeb3SDave Chinner } 790d75afeb3SDave Chinner 7911da177e4SLinus Torvalds /* 7921da177e4SLinus Torvalds * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of 7931da177e4SLinus Torvalds * dquots. However, unlike in inode buffer recovery, dquot buffers get 7941da177e4SLinus Torvalds * recovered in their entirety. (Hence, no XFS_BLI_DQUOT_ALLOC_BUF flag). 7951da177e4SLinus Torvalds * The only thing that makes dquot buffers different from regular 7961da177e4SLinus Torvalds * buffers is that we must not replay dquot bufs when recovering 7971da177e4SLinus Torvalds * if a _corresponding_ quotaoff has happened. We also have to distinguish 7981da177e4SLinus Torvalds * between usr dquot bufs and grp dquot bufs, because usr and grp quotas 7991da177e4SLinus Torvalds * can be turned off independently. 8001da177e4SLinus Torvalds */ 8011da177e4SLinus Torvalds /* ARGSUSED */ 8021da177e4SLinus Torvalds void 8031da177e4SLinus Torvalds xfs_trans_dquot_buf( 8041da177e4SLinus Torvalds xfs_trans_t *tp, 8051da177e4SLinus Torvalds xfs_buf_t *bp, 8061da177e4SLinus Torvalds uint type) 8071da177e4SLinus Torvalds { 80861fe135cSDave Chinner struct xfs_buf_log_item *bip = bp->b_fspriv; 80961fe135cSDave Chinner 810c1155410SDave Chinner ASSERT(type == XFS_BLF_UDQUOT_BUF || 811c1155410SDave Chinner type == XFS_BLF_PDQUOT_BUF || 812c1155410SDave Chinner type == XFS_BLF_GDQUOT_BUF); 8131da177e4SLinus Torvalds 81461fe135cSDave Chinner bip->__bli_format.blf_flags |= type; 81561fe135cSDave Chinner 81661fe135cSDave Chinner switch (type) { 81761fe135cSDave Chinner case XFS_BLF_UDQUOT_BUF: 81861fe135cSDave Chinner type = XFS_BLFT_UDQUOT_BUF; 81961fe135cSDave Chinner break; 82061fe135cSDave Chinner case XFS_BLF_PDQUOT_BUF: 82161fe135cSDave Chinner type = XFS_BLFT_PDQUOT_BUF; 82261fe135cSDave Chinner break; 82361fe135cSDave Chinner case XFS_BLF_GDQUOT_BUF: 82461fe135cSDave Chinner type = XFS_BLFT_GDQUOT_BUF; 82561fe135cSDave Chinner break; 82661fe135cSDave Chinner default: 82761fe135cSDave Chinner type = XFS_BLFT_UNKNOWN_BUF; 82861fe135cSDave Chinner break; 82961fe135cSDave Chinner } 83061fe135cSDave Chinner 831ee1a47abSChristoph Hellwig xfs_trans_buf_set_type(tp, bp, type); 8321da177e4SLinus Torvalds } 833