1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2023 Red Hat
4 */
5
6#ifndef VDO_COMPLETION_H
7#define VDO_COMPLETION_H
8
9#include "permassert.h"
10
11#include "status-codes.h"
12#include "types.h"
13
14/**
15 * vdo_run_completion() - Run a completion's callback or error handler on the current thread.
16 *
17 * Context: This function must be called from the correct callback thread.
18 */
19static inline void vdo_run_completion(struct vdo_completion *completion)
20{
21	if ((completion->result != VDO_SUCCESS) && (completion->error_handler != NULL)) {
22		completion->error_handler(completion);
23		return;
24	}
25
26	completion->callback(completion);
27}
28
29void vdo_set_completion_result(struct vdo_completion *completion, int result);
30
31void vdo_initialize_completion(struct vdo_completion *completion, struct vdo *vdo,
32			       enum vdo_completion_type type);
33
34/**
35 * vdo_reset_completion() - Reset a completion to a clean state, while keeping the type, vdo and
36 *                          parent information.
37 */
38static inline void vdo_reset_completion(struct vdo_completion *completion)
39{
40	completion->result = VDO_SUCCESS;
41	completion->complete = false;
42}
43
44void vdo_launch_completion_with_priority(struct vdo_completion *completion,
45					 enum vdo_completion_priority priority);
46
47/**
48 * vdo_launch_completion() - Launch a completion with default priority.
49 */
50static inline void vdo_launch_completion(struct vdo_completion *completion)
51{
52	vdo_launch_completion_with_priority(completion, VDO_WORK_Q_DEFAULT_PRIORITY);
53}
54
55/**
56 * vdo_continue_completion() - Continue processing a completion.
57 * @result: The current result (will not mask older errors).
58 *
59 * Continue processing a completion by setting the current result and calling
60 * vdo_launch_completion().
61 */
62static inline void vdo_continue_completion(struct vdo_completion *completion, int result)
63{
64	vdo_set_completion_result(completion, result);
65	vdo_launch_completion(completion);
66}
67
68void vdo_finish_completion(struct vdo_completion *completion);
69
70/**
71 * vdo_fail_completion() - Set the result of a completion if it does not already have an error,
72 *                         then finish it.
73 */
74static inline void vdo_fail_completion(struct vdo_completion *completion, int result)
75{
76	vdo_set_completion_result(completion, result);
77	vdo_finish_completion(completion);
78}
79
80/**
81 * vdo_assert_completion_type() - Assert that a completion is of the correct type.
82 *
83 * Return: VDO_SUCCESS or an error
84 */
85static inline int vdo_assert_completion_type(struct vdo_completion *completion,
86					     enum vdo_completion_type expected)
87{
88	return VDO_ASSERT(expected == completion->type,
89			  "completion type should be %u, not %u", expected,
90			  completion->type);
91}
92
93static inline void vdo_set_completion_callback(struct vdo_completion *completion,
94					       vdo_action_fn callback,
95					       thread_id_t callback_thread_id)
96{
97	completion->callback = callback;
98	completion->callback_thread_id = callback_thread_id;
99}
100
101/**
102 * vdo_launch_completion_callback() - Set the callback for a completion and launch it immediately.
103 */
104static inline void vdo_launch_completion_callback(struct vdo_completion *completion,
105						  vdo_action_fn callback,
106						  thread_id_t callback_thread_id)
107{
108	vdo_set_completion_callback(completion, callback, callback_thread_id);
109	vdo_launch_completion(completion);
110}
111
112/**
113 * vdo_prepare_completion() - Prepare a completion for launch.
114 *
115 * Resets the completion, and then sets its callback, error handler, callback thread, and parent.
116 */
117static inline void vdo_prepare_completion(struct vdo_completion *completion,
118					  vdo_action_fn callback,
119					  vdo_action_fn error_handler,
120					  thread_id_t callback_thread_id, void *parent)
121{
122	vdo_reset_completion(completion);
123	vdo_set_completion_callback(completion, callback, callback_thread_id);
124	completion->error_handler = error_handler;
125	completion->parent = parent;
126}
127
128/**
129 * vdo_prepare_completion_for_requeue() - Prepare a completion for launch ensuring that it will
130 *                                        always be requeued.
131 *
132 * Resets the completion, and then sets its callback, error handler, callback thread, and parent.
133 */
134static inline void vdo_prepare_completion_for_requeue(struct vdo_completion *completion,
135						      vdo_action_fn callback,
136						      vdo_action_fn error_handler,
137						      thread_id_t callback_thread_id,
138						      void *parent)
139{
140	vdo_prepare_completion(completion, callback, error_handler,
141			       callback_thread_id, parent);
142	completion->requeue = true;
143}
144
145void vdo_enqueue_completion(struct vdo_completion *completion,
146			    enum vdo_completion_priority priority);
147
148
149bool vdo_requeue_completion_if_needed(struct vdo_completion *completion,
150				      thread_id_t callback_thread_id);
151
152#endif /* VDO_COMPLETION_H */
153