📄 xfs_trans_buf.c
字号:
xfs_buf_t *bp, uint first, uint last){ xfs_buf_log_item_t *bip; xfs_log_item_desc_t *lidp; ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); ASSERT((first <= last) && (last < XFS_BUF_COUNT(bp))); ASSERT((XFS_BUF_IODONE_FUNC(bp) == NULL) || (XFS_BUF_IODONE_FUNC(bp) == xfs_buf_iodone_callbacks)); /* * Mark the buffer as needing to be written out eventually, * and set its iodone function to remove the buffer's buf log * item from the AIL and free it when the buffer is flushed * to disk. See xfs_buf_attach_iodone() for more details * on li_cb and xfs_buf_iodone_callbacks(). * If we end up aborting this transaction, we trap this buffer * inside the b_bdstrat callback so that this won't get written to * disk. */ XFS_BUF_DELAYWRITE(bp); XFS_BUF_DONE(bp); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(atomic_read(&bip->bli_refcount) > 0); XFS_BUF_SET_IODONE_FUNC(bp, xfs_buf_iodone_callbacks); bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*))xfs_buf_iodone; /* * If we invalidated the buffer within this transaction, then * cancel the invalidation now that we're dirtying the buffer * again. There are no races with the code in xfs_buf_item_unpin(), * because we have a reference to the buffer this entire time. */ if (bip->bli_flags & XFS_BLI_STALE) { xfs_buf_item_trace("BLOG UNSTALE", bip); bip->bli_flags &= ~XFS_BLI_STALE; ASSERT(XFS_BUF_ISSTALE(bp)); XFS_BUF_UNSTALE(bp); bip->bli_format.blf_flags &= ~XFS_BLI_CANCEL; } lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); ASSERT(lidp != NULL); tp->t_flags |= XFS_TRANS_DIRTY; lidp->lid_flags |= XFS_LID_DIRTY; lidp->lid_flags &= ~XFS_LID_BUF_STALE; bip->bli_flags |= XFS_BLI_LOGGED; xfs_buf_item_log(bip, first, last); xfs_buf_item_trace("BLOG", bip);}/* * This called to invalidate a buffer that is being used within * a transaction. Typically this is because the blocks in the * buffer are being freed, so we need to prevent it from being * written out when we're done. Allowing it to be written again * might overwrite data in the free blocks if they are reallocated * to a file. * * We prevent the buffer from being written out by clearing the * B_DELWRI flag. We can't always * get rid of the buf log item at this point, though, because * the buffer may still be pinned by another transaction. If that * is the case, then we'll wait until the buffer is committed to * disk for the last time (we can tell by the ref count) and * free it in xfs_buf_item_unpin(). Until it is cleaned up we * will keep the buffer locked so that the buffer and buf log item * are not reused. */voidxfs_trans_binval( xfs_trans_t *tp, xfs_buf_t *bp){ xfs_log_item_desc_t *lidp; xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); lidp = xfs_trans_find_item(tp, (xfs_log_item_t*)bip); ASSERT(lidp != NULL); ASSERT(atomic_read(&bip->bli_refcount) > 0); if (bip->bli_flags & XFS_BLI_STALE) { /* * If the buffer is already invalidated, then * just return. */ ASSERT(!(XFS_BUF_ISDELAYWRITE(bp))); ASSERT(XFS_BUF_ISSTALE(bp)); ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY))); ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_INODE_BUF)); ASSERT(bip->bli_format.blf_flags & XFS_BLI_CANCEL); ASSERT(lidp->lid_flags & XFS_LID_DIRTY); ASSERT(tp->t_flags & XFS_TRANS_DIRTY); xfs_buftrace("XFS_BINVAL RECUR", bp); xfs_buf_item_trace("BINVAL RECUR", bip); return; } /* * Clear the dirty bit in the buffer and set the STALE flag * in the buf log item. The STALE flag will be used in * xfs_buf_item_unpin() to determine if it should clean up * when the last reference to the buf item is given up. * We set the XFS_BLI_CANCEL flag in the buf log format structure * and log the buf item. This will be used at recovery time * to determine that copies of the buffer in the log before * this should not be replayed. * We mark the item descriptor and the transaction dirty so * that we'll hold the buffer until after the commit. * * Since we're invalidating the buffer, we also clear the state * about which parts of the buffer have been logged. We also * clear the flag indicating that this is an inode buffer since * the data in the buffer will no longer be valid. * * We set the stale bit in the buffer as well since we're getting * rid of it. */ XFS_BUF_UNDELAYWRITE(bp); XFS_BUF_STALE(bp); bip->bli_flags |= XFS_BLI_STALE; bip->bli_flags &= ~(XFS_BLI_LOGGED | XFS_BLI_DIRTY); bip->bli_format.blf_flags &= ~XFS_BLI_INODE_BUF; bip->bli_format.blf_flags |= XFS_BLI_CANCEL; memset((char *)(bip->bli_format.blf_data_map), 0, (bip->bli_format.blf_map_size * sizeof(uint))); lidp->lid_flags |= XFS_LID_DIRTY|XFS_LID_BUF_STALE; tp->t_flags |= XFS_TRANS_DIRTY; xfs_buftrace("XFS_BINVAL", bp); xfs_buf_item_trace("BINVAL", bip);}/* * This call is used to indicate that the buffer contains on-disk * inodes which must be handled specially during recovery. They * require special handling because only the di_next_unlinked from * the inodes in the buffer should be recovered. The rest of the * data in the buffer is logged via the inodes themselves. * * All we do is set the XFS_BLI_INODE_BUF flag in the buffer's log * format structure so that we'll know what to do at recovery time. *//* ARGSUSED */voidxfs_trans_inode_buf( xfs_trans_t *tp, xfs_buf_t *bp){ xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(atomic_read(&bip->bli_refcount) > 0); bip->bli_format.blf_flags |= XFS_BLI_INODE_BUF;}/* * This call is used to indicate that the buffer is going to * be staled and was an inode buffer. This means it gets * special processing during unpin - where any inodes * associated with the buffer should be removed from ail. * There is also special processing during recovery, * any replay of the inodes in the buffer needs to be * prevented as the buffer may have been reused. */voidxfs_trans_stale_inode_buf( xfs_trans_t *tp, xfs_buf_t *bp){ xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(atomic_read(&bip->bli_refcount) > 0); bip->bli_flags |= XFS_BLI_STALE_INODE; bip->bli_item.li_cb = (void(*)(xfs_buf_t*,xfs_log_item_t*)) xfs_buf_iodone;}/* * Mark the buffer as being one which contains newly allocated * inodes. We need to make sure that even if this buffer is * relogged as an 'inode buf' we still recover all of the inode * images in the face of a crash. This works in coordination with * xfs_buf_item_committed() to ensure that the buffer remains in the * AIL at its original location even after it has been relogged. *//* ARGSUSED */voidxfs_trans_inode_alloc_buf( xfs_trans_t *tp, xfs_buf_t *bp){ xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(atomic_read(&bip->bli_refcount) > 0); bip->bli_flags |= XFS_BLI_INODE_ALLOC_BUF;}/* * Similar to xfs_trans_inode_buf(), this marks the buffer as a cluster of * dquots. However, unlike in inode buffer recovery, dquot buffers get * recovered in their entirety. (Hence, no XFS_BLI_DQUOT_ALLOC_BUF flag). * The only thing that makes dquot buffers different from regular * buffers is that we must not replay dquot bufs when recovering * if a _corresponding_ quotaoff has happened. We also have to distinguish * between usr dquot bufs and grp dquot bufs, because usr and grp quotas * can be turned off independently. *//* ARGSUSED */voidxfs_trans_dquot_buf( xfs_trans_t *tp, xfs_buf_t *bp, uint type){ xfs_buf_log_item_t *bip; ASSERT(XFS_BUF_ISBUSY(bp)); ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); ASSERT(type == XFS_BLI_UDQUOT_BUF || type == XFS_BLI_PDQUOT_BUF || type == XFS_BLI_GDQUOT_BUF); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); ASSERT(atomic_read(&bip->bli_refcount) > 0); bip->bli_format.blf_flags |= type;}/* * Check to see if a buffer matching the given parameters is already * a part of the given transaction. Only check the first, embedded * chunk, since we don't want to spend all day scanning large transactions. */STATIC xfs_buf_t *xfs_trans_buf_item_match( xfs_trans_t *tp, xfs_buftarg_t *target, xfs_daddr_t blkno, int len){ xfs_log_item_chunk_t *licp; xfs_log_item_desc_t *lidp; xfs_buf_log_item_t *blip; xfs_buf_t *bp; int i; bp = NULL; len = BBTOB(len); licp = &tp->t_items; if (!XFS_LIC_ARE_ALL_FREE(licp)) { for (i = 0; i < licp->lic_unused; i++) { /* * Skip unoccupied slots. */ if (XFS_LIC_ISFREE(licp, i)) { continue; } lidp = XFS_LIC_SLOT(licp, i); blip = (xfs_buf_log_item_t *)lidp->lid_item; if (blip->bli_item.li_type != XFS_LI_BUF) { continue; } bp = blip->bli_buf; if ((XFS_BUF_TARGET(bp) == target) && (XFS_BUF_ADDR(bp) == blkno) && (XFS_BUF_COUNT(bp) == len)) { /* * We found it. Break out and * return the pointer to the buffer. */ break; } else { bp = NULL; } } } return bp;}/* * Check to see if a buffer matching the given parameters is already * a part of the given transaction. Check all the chunks, we * want to be thorough. */STATIC xfs_buf_t *xfs_trans_buf_item_match_all( xfs_trans_t *tp, xfs_buftarg_t *target, xfs_daddr_t blkno, int len){ xfs_log_item_chunk_t *licp; xfs_log_item_desc_t *lidp; xfs_buf_log_item_t *blip; xfs_buf_t *bp; int i; bp = NULL; len = BBTOB(len); for (licp = &tp->t_items; licp != NULL; licp = licp->lic_next) { if (XFS_LIC_ARE_ALL_FREE(licp)) { ASSERT(licp == &tp->t_items); ASSERT(licp->lic_next == NULL); return NULL; } for (i = 0; i < licp->lic_unused; i++) { /* * Skip unoccupied slots. */ if (XFS_LIC_ISFREE(licp, i)) { continue; } lidp = XFS_LIC_SLOT(licp, i); blip = (xfs_buf_log_item_t *)lidp->lid_item; if (blip->bli_item.li_type != XFS_LI_BUF) { continue; } bp = blip->bli_buf; if ((XFS_BUF_TARGET(bp) == target) && (XFS_BUF_ADDR(bp) == blkno) && (XFS_BUF_COUNT(bp) == len)) { /* * We found it. Break out and * return the pointer to the buffer. */ return bp; } } } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -