1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * Copyright 2023 Red Hat
4 */
5
6 #ifndef VDO_PHYSICAL_ZONE_H
7 #define VDO_PHYSICAL_ZONE_H
8
9 #include <linux/atomic.h>
10
11 #include "types.h"
12
13 /*
14 * The type of a PBN lock.
15 */
16 enum pbn_lock_type {
17 VIO_READ_LOCK,
18 VIO_WRITE_LOCK,
19 VIO_BLOCK_MAP_WRITE_LOCK,
20 };
21
22 struct pbn_lock_implementation;
23
24 /*
25 * A PBN lock.
26 */
27 struct pbn_lock {
28 /* The implementation of the lock */
29 const struct pbn_lock_implementation *implementation;
30
31 /* The number of VIOs holding or sharing this lock */
32 data_vio_count_t holder_count;
33 /*
34 * The number of compressed block writers holding a share of this lock while they are
35 * acquiring a reference to the PBN.
36 */
37 u8 fragment_locks;
38
39 /* Whether the locked PBN has been provisionally referenced on behalf of the lock holder. */
40 bool has_provisional_reference;
41
42 /*
43 * For read locks, the number of references that were known to be available on the locked
44 * block at the time the lock was acquired.
45 */
46 u8 increment_limit;
47
48 /*
49 * For read locks, the number of data_vios that have tried to claim one of the available
50 * increments during the lifetime of the lock. Each claim will first increment this
51 * counter, so it can exceed the increment limit.
52 */
53 atomic_t increments_claimed;
54 };
55
56 struct physical_zone {
57 /* Which physical zone this is */
58 zone_count_t zone_number;
59 /* The thread ID for this zone */
60 thread_id_t thread_id;
61 /* In progress operations keyed by PBN */
62 struct int_map *pbn_operations;
63 /* Pool of unused pbn_lock instances */
64 struct pbn_lock_pool *lock_pool;
65 /* The block allocator for this zone */
66 struct block_allocator *allocator;
67 /* The next zone from which to attempt an allocation */
68 struct physical_zone *next;
69 };
70
71 struct physical_zones {
72 /* The number of zones */
73 zone_count_t zone_count;
74 /* The physical zones themselves */
75 struct physical_zone zones[];
76 };
77
78 bool __must_check vdo_is_pbn_read_lock(const struct pbn_lock *lock);
79 void vdo_downgrade_pbn_write_lock(struct pbn_lock *lock, bool compressed_write);
80 bool __must_check vdo_claim_pbn_lock_increment(struct pbn_lock *lock);
81
82 /**
83 * vdo_pbn_lock_has_provisional_reference() - Check whether a PBN lock has a provisional reference.
84 * @lock: The PBN lock.
85 */
vdo_pbn_lock_has_provisional_reference(struct pbn_lock * lock)86 static inline bool vdo_pbn_lock_has_provisional_reference(struct pbn_lock *lock)
87 {
88 return ((lock != NULL) && lock->has_provisional_reference);
89 }
90
91 void vdo_assign_pbn_lock_provisional_reference(struct pbn_lock *lock);
92 void vdo_unassign_pbn_lock_provisional_reference(struct pbn_lock *lock);
93
94 int __must_check vdo_make_physical_zones(struct vdo *vdo,
95 struct physical_zones **zones_ptr);
96
97 void vdo_free_physical_zones(struct physical_zones *zones);
98
99 struct pbn_lock * __must_check vdo_get_physical_zone_pbn_lock(struct physical_zone *zone,
100 physical_block_number_t pbn);
101
102 int __must_check vdo_attempt_physical_zone_pbn_lock(struct physical_zone *zone,
103 physical_block_number_t pbn,
104 enum pbn_lock_type type,
105 struct pbn_lock **lock_ptr);
106
107 bool __must_check vdo_allocate_block_in_zone(struct data_vio *data_vio);
108
109 void vdo_release_physical_zone_pbn_lock(struct physical_zone *zone,
110 physical_block_number_t locked_pbn,
111 struct pbn_lock *lock);
112
113 void vdo_dump_physical_zone(const struct physical_zone *zone);
114
115 #endif /* VDO_PHYSICAL_ZONE_H */
116