1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
2 | /* |
3 | * Copyright (C) 2016 Oracle. All Rights Reserved. |
4 | * Author: Darrick J. Wong <darrick.wong@oracle.com> |
5 | */ |
6 | #ifndef __XFS_DEFER_H__ |
7 | #define __XFS_DEFER_H__ |
8 | |
9 | struct xfs_btree_cur; |
10 | struct xfs_defer_op_type; |
11 | struct xfs_defer_capture; |
12 | |
13 | /* |
14 | * Save a log intent item and a list of extents, so that we can replay |
15 | * whatever action had to happen to the extent list and file the log done |
16 | * item. |
17 | */ |
18 | struct xfs_defer_pending { |
19 | struct list_head dfp_list; /* pending items */ |
20 | struct list_head dfp_work; /* work items */ |
21 | struct xfs_log_item *dfp_intent; /* log intent item */ |
22 | struct xfs_log_item *dfp_done; /* log done item */ |
23 | const struct xfs_defer_op_type *dfp_ops; |
24 | unsigned int dfp_count; /* # extent items */ |
25 | unsigned int dfp_flags; |
26 | }; |
27 | |
28 | /* |
29 | * Create a log intent item for this deferred item, but don't actually finish |
30 | * the work. Caller must clear this before the final transaction commit. |
31 | */ |
32 | #define XFS_DEFER_PAUSED (1U << 0) |
33 | |
34 | #define XFS_DEFER_PENDING_STRINGS \ |
35 | { XFS_DEFER_PAUSED, "paused" } |
36 | |
37 | void xfs_defer_item_pause(struct xfs_trans *tp, struct xfs_defer_pending *dfp); |
38 | void xfs_defer_item_unpause(struct xfs_trans *tp, struct xfs_defer_pending *dfp); |
39 | |
40 | struct xfs_defer_pending *xfs_defer_add(struct xfs_trans *tp, struct list_head *h, |
41 | const struct xfs_defer_op_type *ops); |
42 | int xfs_defer_finish_noroll(struct xfs_trans **tp); |
43 | int xfs_defer_finish(struct xfs_trans **tp); |
44 | int xfs_defer_finish_one(struct xfs_trans *tp, struct xfs_defer_pending *dfp); |
45 | void xfs_defer_cancel(struct xfs_trans *); |
46 | void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); |
47 | |
48 | /* Description of a deferred type. */ |
49 | struct xfs_defer_op_type { |
50 | const char *name; |
51 | unsigned int max_items; |
52 | struct xfs_log_item *(*create_intent)(struct xfs_trans *tp, |
53 | struct list_head *items, unsigned int count, bool sort); |
54 | void (*abort_intent)(struct xfs_log_item *intent); |
55 | struct xfs_log_item *(*create_done)(struct xfs_trans *tp, |
56 | struct xfs_log_item *intent, unsigned int count); |
57 | int (*finish_item)(struct xfs_trans *tp, struct xfs_log_item *done, |
58 | struct list_head *item, struct xfs_btree_cur **state); |
59 | void (*finish_cleanup)(struct xfs_trans *tp, |
60 | struct xfs_btree_cur *state, int error); |
61 | void (*cancel_item)(struct list_head *item); |
62 | int (*recover_work)(struct xfs_defer_pending *dfp, |
63 | struct list_head *capture_list); |
64 | struct xfs_log_item *(*relog_intent)(struct xfs_trans *tp, |
65 | struct xfs_log_item *intent, |
66 | struct xfs_log_item *done_item); |
67 | }; |
68 | |
69 | extern const struct xfs_defer_op_type xfs_bmap_update_defer_type; |
70 | extern const struct xfs_defer_op_type xfs_refcount_update_defer_type; |
71 | extern const struct xfs_defer_op_type xfs_rmap_update_defer_type; |
72 | extern const struct xfs_defer_op_type xfs_extent_free_defer_type; |
73 | extern const struct xfs_defer_op_type xfs_agfl_free_defer_type; |
74 | extern const struct xfs_defer_op_type xfs_attr_defer_type; |
75 | |
76 | |
77 | /* |
78 | * Deferred operation item relogging limits. |
79 | */ |
80 | #define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ |
81 | #define XFS_DEFER_OPS_NR_BUFS 2 /* join up to two buffers */ |
82 | |
83 | /* Resources that must be held across a transaction roll. */ |
84 | struct xfs_defer_resources { |
85 | /* held buffers */ |
86 | struct xfs_buf *dr_bp[XFS_DEFER_OPS_NR_BUFS]; |
87 | |
88 | /* inodes with no unlock flags */ |
89 | struct xfs_inode *dr_ip[XFS_DEFER_OPS_NR_INODES]; |
90 | |
91 | /* number of held buffers */ |
92 | unsigned short dr_bufs; |
93 | |
94 | /* bitmap of ordered buffers */ |
95 | unsigned short dr_ordered; |
96 | |
97 | /* number of held inodes */ |
98 | unsigned short dr_inos; |
99 | }; |
100 | |
101 | /* |
102 | * This structure enables a dfops user to detach the chain of deferred |
103 | * operations from a transaction so that they can be continued later. |
104 | */ |
105 | struct xfs_defer_capture { |
106 | /* List of other capture structures. */ |
107 | struct list_head dfc_list; |
108 | |
109 | /* Deferred ops state saved from the transaction. */ |
110 | struct list_head dfc_dfops; |
111 | unsigned int dfc_tpflags; |
112 | |
113 | /* Block reservations for the data and rt devices. */ |
114 | unsigned int dfc_blkres; |
115 | unsigned int dfc_rtxres; |
116 | |
117 | /* Log reservation saved from the transaction. */ |
118 | unsigned int dfc_logres; |
119 | |
120 | struct xfs_defer_resources dfc_held; |
121 | }; |
122 | |
123 | /* |
124 | * Functions to capture a chain of deferred operations and continue them later. |
125 | * This doesn't normally happen except log recovery. |
126 | */ |
127 | int xfs_defer_ops_capture_and_commit(struct xfs_trans *tp, |
128 | struct list_head *capture_list); |
129 | void xfs_defer_ops_continue(struct xfs_defer_capture *d, struct xfs_trans *tp, |
130 | struct xfs_defer_resources *dres); |
131 | void xfs_defer_ops_capture_abort(struct xfs_mount *mp, |
132 | struct xfs_defer_capture *d); |
133 | void xfs_defer_resources_rele(struct xfs_defer_resources *dres); |
134 | |
135 | void xfs_defer_start_recovery(struct xfs_log_item *lip, |
136 | struct list_head *r_dfops, const struct xfs_defer_op_type *ops); |
137 | void xfs_defer_cancel_recovery(struct xfs_mount *mp, |
138 | struct xfs_defer_pending *dfp); |
139 | int xfs_defer_finish_recovery(struct xfs_mount *mp, |
140 | struct xfs_defer_pending *dfp, struct list_head *capture_list); |
141 | |
142 | static inline void |
143 | xfs_defer_add_item( |
144 | struct xfs_defer_pending *dfp, |
145 | struct list_head *work) |
146 | { |
147 | list_add_tail(work, &dfp->dfp_work); |
148 | dfp->dfp_count++; |
149 | } |
150 | |
151 | int __init xfs_defer_init_item_caches(void); |
152 | void xfs_defer_destroy_item_caches(void); |
153 | |
154 | void xfs_defer_add_barrier(struct xfs_trans *tp); |
155 | |
156 | #endif /* __XFS_DEFER_H__ */ |
157 | |