162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
462306a36Sopenharmony_ci * All Rights Reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#ifndef __XFS_TRANS_PRIV_H__
762306a36Sopenharmony_ci#define	__XFS_TRANS_PRIV_H__
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistruct xlog;
1062306a36Sopenharmony_cistruct xfs_log_item;
1162306a36Sopenharmony_cistruct xfs_mount;
1262306a36Sopenharmony_cistruct xfs_trans;
1362306a36Sopenharmony_cistruct xfs_ail;
1462306a36Sopenharmony_cistruct xfs_log_vec;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_civoid	xfs_trans_init(struct xfs_mount *);
1862306a36Sopenharmony_civoid	xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *);
1962306a36Sopenharmony_civoid	xfs_trans_del_item(struct xfs_log_item *);
2062306a36Sopenharmony_civoid	xfs_trans_unreserve_and_mod_sb(struct xfs_trans *tp);
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_civoid	xfs_trans_committed_bulk(struct xfs_ail *ailp,
2362306a36Sopenharmony_ci				struct list_head *lv_chain,
2462306a36Sopenharmony_ci				xfs_lsn_t commit_lsn, bool aborted);
2562306a36Sopenharmony_ci/*
2662306a36Sopenharmony_ci * AIL traversal cursor.
2762306a36Sopenharmony_ci *
2862306a36Sopenharmony_ci * Rather than using a generation number for detecting changes in the ail, use
2962306a36Sopenharmony_ci * a cursor that is protected by the ail lock. The aild cursor exists in the
3062306a36Sopenharmony_ci * struct xfs_ail, but other traversals can declare it on the stack and link it
3162306a36Sopenharmony_ci * to the ail list.
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * When an object is deleted from or moved int the AIL, the cursor list is
3462306a36Sopenharmony_ci * searched to see if the object is a designated cursor item. If it is, it is
3562306a36Sopenharmony_ci * deleted from the cursor so that the next time the cursor is used traversal
3662306a36Sopenharmony_ci * will return to the start.
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * This means a traversal colliding with a removal will cause a restart of the
3962306a36Sopenharmony_ci * list scan, rather than any insertion or deletion anywhere in the list. The
4062306a36Sopenharmony_ci * low bit of the item pointer is set if the cursor has been invalidated so
4162306a36Sopenharmony_ci * that we can tell the difference between invalidation and reaching the end
4262306a36Sopenharmony_ci * of the list to trigger traversal restarts.
4362306a36Sopenharmony_ci */
4462306a36Sopenharmony_cistruct xfs_ail_cursor {
4562306a36Sopenharmony_ci	struct list_head	list;
4662306a36Sopenharmony_ci	struct xfs_log_item	*item;
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/*
5062306a36Sopenharmony_ci * Private AIL structures.
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci * Eventually we need to drive the locking in here as well.
5362306a36Sopenharmony_ci */
5462306a36Sopenharmony_cistruct xfs_ail {
5562306a36Sopenharmony_ci	struct xlog		*ail_log;
5662306a36Sopenharmony_ci	struct task_struct	*ail_task;
5762306a36Sopenharmony_ci	struct list_head	ail_head;
5862306a36Sopenharmony_ci	xfs_lsn_t		ail_target;
5962306a36Sopenharmony_ci	xfs_lsn_t		ail_target_prev;
6062306a36Sopenharmony_ci	struct list_head	ail_cursors;
6162306a36Sopenharmony_ci	spinlock_t		ail_lock;
6262306a36Sopenharmony_ci	xfs_lsn_t		ail_last_pushed_lsn;
6362306a36Sopenharmony_ci	int			ail_log_flush;
6462306a36Sopenharmony_ci	struct list_head	ail_buf_list;
6562306a36Sopenharmony_ci	wait_queue_head_t	ail_empty;
6662306a36Sopenharmony_ci};
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * From xfs_trans_ail.c
7062306a36Sopenharmony_ci */
7162306a36Sopenharmony_civoid	xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
7262306a36Sopenharmony_ci				struct xfs_ail_cursor *cur,
7362306a36Sopenharmony_ci				struct xfs_log_item **log_items, int nr_items,
7462306a36Sopenharmony_ci				xfs_lsn_t lsn) __releases(ailp->ail_lock);
7562306a36Sopenharmony_ci/*
7662306a36Sopenharmony_ci * Return a pointer to the first item in the AIL.  If the AIL is empty, then
7762306a36Sopenharmony_ci * return NULL.
7862306a36Sopenharmony_ci */
7962306a36Sopenharmony_cistatic inline struct xfs_log_item *
8062306a36Sopenharmony_cixfs_ail_min(
8162306a36Sopenharmony_ci	struct xfs_ail  *ailp)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	return list_first_entry_or_null(&ailp->ail_head, struct xfs_log_item,
8462306a36Sopenharmony_ci					li_ail);
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic inline void
8862306a36Sopenharmony_cixfs_trans_ail_update(
8962306a36Sopenharmony_ci	struct xfs_ail		*ailp,
9062306a36Sopenharmony_ci	struct xfs_log_item	*lip,
9162306a36Sopenharmony_ci	xfs_lsn_t		lsn) __releases(ailp->ail_lock)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_civoid xfs_trans_ail_insert(struct xfs_ail *ailp, struct xfs_log_item *lip,
9762306a36Sopenharmony_ci		xfs_lsn_t lsn);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cixfs_lsn_t xfs_ail_delete_one(struct xfs_ail *ailp, struct xfs_log_item *lip);
10062306a36Sopenharmony_civoid xfs_ail_update_finish(struct xfs_ail *ailp, xfs_lsn_t old_lsn)
10162306a36Sopenharmony_ci			__releases(ailp->ail_lock);
10262306a36Sopenharmony_civoid xfs_trans_ail_delete(struct xfs_log_item *lip, int shutdown_type);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_civoid			xfs_ail_push(struct xfs_ail *, xfs_lsn_t);
10562306a36Sopenharmony_civoid			xfs_ail_push_all(struct xfs_ail *);
10662306a36Sopenharmony_civoid			xfs_ail_push_all_sync(struct xfs_ail *);
10762306a36Sopenharmony_cistruct xfs_log_item	*xfs_ail_min(struct xfs_ail  *ailp);
10862306a36Sopenharmony_cixfs_lsn_t		xfs_ail_min_lsn(struct xfs_ail *ailp);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistruct xfs_log_item *	xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
11162306a36Sopenharmony_ci					struct xfs_ail_cursor *cur,
11262306a36Sopenharmony_ci					xfs_lsn_t lsn);
11362306a36Sopenharmony_cistruct xfs_log_item *	xfs_trans_ail_cursor_last(struct xfs_ail *ailp,
11462306a36Sopenharmony_ci					struct xfs_ail_cursor *cur,
11562306a36Sopenharmony_ci					xfs_lsn_t lsn);
11662306a36Sopenharmony_cistruct xfs_log_item *	xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
11762306a36Sopenharmony_ci					struct xfs_ail_cursor *cur);
11862306a36Sopenharmony_civoid			xfs_trans_ail_cursor_done(struct xfs_ail_cursor *cur);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#if BITS_PER_LONG != 64
12162306a36Sopenharmony_cistatic inline void
12262306a36Sopenharmony_cixfs_trans_ail_copy_lsn(
12362306a36Sopenharmony_ci	struct xfs_ail	*ailp,
12462306a36Sopenharmony_ci	xfs_lsn_t	*dst,
12562306a36Sopenharmony_ci	xfs_lsn_t	*src)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	ASSERT(sizeof(xfs_lsn_t) == 8);	/* don't lock if it shrinks */
12862306a36Sopenharmony_ci	spin_lock(&ailp->ail_lock);
12962306a36Sopenharmony_ci	*dst = *src;
13062306a36Sopenharmony_ci	spin_unlock(&ailp->ail_lock);
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci#else
13362306a36Sopenharmony_cistatic inline void
13462306a36Sopenharmony_cixfs_trans_ail_copy_lsn(
13562306a36Sopenharmony_ci	struct xfs_ail	*ailp,
13662306a36Sopenharmony_ci	xfs_lsn_t	*dst,
13762306a36Sopenharmony_ci	xfs_lsn_t	*src)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	ASSERT(sizeof(xfs_lsn_t) == 8);
14062306a36Sopenharmony_ci	*dst = *src;
14162306a36Sopenharmony_ci}
14262306a36Sopenharmony_ci#endif
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic inline void
14562306a36Sopenharmony_cixfs_clear_li_failed(
14662306a36Sopenharmony_ci	struct xfs_log_item	*lip)
14762306a36Sopenharmony_ci{
14862306a36Sopenharmony_ci	struct xfs_buf	*bp = lip->li_buf;
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags));
15162306a36Sopenharmony_ci	lockdep_assert_held(&lip->li_ailp->ail_lock);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (test_and_clear_bit(XFS_LI_FAILED, &lip->li_flags)) {
15462306a36Sopenharmony_ci		lip->li_buf = NULL;
15562306a36Sopenharmony_ci		xfs_buf_rele(bp);
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistatic inline void
16062306a36Sopenharmony_cixfs_set_li_failed(
16162306a36Sopenharmony_ci	struct xfs_log_item	*lip,
16262306a36Sopenharmony_ci	struct xfs_buf		*bp)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	lockdep_assert_held(&lip->li_ailp->ail_lock);
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (!test_and_set_bit(XFS_LI_FAILED, &lip->li_flags)) {
16762306a36Sopenharmony_ci		xfs_buf_hold(bp);
16862306a36Sopenharmony_ci		lip->li_buf = bp;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci#endif	/* __XFS_TRANS_PRIV_H__ */
173