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