1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
4*4882a593Smuzhiyun * All Rights Reserved.
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun #ifndef __XFS_TRANS_PRIV_H__
7*4882a593Smuzhiyun #define __XFS_TRANS_PRIV_H__
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun struct xfs_log_item;
10*4882a593Smuzhiyun struct xfs_mount;
11*4882a593Smuzhiyun struct xfs_trans;
12*4882a593Smuzhiyun struct xfs_ail;
13*4882a593Smuzhiyun struct xfs_log_vec;
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun void xfs_trans_init(struct xfs_mount *);
17*4882a593Smuzhiyun void xfs_trans_add_item(struct xfs_trans *, struct xfs_log_item *);
18*4882a593Smuzhiyun void xfs_trans_del_item(struct xfs_log_item *);
19*4882a593Smuzhiyun void xfs_trans_unreserve_and_mod_sb(struct xfs_trans *tp);
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun void xfs_trans_committed_bulk(struct xfs_ail *ailp, struct xfs_log_vec *lv,
22*4882a593Smuzhiyun xfs_lsn_t commit_lsn, bool aborted);
23*4882a593Smuzhiyun /*
24*4882a593Smuzhiyun * AIL traversal cursor.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * Rather than using a generation number for detecting changes in the ail, use
27*4882a593Smuzhiyun * a cursor that is protected by the ail lock. The aild cursor exists in the
28*4882a593Smuzhiyun * struct xfs_ail, but other traversals can declare it on the stack and link it
29*4882a593Smuzhiyun * to the ail list.
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * When an object is deleted from or moved int the AIL, the cursor list is
32*4882a593Smuzhiyun * searched to see if the object is a designated cursor item. If it is, it is
33*4882a593Smuzhiyun * deleted from the cursor so that the next time the cursor is used traversal
34*4882a593Smuzhiyun * will return to the start.
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * This means a traversal colliding with a removal will cause a restart of the
37*4882a593Smuzhiyun * list scan, rather than any insertion or deletion anywhere in the list. The
38*4882a593Smuzhiyun * low bit of the item pointer is set if the cursor has been invalidated so
39*4882a593Smuzhiyun * that we can tell the difference between invalidation and reaching the end
40*4882a593Smuzhiyun * of the list to trigger traversal restarts.
41*4882a593Smuzhiyun */
42*4882a593Smuzhiyun struct xfs_ail_cursor {
43*4882a593Smuzhiyun struct list_head list;
44*4882a593Smuzhiyun struct xfs_log_item *item;
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun * Private AIL structures.
49*4882a593Smuzhiyun *
50*4882a593Smuzhiyun * Eventually we need to drive the locking in here as well.
51*4882a593Smuzhiyun */
52*4882a593Smuzhiyun struct xfs_ail {
53*4882a593Smuzhiyun struct xfs_mount *ail_mount;
54*4882a593Smuzhiyun struct task_struct *ail_task;
55*4882a593Smuzhiyun struct list_head ail_head;
56*4882a593Smuzhiyun xfs_lsn_t ail_target;
57*4882a593Smuzhiyun xfs_lsn_t ail_target_prev;
58*4882a593Smuzhiyun struct list_head ail_cursors;
59*4882a593Smuzhiyun spinlock_t ail_lock;
60*4882a593Smuzhiyun xfs_lsn_t ail_last_pushed_lsn;
61*4882a593Smuzhiyun int ail_log_flush;
62*4882a593Smuzhiyun struct list_head ail_buf_list;
63*4882a593Smuzhiyun wait_queue_head_t ail_empty;
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /*
67*4882a593Smuzhiyun * From xfs_trans_ail.c
68*4882a593Smuzhiyun */
69*4882a593Smuzhiyun void xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
70*4882a593Smuzhiyun struct xfs_ail_cursor *cur,
71*4882a593Smuzhiyun struct xfs_log_item **log_items, int nr_items,
72*4882a593Smuzhiyun xfs_lsn_t lsn) __releases(ailp->ail_lock);
73*4882a593Smuzhiyun /*
74*4882a593Smuzhiyun * Return a pointer to the first item in the AIL. If the AIL is empty, then
75*4882a593Smuzhiyun * return NULL.
76*4882a593Smuzhiyun */
77*4882a593Smuzhiyun static inline struct xfs_log_item *
xfs_ail_min(struct xfs_ail * ailp)78*4882a593Smuzhiyun xfs_ail_min(
79*4882a593Smuzhiyun struct xfs_ail *ailp)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun return list_first_entry_or_null(&ailp->ail_head, struct xfs_log_item,
82*4882a593Smuzhiyun li_ail);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun static inline void
xfs_trans_ail_update(struct xfs_ail * ailp,struct xfs_log_item * lip,xfs_lsn_t lsn)86*4882a593Smuzhiyun xfs_trans_ail_update(
87*4882a593Smuzhiyun struct xfs_ail *ailp,
88*4882a593Smuzhiyun struct xfs_log_item *lip,
89*4882a593Smuzhiyun xfs_lsn_t lsn) __releases(ailp->ail_lock)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun void xfs_trans_ail_insert(struct xfs_ail *ailp, struct xfs_log_item *lip,
95*4882a593Smuzhiyun xfs_lsn_t lsn);
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun xfs_lsn_t xfs_ail_delete_one(struct xfs_ail *ailp, struct xfs_log_item *lip);
98*4882a593Smuzhiyun void xfs_ail_update_finish(struct xfs_ail *ailp, xfs_lsn_t old_lsn)
99*4882a593Smuzhiyun __releases(ailp->ail_lock);
100*4882a593Smuzhiyun void xfs_trans_ail_delete(struct xfs_log_item *lip, int shutdown_type);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun void xfs_ail_push(struct xfs_ail *, xfs_lsn_t);
103*4882a593Smuzhiyun void xfs_ail_push_all(struct xfs_ail *);
104*4882a593Smuzhiyun void xfs_ail_push_all_sync(struct xfs_ail *);
105*4882a593Smuzhiyun struct xfs_log_item *xfs_ail_min(struct xfs_ail *ailp);
106*4882a593Smuzhiyun xfs_lsn_t xfs_ail_min_lsn(struct xfs_ail *ailp);
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun struct xfs_log_item * xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
109*4882a593Smuzhiyun struct xfs_ail_cursor *cur,
110*4882a593Smuzhiyun xfs_lsn_t lsn);
111*4882a593Smuzhiyun struct xfs_log_item * xfs_trans_ail_cursor_last(struct xfs_ail *ailp,
112*4882a593Smuzhiyun struct xfs_ail_cursor *cur,
113*4882a593Smuzhiyun xfs_lsn_t lsn);
114*4882a593Smuzhiyun struct xfs_log_item * xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
115*4882a593Smuzhiyun struct xfs_ail_cursor *cur);
116*4882a593Smuzhiyun void xfs_trans_ail_cursor_done(struct xfs_ail_cursor *cur);
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun #if BITS_PER_LONG != 64
119*4882a593Smuzhiyun static inline void
xfs_trans_ail_copy_lsn(struct xfs_ail * ailp,xfs_lsn_t * dst,xfs_lsn_t * src)120*4882a593Smuzhiyun xfs_trans_ail_copy_lsn(
121*4882a593Smuzhiyun struct xfs_ail *ailp,
122*4882a593Smuzhiyun xfs_lsn_t *dst,
123*4882a593Smuzhiyun xfs_lsn_t *src)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun ASSERT(sizeof(xfs_lsn_t) == 8); /* don't lock if it shrinks */
126*4882a593Smuzhiyun spin_lock(&ailp->ail_lock);
127*4882a593Smuzhiyun *dst = *src;
128*4882a593Smuzhiyun spin_unlock(&ailp->ail_lock);
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun #else
131*4882a593Smuzhiyun static inline void
xfs_trans_ail_copy_lsn(struct xfs_ail * ailp,xfs_lsn_t * dst,xfs_lsn_t * src)132*4882a593Smuzhiyun xfs_trans_ail_copy_lsn(
133*4882a593Smuzhiyun struct xfs_ail *ailp,
134*4882a593Smuzhiyun xfs_lsn_t *dst,
135*4882a593Smuzhiyun xfs_lsn_t *src)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun ASSERT(sizeof(xfs_lsn_t) == 8);
138*4882a593Smuzhiyun *dst = *src;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun #endif
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun static inline void
xfs_clear_li_failed(struct xfs_log_item * lip)143*4882a593Smuzhiyun xfs_clear_li_failed(
144*4882a593Smuzhiyun struct xfs_log_item *lip)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun struct xfs_buf *bp = lip->li_buf;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags));
149*4882a593Smuzhiyun lockdep_assert_held(&lip->li_ailp->ail_lock);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun if (test_and_clear_bit(XFS_LI_FAILED, &lip->li_flags)) {
152*4882a593Smuzhiyun lip->li_buf = NULL;
153*4882a593Smuzhiyun xfs_buf_rele(bp);
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun static inline void
xfs_set_li_failed(struct xfs_log_item * lip,struct xfs_buf * bp)158*4882a593Smuzhiyun xfs_set_li_failed(
159*4882a593Smuzhiyun struct xfs_log_item *lip,
160*4882a593Smuzhiyun struct xfs_buf *bp)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun lockdep_assert_held(&lip->li_ailp->ail_lock);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun if (!test_and_set_bit(XFS_LI_FAILED, &lip->li_flags)) {
165*4882a593Smuzhiyun xfs_buf_hold(bp);
166*4882a593Smuzhiyun lip->li_buf = bp;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun #endif /* __XFS_TRANS_PRIV_H__ */
171