dm vdo: remove unnecessary indexer.h includes
[linux-2.6-block.git] / drivers / md / dm-vdo / data-vio.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright 2023 Red Hat
4  */
5
6 #ifndef DATA_VIO_H
7 #define DATA_VIO_H
8
9 #include <linux/atomic.h>
10 #include <linux/bio.h>
11 #include <linux/list.h>
12
13 #include "indexer.h"
14 #include "permassert.h"
15
16 #include "block-map.h"
17 #include "completion.h"
18 #include "constants.h"
19 #include "dedupe.h"
20 #include "encodings.h"
21 #include "logical-zone.h"
22 #include "physical-zone.h"
23 #include "types.h"
24 #include "vdo.h"
25 #include "vio.h"
26 #include "wait-queue.h"
27
28 /* Codes for describing the last asynchronous operation performed on a vio. */
29 enum async_operation_number {
30         MIN_VIO_ASYNC_OPERATION_NUMBER,
31         VIO_ASYNC_OP_LAUNCH = MIN_VIO_ASYNC_OPERATION_NUMBER,
32         VIO_ASYNC_OP_ACKNOWLEDGE_WRITE,
33         VIO_ASYNC_OP_ACQUIRE_VDO_HASH_LOCK,
34         VIO_ASYNC_OP_ATTEMPT_LOGICAL_BLOCK_LOCK,
35         VIO_ASYNC_OP_LOCK_DUPLICATE_PBN,
36         VIO_ASYNC_OP_CHECK_FOR_DUPLICATION,
37         VIO_ASYNC_OP_CLEANUP,
38         VIO_ASYNC_OP_COMPRESS_DATA_VIO,
39         VIO_ASYNC_OP_FIND_BLOCK_MAP_SLOT,
40         VIO_ASYNC_OP_GET_MAPPED_BLOCK_FOR_READ,
41         VIO_ASYNC_OP_GET_MAPPED_BLOCK_FOR_WRITE,
42         VIO_ASYNC_OP_HASH_DATA_VIO,
43         VIO_ASYNC_OP_JOURNAL_REMAPPING,
44         VIO_ASYNC_OP_ATTEMPT_PACKING,
45         VIO_ASYNC_OP_PUT_MAPPED_BLOCK,
46         VIO_ASYNC_OP_READ_DATA_VIO,
47         VIO_ASYNC_OP_UPDATE_DEDUPE_INDEX,
48         VIO_ASYNC_OP_UPDATE_REFERENCE_COUNTS,
49         VIO_ASYNC_OP_VERIFY_DUPLICATION,
50         VIO_ASYNC_OP_WRITE_DATA_VIO,
51         MAX_VIO_ASYNC_OPERATION_NUMBER,
52 } __packed;
53
54 struct lbn_lock {
55         logical_block_number_t lbn;
56         bool locked;
57         struct vdo_wait_queue waiters;
58         struct logical_zone *zone;
59 };
60
61 /* A position in the arboreal block map at a specific level. */
62 struct block_map_tree_slot {
63         page_number_t page_index;
64         struct block_map_slot block_map_slot;
65 };
66
67 /* Fields for using the arboreal block map. */
68 struct tree_lock {
69         /* The current height at which this data_vio is operating */
70         height_t height;
71         /* The block map tree for this LBN */
72         root_count_t root_index;
73         /* Whether we hold a page lock */
74         bool locked;
75         /* The key for the lock map */
76         u64 key;
77         /* The queue of waiters for the page this vio is allocating or loading */
78         struct vdo_wait_queue waiters;
79         /* The block map tree slots for this LBN */
80         struct block_map_tree_slot tree_slots[VDO_BLOCK_MAP_TREE_HEIGHT + 1];
81 };
82
83 struct zoned_pbn {
84         physical_block_number_t pbn;
85         enum block_mapping_state state;
86         struct physical_zone *zone;
87 };
88
89 /*
90  * Where a data_vio is on the compression path; advance_compression_stage() depends on the order of
91  * this enum.
92  */
93 enum data_vio_compression_stage {
94         /* A data_vio which has not yet entered the compression path */
95         DATA_VIO_PRE_COMPRESSOR,
96         /* A data_vio which is in the compressor */
97         DATA_VIO_COMPRESSING,
98         /* A data_vio which is blocked in the packer */
99         DATA_VIO_PACKING,
100         /* A data_vio which is no longer on the compression path (and never will be) */
101         DATA_VIO_POST_PACKER,
102 };
103
104 struct data_vio_compression_status {
105         enum data_vio_compression_stage stage;
106         bool may_not_compress;
107 };
108
109 struct compression_state {
110         /*
111          * The current compression status of this data_vio. This field contains a value which
112          * consists of a data_vio_compression_stage and a flag indicating whether a request has
113          * been made to cancel (or prevent) compression for this data_vio.
114          *
115          * This field should be accessed through the get_data_vio_compression_status() and
116          * set_data_vio_compression_status() methods. It should not be accessed directly.
117          */
118         atomic_t status;
119
120         /* The compressed size of this block */
121         u16 size;
122
123         /* The packer input or output bin slot which holds the enclosing data_vio */
124         slot_number_t slot;
125
126         /* The packer bin to which the enclosing data_vio has been assigned */
127         struct packer_bin *bin;
128
129         /* A link in the chain of data_vios which have been packed together */
130         struct data_vio *next_in_batch;
131
132         /* A vio which is blocked in the packer while holding a lock this vio needs. */
133         struct data_vio *lock_holder;
134
135         /*
136          * The compressed block used to hold the compressed form of this block and that of any
137          * other blocks for which this data_vio is the compressed write agent.
138          */
139         struct compressed_block *block;
140 };
141
142 /* Fields supporting allocation of data blocks. */
143 struct allocation {
144         /* The physical zone in which to allocate a physical block */
145         struct physical_zone *zone;
146
147         /* The block allocated to this vio */
148         physical_block_number_t pbn;
149
150         /*
151          * If non-NULL, the pooled PBN lock held on the allocated block. Must be a write lock until
152          * the block has been written, after which it will become a read lock.
153          */
154         struct pbn_lock *lock;
155
156         /* The type of write lock to obtain on the allocated block */
157         enum pbn_lock_type write_lock_type;
158
159         /* The zone which was the start of the current allocation cycle */
160         zone_count_t first_allocation_zone;
161
162         /* Whether this vio should wait for a clean slab */
163         bool wait_for_clean_slab;
164 };
165
166 struct reference_updater {
167         enum journal_operation operation;
168         bool increment;
169         struct zoned_pbn zpbn;
170         struct pbn_lock *lock;
171         struct vdo_waiter waiter;
172 };
173
174 /* A vio for processing user data requests. */
175 struct data_vio {
176         /* The vdo_wait_queue entry structure */
177         struct vdo_waiter waiter;
178
179         /* The logical block of this request */
180         struct lbn_lock logical;
181
182         /* The state for traversing the block map tree */
183         struct tree_lock tree_lock;
184
185         /* The current partition address of this block */
186         struct zoned_pbn mapped;
187
188         /* The hash of this vio (if not zero) */
189         struct uds_record_name record_name;
190
191         /* Used for logging and debugging */
192         enum async_operation_number last_async_operation;
193
194         /* The operations to record in the recovery and slab journals */
195         struct reference_updater increment_updater;
196         struct reference_updater decrement_updater;
197
198         u16 read : 1;
199         u16 write : 1;
200         u16 fua : 1;
201         u16 is_zero : 1;
202         u16 is_discard : 1;
203         u16 is_partial : 1;
204         u16 is_duplicate : 1;
205         u16 first_reference_operation_complete : 1;
206         u16 downgrade_allocation_lock : 1;
207
208         struct allocation allocation;
209
210         /*
211          * Whether this vio has received an allocation. This field is examined from threads not in
212          * the allocation zone.
213          */
214         bool allocation_succeeded;
215
216         /* The new partition address of this block after the vio write completes */
217         struct zoned_pbn new_mapped;
218
219         /* The hash zone responsible for the name (NULL if is_zero_block) */
220         struct hash_zone *hash_zone;
221
222         /* The lock this vio holds or shares with other vios with the same data */
223         struct hash_lock *hash_lock;
224
225         /* All data_vios sharing a hash lock are kept in a list linking these list entries */
226         struct list_head hash_lock_entry;
227
228         /* The block number in the partition of the UDS deduplication advice */
229         struct zoned_pbn duplicate;
230
231         /*
232          * The sequence number of the recovery journal block containing the increment entry for
233          * this vio.
234          */
235         sequence_number_t recovery_sequence_number;
236
237         /* The point in the recovery journal where this write last made an entry */
238         struct journal_point recovery_journal_point;
239
240         /* The list of vios in user initiated write requests */
241         struct list_head write_entry;
242
243         /* The generation number of the VDO that this vio belongs to */
244         sequence_number_t flush_generation;
245
246         /* The completion to use for fetching block map pages for this vio */
247         struct vdo_page_completion page_completion;
248
249         /* The user bio that initiated this VIO */
250         struct bio *user_bio;
251
252         /* partial block support */
253         block_size_t offset;
254
255         /*
256          * The number of bytes to be discarded. For discards, this field will always be positive,
257          * whereas for non-discards it will always be 0. Hence it can be used to determine whether
258          * a data_vio is processing a discard, even after the user_bio has been acknowledged.
259          */
260         u32 remaining_discard;
261
262         struct dedupe_context *dedupe_context;
263
264         /* Fields beyond this point will not be reset when a pooled data_vio is reused. */
265
266         struct vio vio;
267
268         /* The completion for making reference count decrements */
269         struct vdo_completion decrement_completion;
270
271         /* All of the fields necessary for the compression path */
272         struct compression_state compression;
273
274         /* A block used as output during compression or uncompression */
275         char *scratch_block;
276
277         struct list_head pool_entry;
278 };
279
280 static inline struct data_vio *vio_as_data_vio(struct vio *vio)
281 {
282         ASSERT_LOG_ONLY((vio->type == VIO_TYPE_DATA), "vio is a data_vio");
283         return container_of(vio, struct data_vio, vio);
284 }
285
286 static inline struct data_vio *as_data_vio(struct vdo_completion *completion)
287 {
288         return vio_as_data_vio(as_vio(completion));
289 }
290
291 static inline struct data_vio *vdo_waiter_as_data_vio(struct vdo_waiter *waiter)
292 {
293         if (waiter == NULL)
294                 return NULL;
295
296         return container_of(waiter, struct data_vio, waiter);
297 }
298
299 static inline struct data_vio *data_vio_from_reference_updater(struct reference_updater *updater)
300 {
301         if (updater->increment)
302                 return container_of(updater, struct data_vio, increment_updater);
303
304         return container_of(updater, struct data_vio, decrement_updater);
305 }
306
307 static inline bool data_vio_has_flush_generation_lock(struct data_vio *data_vio)
308 {
309         return !list_empty(&data_vio->write_entry);
310 }
311
312 static inline struct vdo *vdo_from_data_vio(struct data_vio *data_vio)
313 {
314         return data_vio->vio.completion.vdo;
315 }
316
317 static inline bool data_vio_has_allocation(struct data_vio *data_vio)
318 {
319         return (data_vio->allocation.pbn != VDO_ZERO_BLOCK);
320 }
321
322 struct data_vio_compression_status __must_check
323 advance_data_vio_compression_stage(struct data_vio *data_vio);
324 struct data_vio_compression_status __must_check
325 get_data_vio_compression_status(struct data_vio *data_vio);
326 bool cancel_data_vio_compression(struct data_vio *data_vio);
327
328 struct data_vio_pool;
329
330 int make_data_vio_pool(struct vdo *vdo, data_vio_count_t pool_size,
331                        data_vio_count_t discard_limit, struct data_vio_pool **pool_ptr);
332 void free_data_vio_pool(struct data_vio_pool *pool);
333 void vdo_launch_bio(struct data_vio_pool *pool, struct bio *bio);
334 void drain_data_vio_pool(struct data_vio_pool *pool, struct vdo_completion *completion);
335 void resume_data_vio_pool(struct data_vio_pool *pool, struct vdo_completion *completion);
336
337 void dump_data_vio_pool(struct data_vio_pool *pool, bool dump_vios);
338 data_vio_count_t get_data_vio_pool_active_discards(struct data_vio_pool *pool);
339 data_vio_count_t get_data_vio_pool_discard_limit(struct data_vio_pool *pool);
340 data_vio_count_t get_data_vio_pool_maximum_discards(struct data_vio_pool *pool);
341 int __must_check set_data_vio_pool_discard_limit(struct data_vio_pool *pool,
342                                                  data_vio_count_t limit);
343 data_vio_count_t get_data_vio_pool_active_requests(struct data_vio_pool *pool);
344 data_vio_count_t get_data_vio_pool_request_limit(struct data_vio_pool *pool);
345 data_vio_count_t get_data_vio_pool_maximum_requests(struct data_vio_pool *pool);
346
347 void complete_data_vio(struct vdo_completion *completion);
348 void handle_data_vio_error(struct vdo_completion *completion);
349
350 static inline void continue_data_vio(struct data_vio *data_vio)
351 {
352         vdo_launch_completion(&data_vio->vio.completion);
353 }
354
355 /**
356  * continue_data_vio_with_error() - Set an error code and then continue processing a data_vio.
357  *
358  * This will not mask older errors. This function can be called with a success code, but it is more
359  * efficient to call continue_data_vio() if the caller knows the result was a success.
360  */
361 static inline void continue_data_vio_with_error(struct data_vio *data_vio, int result)
362 {
363         vdo_continue_completion(&data_vio->vio.completion, result);
364 }
365
366 const char * __must_check get_data_vio_operation_name(struct data_vio *data_vio);
367
368 static inline void assert_data_vio_in_hash_zone(struct data_vio *data_vio)
369 {
370         thread_id_t expected = data_vio->hash_zone->thread_id;
371         thread_id_t thread_id = vdo_get_callback_thread_id();
372         /*
373          * It's odd to use the LBN, but converting the record name to hex is a bit clunky for an
374          * inline, and the LBN better than nothing as an identifier.
375          */
376         ASSERT_LOG_ONLY((expected == thread_id),
377                         "data_vio for logical block %llu on thread %u, should be on hash zone thread %u",
378                         (unsigned long long) data_vio->logical.lbn, thread_id, expected);
379 }
380
381 static inline void set_data_vio_hash_zone_callback(struct data_vio *data_vio,
382                                                    vdo_action_fn callback)
383 {
384         vdo_set_completion_callback(&data_vio->vio.completion, callback,
385                                     data_vio->hash_zone->thread_id);
386 }
387
388 /**
389  * launch_data_vio_hash_zone_callback() - Set a callback as a hash zone operation and invoke it
390  *                                        immediately.
391  */
392 static inline void launch_data_vio_hash_zone_callback(struct data_vio *data_vio,
393                                                       vdo_action_fn callback)
394 {
395         set_data_vio_hash_zone_callback(data_vio, callback);
396         vdo_launch_completion(&data_vio->vio.completion);
397 }
398
399 static inline void assert_data_vio_in_logical_zone(struct data_vio *data_vio)
400 {
401         thread_id_t expected = data_vio->logical.zone->thread_id;
402         thread_id_t thread_id = vdo_get_callback_thread_id();
403
404         ASSERT_LOG_ONLY((expected == thread_id),
405                         "data_vio for logical block %llu on thread %u, should be on thread %u",
406                         (unsigned long long) data_vio->logical.lbn, thread_id, expected);
407 }
408
409 static inline void set_data_vio_logical_callback(struct data_vio *data_vio,
410                                                  vdo_action_fn callback)
411 {
412         vdo_set_completion_callback(&data_vio->vio.completion, callback,
413                                     data_vio->logical.zone->thread_id);
414 }
415
416 /**
417  * launch_data_vio_logical_callback() - Set a callback as a logical block operation and invoke it
418  *                                      immediately.
419  */
420 static inline void launch_data_vio_logical_callback(struct data_vio *data_vio,
421                                                     vdo_action_fn callback)
422 {
423         set_data_vio_logical_callback(data_vio, callback);
424         vdo_launch_completion(&data_vio->vio.completion);
425 }
426
427 static inline void assert_data_vio_in_allocated_zone(struct data_vio *data_vio)
428 {
429         thread_id_t expected = data_vio->allocation.zone->thread_id;
430         thread_id_t thread_id = vdo_get_callback_thread_id();
431
432         ASSERT_LOG_ONLY((expected == thread_id),
433                         "struct data_vio for allocated physical block %llu on thread %u, should be on thread %u",
434                         (unsigned long long) data_vio->allocation.pbn, thread_id,
435                         expected);
436 }
437
438 static inline void set_data_vio_allocated_zone_callback(struct data_vio *data_vio,
439                                                         vdo_action_fn callback)
440 {
441         vdo_set_completion_callback(&data_vio->vio.completion, callback,
442                                     data_vio->allocation.zone->thread_id);
443 }
444
445 /**
446  * launch_data_vio_allocated_zone_callback() - Set a callback as a physical block operation in a
447  *                                             data_vio's allocated zone and queue the data_vio and
448  *                                             invoke it immediately.
449  */
450 static inline void launch_data_vio_allocated_zone_callback(struct data_vio *data_vio,
451                                                            vdo_action_fn callback)
452 {
453         set_data_vio_allocated_zone_callback(data_vio, callback);
454         vdo_launch_completion(&data_vio->vio.completion);
455 }
456
457 static inline void assert_data_vio_in_duplicate_zone(struct data_vio *data_vio)
458 {
459         thread_id_t expected = data_vio->duplicate.zone->thread_id;
460         thread_id_t thread_id = vdo_get_callback_thread_id();
461
462         ASSERT_LOG_ONLY((expected == thread_id),
463                         "data_vio for duplicate physical block %llu on thread %u, should be on thread %u",
464                         (unsigned long long) data_vio->duplicate.pbn, thread_id,
465                         expected);
466 }
467
468 static inline void set_data_vio_duplicate_zone_callback(struct data_vio *data_vio,
469                                                         vdo_action_fn callback)
470 {
471         vdo_set_completion_callback(&data_vio->vio.completion, callback,
472                                     data_vio->duplicate.zone->thread_id);
473 }
474
475 /**
476  * launch_data_vio_duplicate_zone_callback() - Set a callback as a physical block operation in a
477  *                                             data_vio's duplicate zone and queue the data_vio and
478  *                                             invoke it immediately.
479  */
480 static inline void launch_data_vio_duplicate_zone_callback(struct data_vio *data_vio,
481                                                            vdo_action_fn callback)
482 {
483         set_data_vio_duplicate_zone_callback(data_vio, callback);
484         vdo_launch_completion(&data_vio->vio.completion);
485 }
486
487 static inline void assert_data_vio_in_mapped_zone(struct data_vio *data_vio)
488 {
489         thread_id_t expected = data_vio->mapped.zone->thread_id;
490         thread_id_t thread_id = vdo_get_callback_thread_id();
491
492         ASSERT_LOG_ONLY((expected == thread_id),
493                         "data_vio for mapped physical block %llu on thread %u, should be on thread %u",
494                         (unsigned long long) data_vio->mapped.pbn, thread_id, expected);
495 }
496
497 static inline void set_data_vio_mapped_zone_callback(struct data_vio *data_vio,
498                                                      vdo_action_fn callback)
499 {
500         vdo_set_completion_callback(&data_vio->vio.completion, callback,
501                                     data_vio->mapped.zone->thread_id);
502 }
503
504 static inline void assert_data_vio_in_new_mapped_zone(struct data_vio *data_vio)
505 {
506         thread_id_t expected = data_vio->new_mapped.zone->thread_id;
507         thread_id_t thread_id = vdo_get_callback_thread_id();
508
509         ASSERT_LOG_ONLY((expected == thread_id),
510                         "data_vio for new_mapped physical block %llu on thread %u, should be on thread %u",
511                         (unsigned long long) data_vio->new_mapped.pbn, thread_id,
512                         expected);
513 }
514
515 static inline void set_data_vio_new_mapped_zone_callback(struct data_vio *data_vio,
516                                                          vdo_action_fn callback)
517 {
518         vdo_set_completion_callback(&data_vio->vio.completion, callback,
519                                     data_vio->new_mapped.zone->thread_id);
520 }
521
522 static inline void assert_data_vio_in_journal_zone(struct data_vio *data_vio)
523 {
524         thread_id_t journal_thread = vdo_from_data_vio(data_vio)->thread_config.journal_thread;
525         thread_id_t thread_id = vdo_get_callback_thread_id();
526
527         ASSERT_LOG_ONLY((journal_thread == thread_id),
528                         "data_vio for logical block %llu on thread %u, should be on journal thread %u",
529                         (unsigned long long) data_vio->logical.lbn, thread_id,
530                         journal_thread);
531 }
532
533 static inline void set_data_vio_journal_callback(struct data_vio *data_vio,
534                                                  vdo_action_fn callback)
535 {
536         thread_id_t journal_thread = vdo_from_data_vio(data_vio)->thread_config.journal_thread;
537
538         vdo_set_completion_callback(&data_vio->vio.completion, callback, journal_thread);
539 }
540
541 /**
542  * launch_data_vio_journal_callback() - Set a callback as a journal operation and invoke it
543  *                                      immediately.
544  */
545 static inline void launch_data_vio_journal_callback(struct data_vio *data_vio,
546                                                     vdo_action_fn callback)
547 {
548         set_data_vio_journal_callback(data_vio, callback);
549         vdo_launch_completion(&data_vio->vio.completion);
550 }
551
552 static inline void assert_data_vio_in_packer_zone(struct data_vio *data_vio)
553 {
554         thread_id_t packer_thread = vdo_from_data_vio(data_vio)->thread_config.packer_thread;
555         thread_id_t thread_id = vdo_get_callback_thread_id();
556
557         ASSERT_LOG_ONLY((packer_thread == thread_id),
558                         "data_vio for logical block %llu on thread %u, should be on packer thread %u",
559                         (unsigned long long) data_vio->logical.lbn, thread_id,
560                         packer_thread);
561 }
562
563 static inline void set_data_vio_packer_callback(struct data_vio *data_vio,
564                                                 vdo_action_fn callback)
565 {
566         thread_id_t packer_thread = vdo_from_data_vio(data_vio)->thread_config.packer_thread;
567
568         vdo_set_completion_callback(&data_vio->vio.completion, callback, packer_thread);
569 }
570
571 /**
572  * launch_data_vio_packer_callback() - Set a callback as a packer operation and invoke it
573  *                                     immediately.
574  */
575 static inline void launch_data_vio_packer_callback(struct data_vio *data_vio,
576                                                    vdo_action_fn callback)
577 {
578         set_data_vio_packer_callback(data_vio, callback);
579         vdo_launch_completion(&data_vio->vio.completion);
580 }
581
582 static inline void assert_data_vio_on_cpu_thread(struct data_vio *data_vio)
583 {
584         thread_id_t cpu_thread = vdo_from_data_vio(data_vio)->thread_config.cpu_thread;
585         thread_id_t thread_id = vdo_get_callback_thread_id();
586
587         ASSERT_LOG_ONLY((cpu_thread == thread_id),
588                         "data_vio for logical block %llu on thread %u, should be on cpu thread %u",
589                         (unsigned long long) data_vio->logical.lbn, thread_id,
590                         cpu_thread);
591 }
592
593 static inline void set_data_vio_cpu_callback(struct data_vio *data_vio,
594                                              vdo_action_fn callback)
595 {
596         thread_id_t cpu_thread = vdo_from_data_vio(data_vio)->thread_config.cpu_thread;
597
598         vdo_set_completion_callback(&data_vio->vio.completion, callback, cpu_thread);
599 }
600
601 /**
602  * launch_data_vio_cpu_callback() - Set a callback to run on the CPU queues and invoke it
603  *                                  immediately.
604  */
605 static inline void launch_data_vio_cpu_callback(struct data_vio *data_vio,
606                                                 vdo_action_fn callback,
607                                                 enum vdo_completion_priority priority)
608 {
609         set_data_vio_cpu_callback(data_vio, callback);
610         vdo_launch_completion_with_priority(&data_vio->vio.completion, priority);
611 }
612
613 static inline void set_data_vio_bio_zone_callback(struct data_vio *data_vio,
614                                                   vdo_action_fn callback)
615 {
616         vdo_set_completion_callback(&data_vio->vio.completion, callback,
617                                     get_vio_bio_zone_thread_id(&data_vio->vio));
618 }
619
620 /**
621  * launch_data_vio_bio_zone_callback() - Set a callback as a bio zone operation and invoke it
622  *                                       immediately.
623  */
624 static inline void launch_data_vio_bio_zone_callback(struct data_vio *data_vio,
625                                                      vdo_action_fn callback)
626 {
627         set_data_vio_bio_zone_callback(data_vio, callback);
628         vdo_launch_completion_with_priority(&data_vio->vio.completion,
629                                             BIO_Q_DATA_PRIORITY);
630 }
631
632 /**
633  * launch_data_vio_on_bio_ack_queue() - If the vdo uses a bio_ack queue, set a callback to run on
634  *                                      it and invoke it immediately, otherwise, just run the
635  *                                      callback on the current thread.
636  */
637 static inline void launch_data_vio_on_bio_ack_queue(struct data_vio *data_vio,
638                                                     vdo_action_fn callback)
639 {
640         struct vdo_completion *completion = &data_vio->vio.completion;
641         struct vdo *vdo = completion->vdo;
642
643         if (!vdo_uses_bio_ack_queue(vdo)) {
644                 callback(completion);
645                 return;
646         }
647
648         vdo_set_completion_callback(completion, callback,
649                                     vdo->thread_config.bio_ack_thread);
650         vdo_launch_completion_with_priority(completion, BIO_ACK_Q_ACK_PRIORITY);
651 }
652
653 void data_vio_allocate_data_block(struct data_vio *data_vio,
654                                   enum pbn_lock_type write_lock_type,
655                                   vdo_action_fn callback, vdo_action_fn error_handler);
656
657 void release_data_vio_allocation_lock(struct data_vio *data_vio, bool reset);
658
659 int __must_check uncompress_data_vio(struct data_vio *data_vio,
660                                      enum block_mapping_state mapping_state,
661                                      char *buffer);
662
663 void update_metadata_for_data_vio_write(struct data_vio *data_vio,
664                                         struct pbn_lock *lock);
665 void write_data_vio(struct data_vio *data_vio);
666 void launch_compress_data_vio(struct data_vio *data_vio);
667 void continue_data_vio_with_block_map_slot(struct vdo_completion *completion);
668
669 #endif /* DATA_VIO_H */