/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright 2023 Red Hat */ #ifndef VDO_PHYSICAL_ZONE_H #define VDO_PHYSICAL_ZONE_H #include #include "types.h" /* * The type of a PBN lock. */ enum pbn_lock_type { VIO_READ_LOCK, VIO_WRITE_LOCK, VIO_BLOCK_MAP_WRITE_LOCK, }; struct pbn_lock_implementation; /* * A PBN lock. */ struct pbn_lock { /* The implementation of the lock */ const struct pbn_lock_implementation *implementation; /* The number of VIOs holding or sharing this lock */ data_vio_count_t holder_count; /* * The number of compressed block writers holding a share of this lock while they are * acquiring a reference to the PBN. */ u8 fragment_locks; /* Whether the locked PBN has been provisionally referenced on behalf of the lock holder. */ bool has_provisional_reference; /* * For read locks, the number of references that were known to be available on the locked * block at the time the lock was acquired. */ u8 increment_limit; /* * For read locks, the number of data_vios that have tried to claim one of the available * increments during the lifetime of the lock. Each claim will first increment this * counter, so it can exceed the increment limit. */ atomic_t increments_claimed; }; struct physical_zone { /* Which physical zone this is */ zone_count_t zone_number; /* The thread ID for this zone */ thread_id_t thread_id; /* In progress operations keyed by PBN */ struct int_map *pbn_operations; /* Pool of unused pbn_lock instances */ struct pbn_lock_pool *lock_pool; /* The block allocator for this zone */ struct block_allocator *allocator; /* The next zone from which to attempt an allocation */ struct physical_zone *next; }; struct physical_zones { /* The number of zones */ zone_count_t zone_count; /* The physical zones themselves */ struct physical_zone zones[]; }; bool __must_check vdo_is_pbn_read_lock(const struct pbn_lock *lock); void vdo_downgrade_pbn_write_lock(struct pbn_lock *lock, bool compressed_write); bool __must_check vdo_claim_pbn_lock_increment(struct pbn_lock *lock); /** * vdo_pbn_lock_has_provisional_reference() - Check whether a PBN lock has a provisional reference. * @lock: The PBN lock. */ static inline bool vdo_pbn_lock_has_provisional_reference(struct pbn_lock *lock) { return ((lock != NULL) && lock->has_provisional_reference); } void vdo_assign_pbn_lock_provisional_reference(struct pbn_lock *lock); void vdo_unassign_pbn_lock_provisional_reference(struct pbn_lock *lock); int __must_check vdo_make_physical_zones(struct vdo *vdo, struct physical_zones **zones_ptr); void vdo_free_physical_zones(struct physical_zones *zones); struct pbn_lock * __must_check vdo_get_physical_zone_pbn_lock(struct physical_zone *zone, physical_block_number_t pbn); int __must_check vdo_attempt_physical_zone_pbn_lock(struct physical_zone *zone, physical_block_number_t pbn, enum pbn_lock_type type, struct pbn_lock **lock_ptr); bool __must_check vdo_allocate_block_in_zone(struct data_vio *data_vio); void vdo_release_physical_zone_pbn_lock(struct physical_zone *zone, physical_block_number_t locked_pbn, struct pbn_lock *lock); void vdo_dump_physical_zone(const struct physical_zone *zone); #endif /* VDO_PHYSICAL_ZONE_H */