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 */ 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