xref: /OK3568_Linux_fs/kernel/fs/xfs/xfs_trans_priv.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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