10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* 37b718769SNathan Scott * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 47b718769SNathan Scott * All Rights Reserved. 51da177e4SLinus Torvalds */ 61da177e4SLinus Torvalds #include "xfs.h" 7a844f451SNathan Scott #include "xfs_fs.h" 870a9883cSDave Chinner #include "xfs_shared.h" 9a4fbe6abSDave Chinner #include "xfs_format.h" 10239880efSDave Chinner #include "xfs_log_format.h" 11239880efSDave Chinner #include "xfs_trans_resv.h" 121da177e4SLinus Torvalds #include "xfs_mount.h" 13239880efSDave Chinner #include "xfs_trans.h" 14a844f451SNathan Scott #include "xfs_buf_item.h" 151da177e4SLinus Torvalds #include "xfs_trans_priv.h" 160b1b213fSChristoph Hellwig #include "xfs_trace.h" 171da177e4SLinus Torvalds 184a5224d7SChristoph Hellwig /* 194a5224d7SChristoph Hellwig * Check to see if a buffer matching the given parameters is already 204a5224d7SChristoph Hellwig * a part of the given transaction. 214a5224d7SChristoph Hellwig */ 224a5224d7SChristoph Hellwig STATIC struct xfs_buf * 234a5224d7SChristoph Hellwig xfs_trans_buf_item_match( 244a5224d7SChristoph Hellwig struct xfs_trans *tp, 254a5224d7SChristoph Hellwig struct xfs_buftarg *target, 26de2a4f59SDave Chinner struct xfs_buf_map *map, 27de2a4f59SDave Chinner int nmaps) 284a5224d7SChristoph Hellwig { 29e6631f85SDave Chinner struct xfs_log_item *lip; 30e98c414fSChristoph Hellwig struct xfs_buf_log_item *blip; 31de2a4f59SDave Chinner int len = 0; 32de2a4f59SDave Chinner int i; 331da177e4SLinus Torvalds 34de2a4f59SDave Chinner for (i = 0; i < nmaps; i++) 35de2a4f59SDave Chinner len += map[i].bm_len; 36de2a4f59SDave Chinner 37e6631f85SDave Chinner list_for_each_entry(lip, &tp->t_items, li_trans) { 38e6631f85SDave Chinner blip = (struct xfs_buf_log_item *)lip; 39e98c414fSChristoph Hellwig if (blip->bli_item.li_type == XFS_LI_BUF && 4049074c06SChandra Seetharaman blip->bli_buf->b_target == target && 41de2a4f59SDave Chinner XFS_BUF_ADDR(blip->bli_buf) == map[0].bm_bn && 42de2a4f59SDave Chinner blip->bli_buf->b_length == len) { 43de2a4f59SDave Chinner ASSERT(blip->bli_buf->b_map_count == nmaps); 444a5224d7SChristoph Hellwig return blip->bli_buf; 454a5224d7SChristoph Hellwig } 46de2a4f59SDave Chinner } 474a5224d7SChristoph Hellwig 484a5224d7SChristoph Hellwig return NULL; 494a5224d7SChristoph Hellwig } 501da177e4SLinus Torvalds 51d7e84f41SChristoph Hellwig /* 52d7e84f41SChristoph Hellwig * Add the locked buffer to the transaction. 53d7e84f41SChristoph Hellwig * 54d7e84f41SChristoph Hellwig * The buffer must be locked, and it cannot be associated with any 55d7e84f41SChristoph Hellwig * transaction. 56d7e84f41SChristoph Hellwig * 57d7e84f41SChristoph Hellwig * If the buffer does not yet have a buf log item associated with it, 58d7e84f41SChristoph Hellwig * then allocate one for it. Then add the buf item to the transaction. 59d7e84f41SChristoph Hellwig */ 60d7e84f41SChristoph Hellwig STATIC void 61d7e84f41SChristoph Hellwig _xfs_trans_bjoin( 62d7e84f41SChristoph Hellwig struct xfs_trans *tp, 63d7e84f41SChristoph Hellwig struct xfs_buf *bp, 64d7e84f41SChristoph Hellwig int reset_recur) 65d7e84f41SChristoph Hellwig { 66d7e84f41SChristoph Hellwig struct xfs_buf_log_item *bip; 67d7e84f41SChristoph Hellwig 68bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == NULL); 69d7e84f41SChristoph Hellwig 70d7e84f41SChristoph Hellwig /* 71fb1755a6SCarlos Maiolino * The xfs_buf_log_item pointer is stored in b_log_item. If 72d7e84f41SChristoph Hellwig * it doesn't have one yet, then allocate one and initialize it. 73d7e84f41SChristoph Hellwig * The checks to see if one is there are in xfs_buf_item_init(). 74d7e84f41SChristoph Hellwig */ 75d7e84f41SChristoph Hellwig xfs_buf_item_init(bp, tp->t_mountp); 76fb1755a6SCarlos Maiolino bip = bp->b_log_item; 77d7e84f41SChristoph Hellwig ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 780f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 79d7e84f41SChristoph Hellwig ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 80d7e84f41SChristoph Hellwig if (reset_recur) 81d7e84f41SChristoph Hellwig bip->bli_recur = 0; 82d7e84f41SChristoph Hellwig 83d7e84f41SChristoph Hellwig /* 84d7e84f41SChristoph Hellwig * Take a reference for this transaction on the buf item. 85d7e84f41SChristoph Hellwig */ 86d7e84f41SChristoph Hellwig atomic_inc(&bip->bli_refcount); 87d7e84f41SChristoph Hellwig 88d7e84f41SChristoph Hellwig /* 89e6631f85SDave Chinner * Attach the item to the transaction so we can find it in 90e6631f85SDave Chinner * xfs_trans_get_buf() and friends. 91d7e84f41SChristoph Hellwig */ 92e98c414fSChristoph Hellwig xfs_trans_add_item(tp, &bip->bli_item); 93bf9d9013SChristoph Hellwig bp->b_transp = tp; 94d7e84f41SChristoph Hellwig 95d7e84f41SChristoph Hellwig } 96d7e84f41SChristoph Hellwig 97d7e84f41SChristoph Hellwig void 98d7e84f41SChristoph Hellwig xfs_trans_bjoin( 99d7e84f41SChristoph Hellwig struct xfs_trans *tp, 100d7e84f41SChristoph Hellwig struct xfs_buf *bp) 101d7e84f41SChristoph Hellwig { 102d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 0); 103fb1755a6SCarlos Maiolino trace_xfs_trans_bjoin(bp->b_log_item); 104d7e84f41SChristoph Hellwig } 1051da177e4SLinus Torvalds 1061da177e4SLinus Torvalds /* 1071da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 1081da177e4SLinus Torvalds * locked within the given transaction. If it is already locked 1091da177e4SLinus Torvalds * within the transaction, just increment its lock recursion count 1101da177e4SLinus Torvalds * and return a pointer to it. 1111da177e4SLinus Torvalds * 1121da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 1131da177e4SLinus Torvalds * get_buf() call. 1141da177e4SLinus Torvalds */ 115*9676b54eSDarrick J. Wong int 116de2a4f59SDave Chinner xfs_trans_get_buf_map( 117de2a4f59SDave Chinner struct xfs_trans *tp, 118de2a4f59SDave Chinner struct xfs_buftarg *target, 119de2a4f59SDave Chinner struct xfs_buf_map *map, 120de2a4f59SDave Chinner int nmaps, 121*9676b54eSDarrick J. Wong xfs_buf_flags_t flags, 122*9676b54eSDarrick J. Wong struct xfs_buf **bpp) 1231da177e4SLinus Torvalds { 1241da177e4SLinus Torvalds xfs_buf_t *bp; 12570a20655SCarlos Maiolino struct xfs_buf_log_item *bip; 1263848b5f6SDarrick J. Wong int error; 1271da177e4SLinus Torvalds 128*9676b54eSDarrick J. Wong *bpp = NULL; 129*9676b54eSDarrick J. Wong if (!tp) 130*9676b54eSDarrick J. Wong return xfs_buf_get_map(target, map, nmaps, flags, bpp); 1311da177e4SLinus Torvalds 1321da177e4SLinus Torvalds /* 1331da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 1341da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 1351da177e4SLinus Torvalds * have it locked. In this case we just increment the lock 1361da177e4SLinus Torvalds * recursion count and return the buffer to the caller. 1371da177e4SLinus Torvalds */ 138de2a4f59SDave Chinner bp = xfs_trans_buf_item_match(tp, target, map, nmaps); 1391da177e4SLinus Torvalds if (bp != NULL) { 1400c842ad4SChristoph Hellwig ASSERT(xfs_buf_islocked(bp)); 141c867cb61SChristoph Hellwig if (XFS_FORCED_SHUTDOWN(tp->t_mountp)) { 142c867cb61SChristoph Hellwig xfs_buf_stale(bp); 143b0388bf1SDave Chinner bp->b_flags |= XBF_DONE; 144c867cb61SChristoph Hellwig } 1450b1b213fSChristoph Hellwig 146bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 147fb1755a6SCarlos Maiolino bip = bp->b_log_item; 1481da177e4SLinus Torvalds ASSERT(bip != NULL); 1491da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 1501da177e4SLinus Torvalds bip->bli_recur++; 1510b1b213fSChristoph Hellwig trace_xfs_trans_get_buf_recur(bip); 152*9676b54eSDarrick J. Wong *bpp = bp; 153*9676b54eSDarrick J. Wong return 0; 1541da177e4SLinus Torvalds } 1551da177e4SLinus Torvalds 1563848b5f6SDarrick J. Wong error = xfs_buf_get_map(target, map, nmaps, flags, &bp); 1573848b5f6SDarrick J. Wong if (error) 158*9676b54eSDarrick J. Wong return error; 1591da177e4SLinus Torvalds 1605a52c2a5SChandra Seetharaman ASSERT(!bp->b_error); 1611da177e4SLinus Torvalds 162d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 163fb1755a6SCarlos Maiolino trace_xfs_trans_get_buf(bp->b_log_item); 164*9676b54eSDarrick J. Wong *bpp = bp; 165*9676b54eSDarrick J. Wong return 0; 1661da177e4SLinus Torvalds } 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds /* 1691da177e4SLinus Torvalds * Get and lock the superblock buffer of this file system for the 1701da177e4SLinus Torvalds * given transaction. 1711da177e4SLinus Torvalds * 1721da177e4SLinus Torvalds * We don't need to use incore_match() here, because the superblock 1731da177e4SLinus Torvalds * buffer is a private buffer which we keep a pointer to in the 1741da177e4SLinus Torvalds * mount structure. 1751da177e4SLinus Torvalds */ 1761da177e4SLinus Torvalds xfs_buf_t * 17770a20655SCarlos Maiolino xfs_trans_getsb( 17870a20655SCarlos Maiolino xfs_trans_t *tp, 1798c9ce2f7SEric Sandeen struct xfs_mount *mp) 1801da177e4SLinus Torvalds { 1811da177e4SLinus Torvalds xfs_buf_t *bp; 18270a20655SCarlos Maiolino struct xfs_buf_log_item *bip; 1831da177e4SLinus Torvalds 1841da177e4SLinus Torvalds /* 1851da177e4SLinus Torvalds * Default to just trying to lock the superblock buffer 1861da177e4SLinus Torvalds * if tp is NULL. 1871da177e4SLinus Torvalds */ 188d99831ffSEric Sandeen if (tp == NULL) 1898c9ce2f7SEric Sandeen return xfs_getsb(mp); 1901da177e4SLinus Torvalds 1911da177e4SLinus Torvalds /* 1921da177e4SLinus Torvalds * If the superblock buffer already has this transaction 1931da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 1941da177e4SLinus Torvalds * have it locked. In this case we just increment the lock 1951da177e4SLinus Torvalds * recursion count and return the buffer to the caller. 1961da177e4SLinus Torvalds */ 1971da177e4SLinus Torvalds bp = mp->m_sb_bp; 198bf9d9013SChristoph Hellwig if (bp->b_transp == tp) { 199fb1755a6SCarlos Maiolino bip = bp->b_log_item; 2001da177e4SLinus Torvalds ASSERT(bip != NULL); 2011da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 2021da177e4SLinus Torvalds bip->bli_recur++; 2030b1b213fSChristoph Hellwig trace_xfs_trans_getsb_recur(bip); 204d99831ffSEric Sandeen return bp; 2051da177e4SLinus Torvalds } 2061da177e4SLinus Torvalds 2078c9ce2f7SEric Sandeen bp = xfs_getsb(mp); 208d7e84f41SChristoph Hellwig if (bp == NULL) 2091da177e4SLinus Torvalds return NULL; 2101da177e4SLinus Torvalds 211d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 212fb1755a6SCarlos Maiolino trace_xfs_trans_getsb(bp->b_log_item); 213d99831ffSEric Sandeen return bp; 2141da177e4SLinus Torvalds } 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds /* 2171da177e4SLinus Torvalds * Get and lock the buffer for the caller if it is not already 2181da177e4SLinus Torvalds * locked within the given transaction. If it has not yet been 2191da177e4SLinus Torvalds * read in, read it from disk. If it is already locked 2201da177e4SLinus Torvalds * within the transaction and already read in, just increment its 2211da177e4SLinus Torvalds * lock recursion count and return a pointer to it. 2221da177e4SLinus Torvalds * 2231da177e4SLinus Torvalds * If the transaction pointer is NULL, make this just a normal 2241da177e4SLinus Torvalds * read_buf() call. 2251da177e4SLinus Torvalds */ 2261da177e4SLinus Torvalds int 227de2a4f59SDave Chinner xfs_trans_read_buf_map( 228de2a4f59SDave Chinner struct xfs_mount *mp, 229de2a4f59SDave Chinner struct xfs_trans *tp, 230de2a4f59SDave Chinner struct xfs_buftarg *target, 231de2a4f59SDave Chinner struct xfs_buf_map *map, 232de2a4f59SDave Chinner int nmaps, 233de2a4f59SDave Chinner xfs_buf_flags_t flags, 234c3f8fc73SDave Chinner struct xfs_buf **bpp, 2351813dd64SDave Chinner const struct xfs_buf_ops *ops) 2361da177e4SLinus Torvalds { 2372d3d0c53SDave Chinner struct xfs_buf *bp = NULL; 2382d3d0c53SDave Chinner struct xfs_buf_log_item *bip; 2391da177e4SLinus Torvalds int error; 2401da177e4SLinus Torvalds 2417ca790a5SDave Chinner *bpp = NULL; 2421da177e4SLinus Torvalds /* 2431da177e4SLinus Torvalds * If we find the buffer in the cache with this transaction 2441da177e4SLinus Torvalds * pointer in its b_fsprivate2 field, then we know we already 2451da177e4SLinus Torvalds * have it locked. If it is already read in we just increment 2461da177e4SLinus Torvalds * the lock recursion count and return the buffer to the caller. 2471da177e4SLinus Torvalds * If the buffer is not yet read in, then we read it in, increment 2481da177e4SLinus Torvalds * the lock recursion count, and return it to the caller. 2491da177e4SLinus Torvalds */ 2502d3d0c53SDave Chinner if (tp) 251de2a4f59SDave Chinner bp = xfs_trans_buf_item_match(tp, target, map, nmaps); 2522d3d0c53SDave Chinner if (bp) { 2530c842ad4SChristoph Hellwig ASSERT(xfs_buf_islocked(bp)); 254bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 255fb1755a6SCarlos Maiolino ASSERT(bp->b_log_item != NULL); 2565a52c2a5SChandra Seetharaman ASSERT(!bp->b_error); 2572d3d0c53SDave Chinner ASSERT(bp->b_flags & XBF_DONE); 25883a0adc3SChristoph Hellwig 2591da177e4SLinus Torvalds /* 2601da177e4SLinus Torvalds * We never locked this buf ourselves, so we shouldn't 2611da177e4SLinus Torvalds * brelse it either. Just get out. 2621da177e4SLinus Torvalds */ 2631da177e4SLinus Torvalds if (XFS_FORCED_SHUTDOWN(mp)) { 2640b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_shut(bp, _RET_IP_); 2652451337dSDave Chinner return -EIO; 2661da177e4SLinus Torvalds } 2671da177e4SLinus Torvalds 2681aff5696SDarrick J. Wong /* 2691aff5696SDarrick J. Wong * Check if the caller is trying to read a buffer that is 2701aff5696SDarrick J. Wong * already attached to the transaction yet has no buffer ops 2711aff5696SDarrick J. Wong * assigned. Ops are usually attached when the buffer is 2721aff5696SDarrick J. Wong * attached to the transaction, or by the read caller if 2731aff5696SDarrick J. Wong * special circumstances. That didn't happen, which is not 2741aff5696SDarrick J. Wong * how this is supposed to go. 2751aff5696SDarrick J. Wong * 2761aff5696SDarrick J. Wong * If the buffer passes verification we'll let this go, but if 2771aff5696SDarrick J. Wong * not we have to shut down. Let the transaction cleanup code 2781aff5696SDarrick J. Wong * release this buffer when it kills the tranaction. 2791aff5696SDarrick J. Wong */ 2801aff5696SDarrick J. Wong ASSERT(bp->b_ops != NULL); 28175d02303SBrian Foster error = xfs_buf_reverify(bp, ops); 2821aff5696SDarrick J. Wong if (error) { 2831aff5696SDarrick J. Wong xfs_buf_ioerror_alert(bp, __func__); 2841aff5696SDarrick J. Wong 2851aff5696SDarrick J. Wong if (tp->t_flags & XFS_TRANS_DIRTY) 2861aff5696SDarrick J. Wong xfs_force_shutdown(tp->t_mountp, 2871aff5696SDarrick J. Wong SHUTDOWN_META_IO_ERROR); 2881aff5696SDarrick J. Wong 2891aff5696SDarrick J. Wong /* bad CRC means corrupted metadata */ 2901aff5696SDarrick J. Wong if (error == -EFSBADCRC) 2911aff5696SDarrick J. Wong error = -EFSCORRUPTED; 2921aff5696SDarrick J. Wong return error; 2931aff5696SDarrick J. Wong } 2941aff5696SDarrick J. Wong 295fb1755a6SCarlos Maiolino bip = bp->b_log_item; 2961da177e4SLinus Torvalds bip->bli_recur++; 2971da177e4SLinus Torvalds 2981da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 2990b1b213fSChristoph Hellwig trace_xfs_trans_read_buf_recur(bip); 3001aff5696SDarrick J. Wong ASSERT(bp->b_ops != NULL || ops == NULL); 3011da177e4SLinus Torvalds *bpp = bp; 3021da177e4SLinus Torvalds return 0; 3031da177e4SLinus Torvalds } 3041da177e4SLinus Torvalds 3054ed8e27bSDarrick J. Wong error = xfs_buf_read_map(target, map, nmaps, flags, &bp, ops); 3064ed8e27bSDarrick J. Wong switch (error) { 3074ed8e27bSDarrick J. Wong case 0: 3084ed8e27bSDarrick J. Wong break; 3094ed8e27bSDarrick J. Wong default: 3102d3d0c53SDave Chinner if (tp && (tp->t_flags & XFS_TRANS_DIRTY)) 3117d04a335SNathan Scott xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); 3124ed8e27bSDarrick J. Wong /* fall through */ 3134ed8e27bSDarrick J. Wong case -ENOMEM: 3144ed8e27bSDarrick J. Wong case -EAGAIN: 3151da177e4SLinus Torvalds return error; 3161da177e4SLinus Torvalds } 3172d3d0c53SDave Chinner 3182d3d0c53SDave Chinner if (XFS_FORCED_SHUTDOWN(mp)) { 3191da177e4SLinus Torvalds xfs_buf_relse(bp); 3202d3d0c53SDave Chinner trace_xfs_trans_read_buf_shut(bp, _RET_IP_); 3212451337dSDave Chinner return -EIO; 3221da177e4SLinus Torvalds } 3231da177e4SLinus Torvalds 324e9892d3cSDave Chinner if (tp) { 325d7e84f41SChristoph Hellwig _xfs_trans_bjoin(tp, bp, 1); 326fb1755a6SCarlos Maiolino trace_xfs_trans_read_buf(bp->b_log_item); 327e9892d3cSDave Chinner } 3281aff5696SDarrick J. Wong ASSERT(bp->b_ops != NULL || ops == NULL); 3291da177e4SLinus Torvalds *bpp = bp; 3301da177e4SLinus Torvalds return 0; 3311da177e4SLinus Torvalds 3321da177e4SLinus Torvalds } 3331da177e4SLinus Torvalds 33438b6238eSDarrick J. Wong /* Has this buffer been dirtied by anyone? */ 33538b6238eSDarrick J. Wong bool 33638b6238eSDarrick J. Wong xfs_trans_buf_is_dirty( 33738b6238eSDarrick J. Wong struct xfs_buf *bp) 33838b6238eSDarrick J. Wong { 33938b6238eSDarrick J. Wong struct xfs_buf_log_item *bip = bp->b_log_item; 34038b6238eSDarrick J. Wong 34138b6238eSDarrick J. Wong if (!bip) 34238b6238eSDarrick J. Wong return false; 34338b6238eSDarrick J. Wong ASSERT(bip->bli_item.li_type == XFS_LI_BUF); 34438b6238eSDarrick J. Wong return test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags); 34538b6238eSDarrick J. Wong } 34638b6238eSDarrick J. Wong 3471da177e4SLinus Torvalds /* 34823420d05SBrian Foster * Release a buffer previously joined to the transaction. If the buffer is 34923420d05SBrian Foster * modified within this transaction, decrement the recursion count but do not 35023420d05SBrian Foster * release the buffer even if the count goes to 0. If the buffer is not modified 35123420d05SBrian Foster * within the transaction, decrement the recursion count and release the buffer 35223420d05SBrian Foster * if the recursion count goes to 0. 3531da177e4SLinus Torvalds * 35423420d05SBrian Foster * If the buffer is to be released and it was not already dirty before this 35523420d05SBrian Foster * transaction began, then also free the buf_log_item associated with it. 3561da177e4SLinus Torvalds * 35723420d05SBrian Foster * If the transaction pointer is NULL, this is a normal xfs_buf_relse() call. 3581da177e4SLinus Torvalds */ 3591da177e4SLinus Torvalds void 36070a20655SCarlos Maiolino xfs_trans_brelse( 36123420d05SBrian Foster struct xfs_trans *tp, 36223420d05SBrian Foster struct xfs_buf *bp) 3631da177e4SLinus Torvalds { 36423420d05SBrian Foster struct xfs_buf_log_item *bip = bp->b_log_item; 3651da177e4SLinus Torvalds 36623420d05SBrian Foster ASSERT(bp->b_transp == tp); 36723420d05SBrian Foster 36823420d05SBrian Foster if (!tp) { 3691da177e4SLinus Torvalds xfs_buf_relse(bp); 3701da177e4SLinus Torvalds return; 3711da177e4SLinus Torvalds } 3721da177e4SLinus Torvalds 37323420d05SBrian Foster trace_xfs_trans_brelse(bip); 3741da177e4SLinus Torvalds ASSERT(bip->bli_item.li_type == XFS_LI_BUF); 3751da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 3761da177e4SLinus Torvalds 3771da177e4SLinus Torvalds /* 37823420d05SBrian Foster * If the release is for a recursive lookup, then decrement the count 37923420d05SBrian Foster * and return. 3801da177e4SLinus Torvalds */ 3811da177e4SLinus Torvalds if (bip->bli_recur > 0) { 3821da177e4SLinus Torvalds bip->bli_recur--; 3831da177e4SLinus Torvalds return; 3841da177e4SLinus Torvalds } 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds /* 38723420d05SBrian Foster * If the buffer is invalidated or dirty in this transaction, we can't 3881da177e4SLinus Torvalds * release it until we commit. 3891da177e4SLinus Torvalds */ 390e6631f85SDave Chinner if (test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags)) 3911da177e4SLinus Torvalds return; 3920b1b213fSChristoph Hellwig if (bip->bli_flags & XFS_BLI_STALE) 3931da177e4SLinus Torvalds return; 3941da177e4SLinus Torvalds 39523420d05SBrian Foster /* 39623420d05SBrian Foster * Unlink the log item from the transaction and clear the hold flag, if 39723420d05SBrian Foster * set. We wouldn't want the next user of the buffer to get confused. 39823420d05SBrian Foster */ 3991da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED)); 400e98c414fSChristoph Hellwig xfs_trans_del_item(&bip->bli_item); 4011da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_HOLD; 4021da177e4SLinus Torvalds 40395808459SBrian Foster /* drop the reference to the bli */ 40495808459SBrian Foster xfs_buf_item_put(bip); 4055b03ff1bSChristoph Hellwig 406bf9d9013SChristoph Hellwig bp->b_transp = NULL; 4071da177e4SLinus Torvalds xfs_buf_relse(bp); 4081da177e4SLinus Torvalds } 4091da177e4SLinus Torvalds 4101da177e4SLinus Torvalds /* 4111da177e4SLinus Torvalds * Mark the buffer as not needing to be unlocked when the buf item's 412ddf92053SChristoph Hellwig * iop_committing() routine is called. The buffer must already be locked 4131da177e4SLinus Torvalds * and associated with the given transaction. 4141da177e4SLinus Torvalds */ 4151da177e4SLinus Torvalds /* ARGSUSED */ 4161da177e4SLinus Torvalds void 41770a20655SCarlos Maiolino xfs_trans_bhold( 41870a20655SCarlos Maiolino xfs_trans_t *tp, 4191da177e4SLinus Torvalds xfs_buf_t *bp) 4201da177e4SLinus Torvalds { 421fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 4221da177e4SLinus Torvalds 423bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 424adadbeefSChristoph Hellwig ASSERT(bip != NULL); 4251da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 4260f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 4271da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 428adadbeefSChristoph Hellwig 4291da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_HOLD; 4300b1b213fSChristoph Hellwig trace_xfs_trans_bhold(bip); 4311da177e4SLinus Torvalds } 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds /* 434efa092f3STim Shimmin * Cancel the previous buffer hold request made on this buffer 435efa092f3STim Shimmin * for this transaction. 436efa092f3STim Shimmin */ 437efa092f3STim Shimmin void 43870a20655SCarlos Maiolino xfs_trans_bhold_release( 43970a20655SCarlos Maiolino xfs_trans_t *tp, 440efa092f3STim Shimmin xfs_buf_t *bp) 441efa092f3STim Shimmin { 442fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 443efa092f3STim Shimmin 444bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 445adadbeefSChristoph Hellwig ASSERT(bip != NULL); 446efa092f3STim Shimmin ASSERT(!(bip->bli_flags & XFS_BLI_STALE)); 4470f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL)); 448efa092f3STim Shimmin ASSERT(atomic_read(&bip->bli_refcount) > 0); 449efa092f3STim Shimmin ASSERT(bip->bli_flags & XFS_BLI_HOLD); 4500b1b213fSChristoph Hellwig 451adadbeefSChristoph Hellwig bip->bli_flags &= ~XFS_BLI_HOLD; 4520b1b213fSChristoph Hellwig trace_xfs_trans_bhold_release(bip); 453efa092f3STim Shimmin } 454efa092f3STim Shimmin 455efa092f3STim Shimmin /* 4569684010dSBrian Foster * Mark a buffer dirty in the transaction. 4571da177e4SLinus Torvalds */ 4581da177e4SLinus Torvalds void 4599684010dSBrian Foster xfs_trans_dirty_buf( 4609684010dSBrian Foster struct xfs_trans *tp, 4619684010dSBrian Foster struct xfs_buf *bp) 4621da177e4SLinus Torvalds { 463fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 4641da177e4SLinus Torvalds 465bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 466adadbeefSChristoph Hellwig ASSERT(bip != NULL); 467cb669ca5SChristoph Hellwig ASSERT(bp->b_iodone == NULL || 468cb669ca5SChristoph Hellwig bp->b_iodone == xfs_buf_iodone_callbacks); 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds /* 4711da177e4SLinus Torvalds * Mark the buffer as needing to be written out eventually, 4721da177e4SLinus Torvalds * and set its iodone function to remove the buffer's buf log 4731da177e4SLinus Torvalds * item from the AIL and free it when the buffer is flushed 4741da177e4SLinus Torvalds * to disk. See xfs_buf_attach_iodone() for more details 4751da177e4SLinus Torvalds * on li_cb and xfs_buf_iodone_callbacks(). 4761da177e4SLinus Torvalds * If we end up aborting this transaction, we trap this buffer 4771da177e4SLinus Torvalds * inside the b_bdstrat callback so that this won't get written to 4781da177e4SLinus Torvalds * disk. 4791da177e4SLinus Torvalds */ 480b0388bf1SDave Chinner bp->b_flags |= XBF_DONE; 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 483cb669ca5SChristoph Hellwig bp->b_iodone = xfs_buf_iodone_callbacks; 484ca30b2a7SChristoph Hellwig bip->bli_item.li_cb = xfs_buf_iodone; 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds /* 4871da177e4SLinus Torvalds * If we invalidated the buffer within this transaction, then 4881da177e4SLinus Torvalds * cancel the invalidation now that we're dirtying the buffer 4891da177e4SLinus Torvalds * again. There are no races with the code in xfs_buf_item_unpin(), 4901da177e4SLinus Torvalds * because we have a reference to the buffer this entire time. 4911da177e4SLinus Torvalds */ 4921da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 4931da177e4SLinus Torvalds bip->bli_flags &= ~XFS_BLI_STALE; 4945cfd28b6SDave Chinner ASSERT(bp->b_flags & XBF_STALE); 4955cfd28b6SDave Chinner bp->b_flags &= ~XBF_STALE; 4960f22f9d0SMark Tinguely bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL; 4971da177e4SLinus Torvalds } 4989684010dSBrian Foster bip->bli_flags |= XFS_BLI_DIRTY | XFS_BLI_LOGGED; 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 501e6631f85SDave Chinner set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags); 5029684010dSBrian Foster } 5039684010dSBrian Foster 5049684010dSBrian Foster /* 5059684010dSBrian Foster * This is called to mark bytes first through last inclusive of the given 5069684010dSBrian Foster * buffer as needing to be logged when the transaction is committed. 5079684010dSBrian Foster * The buffer must already be associated with the given transaction. 5089684010dSBrian Foster * 5099684010dSBrian Foster * First and last are numbers relative to the beginning of this buffer, 5109684010dSBrian Foster * so the first byte in the buffer is numbered 0 regardless of the 5119684010dSBrian Foster * value of b_blkno. 5129684010dSBrian Foster */ 5139684010dSBrian Foster void 5149684010dSBrian Foster xfs_trans_log_buf( 5159684010dSBrian Foster struct xfs_trans *tp, 5169684010dSBrian Foster struct xfs_buf *bp, 5179684010dSBrian Foster uint first, 5189684010dSBrian Foster uint last) 5199684010dSBrian Foster { 520fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 5219684010dSBrian Foster 5229684010dSBrian Foster ASSERT(first <= last && last < BBTOB(bp->b_length)); 5238dc518dfSBrian Foster ASSERT(!(bip->bli_flags & XFS_BLI_ORDERED)); 5249684010dSBrian Foster 5259684010dSBrian Foster xfs_trans_dirty_buf(tp, bp); 5265f6bed76SDave Chinner 5279684010dSBrian Foster trace_xfs_trans_log_buf(bip); 5281da177e4SLinus Torvalds xfs_buf_item_log(bip, first, last); 5291da177e4SLinus Torvalds } 5301da177e4SLinus Torvalds 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds /* 53343ff2122SChristoph Hellwig * Invalidate a buffer that is being used within a transaction. 5341da177e4SLinus Torvalds * 53543ff2122SChristoph Hellwig * Typically this is because the blocks in the buffer are being freed, so we 53643ff2122SChristoph Hellwig * need to prevent it from being written out when we're done. Allowing it 53743ff2122SChristoph Hellwig * to be written again might overwrite data in the free blocks if they are 53843ff2122SChristoph Hellwig * reallocated to a file. 53943ff2122SChristoph Hellwig * 54043ff2122SChristoph Hellwig * We prevent the buffer from being written out by marking it stale. We can't 54143ff2122SChristoph Hellwig * get rid of the buf log item at this point because the buffer may still be 54243ff2122SChristoph Hellwig * pinned by another transaction. If that is the case, then we'll wait until 54343ff2122SChristoph Hellwig * the buffer is committed to disk for the last time (we can tell by the ref 54443ff2122SChristoph Hellwig * count) and free it in xfs_buf_item_unpin(). Until that happens we will 54543ff2122SChristoph Hellwig * keep the buffer locked so that the buffer and buf log item are not reused. 54643ff2122SChristoph Hellwig * 54743ff2122SChristoph Hellwig * We also set the XFS_BLF_CANCEL flag in the buf log format structure and log 54843ff2122SChristoph Hellwig * the buf item. This will be used at recovery time to determine that copies 54943ff2122SChristoph Hellwig * of the buffer in the log before this should not be replayed. 55043ff2122SChristoph Hellwig * 55143ff2122SChristoph Hellwig * We mark the item descriptor and the transaction dirty so that we'll hold 55243ff2122SChristoph Hellwig * the buffer until after the commit. 55343ff2122SChristoph Hellwig * 55443ff2122SChristoph Hellwig * Since we're invalidating the buffer, we also clear the state about which 55543ff2122SChristoph Hellwig * parts of the buffer have been logged. We also clear the flag indicating 55643ff2122SChristoph Hellwig * that this is an inode buffer since the data in the buffer will no longer 55743ff2122SChristoph Hellwig * be valid. 55843ff2122SChristoph Hellwig * 55943ff2122SChristoph Hellwig * We set the stale bit in the buffer as well since we're getting rid of it. 5601da177e4SLinus Torvalds */ 5611da177e4SLinus Torvalds void 5621da177e4SLinus Torvalds xfs_trans_binval( 5631da177e4SLinus Torvalds xfs_trans_t *tp, 5641da177e4SLinus Torvalds xfs_buf_t *bp) 5651da177e4SLinus Torvalds { 566fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 56791e4bac0SMark Tinguely int i; 5681da177e4SLinus Torvalds 569bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 570adadbeefSChristoph Hellwig ASSERT(bip != NULL); 5711da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 5721da177e4SLinus Torvalds 5730b1b213fSChristoph Hellwig trace_xfs_trans_binval(bip); 5740b1b213fSChristoph Hellwig 5751da177e4SLinus Torvalds if (bip->bli_flags & XFS_BLI_STALE) { 5761da177e4SLinus Torvalds /* 5771da177e4SLinus Torvalds * If the buffer is already invalidated, then 5781da177e4SLinus Torvalds * just return. 5791da177e4SLinus Torvalds */ 5805cfd28b6SDave Chinner ASSERT(bp->b_flags & XBF_STALE); 5811da177e4SLinus Torvalds ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); 5820f22f9d0SMark Tinguely ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF)); 58361fe135cSDave Chinner ASSERT(!(bip->__bli_format.blf_flags & XFS_BLFT_MASK)); 5840f22f9d0SMark Tinguely ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL); 585e6631f85SDave Chinner ASSERT(test_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags)); 5861da177e4SLinus Torvalds ASSERT(tp->t_flags & XFS_TRANS_DIRTY); 5871da177e4SLinus Torvalds return; 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 590c867cb61SChristoph Hellwig xfs_buf_stale(bp); 59143ff2122SChristoph Hellwig 5921da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE; 593ccf7c23fSDave Chinner bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY); 5940f22f9d0SMark Tinguely bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF; 5950f22f9d0SMark Tinguely bip->__bli_format.blf_flags |= XFS_BLF_CANCEL; 59661fe135cSDave Chinner bip->__bli_format.blf_flags &= ~XFS_BLFT_MASK; 59791e4bac0SMark Tinguely for (i = 0; i < bip->bli_format_count; i++) { 59891e4bac0SMark Tinguely memset(bip->bli_formats[i].blf_data_map, 0, 59991e4bac0SMark Tinguely (bip->bli_formats[i].blf_map_size * sizeof(uint))); 60091e4bac0SMark Tinguely } 601e6631f85SDave Chinner set_bit(XFS_LI_DIRTY, &bip->bli_item.li_flags); 6021da177e4SLinus Torvalds tp->t_flags |= XFS_TRANS_DIRTY; 6031da177e4SLinus Torvalds } 6041da177e4SLinus Torvalds 6051da177e4SLinus Torvalds /* 606ccf7c23fSDave Chinner * This call is used to indicate that the buffer contains on-disk inodes which 607ccf7c23fSDave Chinner * must be handled specially during recovery. They require special handling 608ccf7c23fSDave Chinner * because only the di_next_unlinked from the inodes in the buffer should be 609ccf7c23fSDave Chinner * recovered. The rest of the data in the buffer is logged via the inodes 610ccf7c23fSDave Chinner * themselves. 6111da177e4SLinus Torvalds * 612ccf7c23fSDave Chinner * All we do is set the XFS_BLI_INODE_BUF flag in the items flags so it can be 613ccf7c23fSDave Chinner * transferred to the buffer's log format structure so that we'll know what to 614ccf7c23fSDave Chinner * do at recovery time. 6151da177e4SLinus Torvalds */ 6161da177e4SLinus Torvalds void 6171da177e4SLinus Torvalds xfs_trans_inode_buf( 6181da177e4SLinus Torvalds xfs_trans_t *tp, 6191da177e4SLinus Torvalds xfs_buf_t *bp) 6201da177e4SLinus Torvalds { 621fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 6221da177e4SLinus Torvalds 623bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 624adadbeefSChristoph Hellwig ASSERT(bip != NULL); 6251da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 6261da177e4SLinus Torvalds 627ccf7c23fSDave Chinner bip->bli_flags |= XFS_BLI_INODE_BUF; 62861fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 6291da177e4SLinus Torvalds } 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds /* 6321da177e4SLinus Torvalds * This call is used to indicate that the buffer is going to 6331da177e4SLinus Torvalds * be staled and was an inode buffer. This means it gets 6341da177e4SLinus Torvalds * special processing during unpin - where any inodes 6351da177e4SLinus Torvalds * associated with the buffer should be removed from ail. 6361da177e4SLinus Torvalds * There is also special processing during recovery, 6371da177e4SLinus Torvalds * any replay of the inodes in the buffer needs to be 6381da177e4SLinus Torvalds * prevented as the buffer may have been reused. 6391da177e4SLinus Torvalds */ 6401da177e4SLinus Torvalds void 6411da177e4SLinus Torvalds xfs_trans_stale_inode_buf( 6421da177e4SLinus Torvalds xfs_trans_t *tp, 6431da177e4SLinus Torvalds xfs_buf_t *bp) 6441da177e4SLinus Torvalds { 645fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 6461da177e4SLinus Torvalds 647bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 648adadbeefSChristoph Hellwig ASSERT(bip != NULL); 6491da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 6501da177e4SLinus Torvalds 6511da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_STALE_INODE; 652ca30b2a7SChristoph Hellwig bip->bli_item.li_cb = xfs_buf_iodone; 65361fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 6541da177e4SLinus Torvalds } 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds /* 6571da177e4SLinus Torvalds * Mark the buffer as being one which contains newly allocated 6581da177e4SLinus Torvalds * inodes. We need to make sure that even if this buffer is 6591da177e4SLinus Torvalds * relogged as an 'inode buf' we still recover all of the inode 6601da177e4SLinus Torvalds * images in the face of a crash. This works in coordination with 6611da177e4SLinus Torvalds * xfs_buf_item_committed() to ensure that the buffer remains in the 6621da177e4SLinus Torvalds * AIL at its original location even after it has been relogged. 6631da177e4SLinus Torvalds */ 6641da177e4SLinus Torvalds /* ARGSUSED */ 6651da177e4SLinus Torvalds void 6661da177e4SLinus Torvalds xfs_trans_inode_alloc_buf( 6671da177e4SLinus Torvalds xfs_trans_t *tp, 6681da177e4SLinus Torvalds xfs_buf_t *bp) 6691da177e4SLinus Torvalds { 670fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 6711da177e4SLinus Torvalds 672bf9d9013SChristoph Hellwig ASSERT(bp->b_transp == tp); 673adadbeefSChristoph Hellwig ASSERT(bip != NULL); 6741da177e4SLinus Torvalds ASSERT(atomic_read(&bip->bli_refcount) > 0); 6751da177e4SLinus Torvalds 6761da177e4SLinus Torvalds bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF; 67761fe135cSDave Chinner xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DINO_BUF); 6781da177e4SLinus Torvalds } 6791da177e4SLinus Torvalds 680ee1a47abSChristoph Hellwig /* 6818dc518dfSBrian Foster * Mark the buffer as ordered for this transaction. This means that the contents 6828dc518dfSBrian Foster * of the buffer are not recorded in the transaction but it is tracked in the 6838dc518dfSBrian Foster * AIL as though it was. This allows us to record logical changes in 6848dc518dfSBrian Foster * transactions rather than the physical changes we make to the buffer without 6858dc518dfSBrian Foster * changing writeback ordering constraints of metadata buffers. 6865f6bed76SDave Chinner */ 687a5814bceSBrian Foster bool 6885f6bed76SDave Chinner xfs_trans_ordered_buf( 6895f6bed76SDave Chinner struct xfs_trans *tp, 6905f6bed76SDave Chinner struct xfs_buf *bp) 6915f6bed76SDave Chinner { 692fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 6935f6bed76SDave Chinner 6945f6bed76SDave Chinner ASSERT(bp->b_transp == tp); 6955f6bed76SDave Chinner ASSERT(bip != NULL); 6965f6bed76SDave Chinner ASSERT(atomic_read(&bip->bli_refcount) > 0); 697a5814bceSBrian Foster 698a5814bceSBrian Foster if (xfs_buf_item_dirty_format(bip)) 699a5814bceSBrian Foster return false; 7005f6bed76SDave Chinner 7015f6bed76SDave Chinner bip->bli_flags |= XFS_BLI_ORDERED; 7025f6bed76SDave Chinner trace_xfs_buf_item_ordered(bip); 7038dc518dfSBrian Foster 7048dc518dfSBrian Foster /* 7058dc518dfSBrian Foster * We don't log a dirty range of an ordered buffer but it still needs 7068dc518dfSBrian Foster * to be marked dirty and that it has been logged. 7078dc518dfSBrian Foster */ 7088dc518dfSBrian Foster xfs_trans_dirty_buf(tp, bp); 709a5814bceSBrian Foster return true; 7105f6bed76SDave Chinner } 7115f6bed76SDave Chinner 7125f6bed76SDave Chinner /* 713ee1a47abSChristoph Hellwig * Set the type of the buffer for log recovery so that it can correctly identify 714ee1a47abSChristoph Hellwig * and hence attach the correct buffer ops to the buffer after replay. 715ee1a47abSChristoph Hellwig */ 716ee1a47abSChristoph Hellwig void 717ee1a47abSChristoph Hellwig xfs_trans_buf_set_type( 718ee1a47abSChristoph Hellwig struct xfs_trans *tp, 719ee1a47abSChristoph Hellwig struct xfs_buf *bp, 72061fe135cSDave Chinner enum xfs_blft type) 721ee1a47abSChristoph Hellwig { 722fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 723ee1a47abSChristoph Hellwig 724d75afeb3SDave Chinner if (!tp) 725d75afeb3SDave Chinner return; 726d75afeb3SDave Chinner 727ee1a47abSChristoph Hellwig ASSERT(bp->b_transp == tp); 728ee1a47abSChristoph Hellwig ASSERT(bip != NULL); 729ee1a47abSChristoph Hellwig ASSERT(atomic_read(&bip->bli_refcount) > 0); 730ee1a47abSChristoph Hellwig 73161fe135cSDave Chinner xfs_blft_to_flags(&bip->__bli_format, type); 732ee1a47abSChristoph Hellwig } 7331da177e4SLinus Torvalds 734d75afeb3SDave Chinner void 735d75afeb3SDave Chinner xfs_trans_buf_copy_type( 736d75afeb3SDave Chinner struct xfs_buf *dst_bp, 737d75afeb3SDave Chinner struct xfs_buf *src_bp) 738d75afeb3SDave Chinner { 739fb1755a6SCarlos Maiolino struct xfs_buf_log_item *sbip = src_bp->b_log_item; 740fb1755a6SCarlos Maiolino struct xfs_buf_log_item *dbip = dst_bp->b_log_item; 74161fe135cSDave Chinner enum xfs_blft type; 742d75afeb3SDave Chinner 74361fe135cSDave Chinner type = xfs_blft_from_flags(&sbip->__bli_format); 74461fe135cSDave Chinner xfs_blft_to_flags(&dbip->__bli_format, type); 745d75afeb3SDave Chinner } 746d75afeb3SDave Chinner 7471da177e4SLinus Torvalds /* 7481da177e4SLinus Torvalds * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of 7491da177e4SLinus Torvalds * dquots. However, unlike in inode buffer recovery, dquot buffers get 7501da177e4SLinus Torvalds * recovered in their entirety. (Hence, no XFS_BLI_DQUOT_ALLOC_BUF flag). 7511da177e4SLinus Torvalds * The only thing that makes dquot buffers different from regular 7521da177e4SLinus Torvalds * buffers is that we must not replay dquot bufs when recovering 7531da177e4SLinus Torvalds * if a _corresponding_ quotaoff has happened. We also have to distinguish 7541da177e4SLinus Torvalds * between usr dquot bufs and grp dquot bufs, because usr and grp quotas 7551da177e4SLinus Torvalds * can be turned off independently. 7561da177e4SLinus Torvalds */ 7571da177e4SLinus Torvalds /* ARGSUSED */ 7581da177e4SLinus Torvalds void 7591da177e4SLinus Torvalds xfs_trans_dquot_buf( 7601da177e4SLinus Torvalds xfs_trans_t *tp, 7611da177e4SLinus Torvalds xfs_buf_t *bp, 7621da177e4SLinus Torvalds uint type) 7631da177e4SLinus Torvalds { 764fb1755a6SCarlos Maiolino struct xfs_buf_log_item *bip = bp->b_log_item; 76561fe135cSDave Chinner 766c1155410SDave Chinner ASSERT(type == XFS_BLF_UDQUOT_BUF || 767c1155410SDave Chinner type == XFS_BLF_PDQUOT_BUF || 768c1155410SDave Chinner type == XFS_BLF_GDQUOT_BUF); 7691da177e4SLinus Torvalds 77061fe135cSDave Chinner bip->__bli_format.blf_flags |= type; 77161fe135cSDave Chinner 77261fe135cSDave Chinner switch (type) { 77361fe135cSDave Chinner case XFS_BLF_UDQUOT_BUF: 77461fe135cSDave Chinner type = XFS_BLFT_UDQUOT_BUF; 77561fe135cSDave Chinner break; 77661fe135cSDave Chinner case XFS_BLF_PDQUOT_BUF: 77761fe135cSDave Chinner type = XFS_BLFT_PDQUOT_BUF; 77861fe135cSDave Chinner break; 77961fe135cSDave Chinner case XFS_BLF_GDQUOT_BUF: 78061fe135cSDave Chinner type = XFS_BLFT_GDQUOT_BUF; 78161fe135cSDave Chinner break; 78261fe135cSDave Chinner default: 78361fe135cSDave Chinner type = XFS_BLFT_UNKNOWN_BUF; 78461fe135cSDave Chinner break; 78561fe135cSDave Chinner } 78661fe135cSDave Chinner 787ee1a47abSChristoph Hellwig xfs_trans_buf_set_type(tp, bp, type); 7881da177e4SLinus Torvalds } 789