95808459b1
The xfs_buf_log_item structure has a reference counter with slightly tricky semantics. In the common case, a buffer is logged and committed in a transaction, committed to the on-disk log (added to the AIL) and then finally written back and removed from the AIL. The bli refcount covers two potentially overlapping timeframes: 1. the bli is held in an active transaction 2. the bli is pinned by the log The caveat to this approach is that the reference counter does not purely dictate the lifetime of the bli. IOW, when a dirty buffer is physically logged and unpinned, the bli refcount may go to zero as the log item is inserted into the AIL. Only once the buffer is written back can the bli finally be freed. The above semantics means that it is not enough for the various refcount decrementing contexts to release the bli on decrement to zero. xfs_trans_brelse(), transaction commit (->iop_unlock()) and unpin (->iop_unpin()) must all drop the associated reference and make additional checks to determine if the current context is responsible for freeing the item. For example, if a transaction holds but does not dirty a particular bli, the commit may drop the refcount to zero. If the bli itself is clean, it is also not AIL resident and must be freed at this time. The same is true for xfs_trans_brelse(). If the transaction dirties a bli and then aborts or an unpin results in an abort due to a log I/O error, the last reference count holder is expected to explicitly remove the item from the AIL and release it (since an abort means filesystem shutdown and metadata writeback will never occur). This leads to fairly complex checks being replicated in a few different places. Since ->iop_unlock() and xfs_trans_brelse() are nearly identical, refactor the logic into a common helper that implements and documents the semantics in one place. This patch does not change behavior. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
67 lines
2.1 KiB
C
67 lines
2.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
|
|
* All Rights Reserved.
|
|
*/
|
|
#ifndef __XFS_BUF_ITEM_H__
|
|
#define __XFS_BUF_ITEM_H__
|
|
|
|
/* kernel only definitions */
|
|
|
|
/* buf log item flags */
|
|
#define XFS_BLI_HOLD 0x01
|
|
#define XFS_BLI_DIRTY 0x02
|
|
#define XFS_BLI_STALE 0x04
|
|
#define XFS_BLI_LOGGED 0x08
|
|
#define XFS_BLI_INODE_ALLOC_BUF 0x10
|
|
#define XFS_BLI_STALE_INODE 0x20
|
|
#define XFS_BLI_INODE_BUF 0x40
|
|
#define XFS_BLI_ORDERED 0x80
|
|
|
|
#define XFS_BLI_FLAGS \
|
|
{ XFS_BLI_HOLD, "HOLD" }, \
|
|
{ XFS_BLI_DIRTY, "DIRTY" }, \
|
|
{ XFS_BLI_STALE, "STALE" }, \
|
|
{ XFS_BLI_LOGGED, "LOGGED" }, \
|
|
{ XFS_BLI_INODE_ALLOC_BUF, "INODE_ALLOC" }, \
|
|
{ XFS_BLI_STALE_INODE, "STALE_INODE" }, \
|
|
{ XFS_BLI_INODE_BUF, "INODE_BUF" }, \
|
|
{ XFS_BLI_ORDERED, "ORDERED" }
|
|
|
|
|
|
struct xfs_buf;
|
|
struct xfs_mount;
|
|
struct xfs_buf_log_item;
|
|
|
|
/*
|
|
* This is the in core log item structure used to track information
|
|
* needed to log buffers. It tracks how many times the lock has been
|
|
* locked, and which 128 byte chunks of the buffer are dirty.
|
|
*/
|
|
struct xfs_buf_log_item {
|
|
xfs_log_item_t bli_item; /* common item structure */
|
|
struct xfs_buf *bli_buf; /* real buffer pointer */
|
|
unsigned int bli_flags; /* misc flags */
|
|
unsigned int bli_recur; /* lock recursion count */
|
|
atomic_t bli_refcount; /* cnt of tp refs */
|
|
int bli_format_count; /* count of headers */
|
|
struct xfs_buf_log_format *bli_formats; /* array of in-log header ptrs */
|
|
struct xfs_buf_log_format __bli_format; /* embedded in-log header */
|
|
};
|
|
|
|
int xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
|
|
void xfs_buf_item_relse(struct xfs_buf *);
|
|
bool xfs_buf_item_put(struct xfs_buf_log_item *);
|
|
void xfs_buf_item_log(struct xfs_buf_log_item *, uint, uint);
|
|
bool xfs_buf_item_dirty_format(struct xfs_buf_log_item *);
|
|
void xfs_buf_attach_iodone(struct xfs_buf *,
|
|
void(*)(struct xfs_buf *, xfs_log_item_t *),
|
|
xfs_log_item_t *);
|
|
void xfs_buf_iodone_callbacks(struct xfs_buf *);
|
|
void xfs_buf_iodone(struct xfs_buf *, struct xfs_log_item *);
|
|
bool xfs_buf_resubmit_failed_buffers(struct xfs_buf *,
|
|
struct list_head *);
|
|
|
|
extern kmem_zone_t *xfs_buf_item_zone;
|
|
|
|
#endif /* __XFS_BUF_ITEM_H__ */
|