forked from openzfs/zfs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request openzfs#567 from delphix/projects/merge-upstream/m…
…aster Merge remote-tracking branch '6.0/stage' into 'master'
- Loading branch information
Showing
24 changed files
with
1,037 additions
and
573 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use bit_set::BitSet; | ||
|
||
use crate::from64::AsUsize; | ||
|
||
/// A "range filter" allows quickly checking if a given offset might be in a set of ranges. It | ||
/// is similar to a Bloom filter, but requires that keys be ordered rather than hashable. | ||
pub struct RangeFilter { | ||
chunk_shift: u32, | ||
bits: BitSet, | ||
} | ||
|
||
impl RangeFilter { | ||
/// Create a new range filter with the given chunk size. The range of values will be divided | ||
/// into power-of-two chunks based on this. | ||
pub fn new(chunk_size: u64) -> Self { | ||
Self { | ||
chunk_shift: chunk_size.next_power_of_two().trailing_zeros(), | ||
bits: Default::default(), | ||
} | ||
} | ||
|
||
/// The `size` needs to be specified even if it's always <= `chunk_size`, because the `start` | ||
/// is not required to be aligned to `chunk_size` and thus the region may span multiple | ||
/// chunks. For example, in the remap code the slabs are offset from the beginning of the | ||
/// disk by 4KB. | ||
#[inline] | ||
pub fn insert(&mut self, start: u64, size: u64) { | ||
let start_index = start >> self.chunk_shift; | ||
let end_index = (start + size - 1) >> self.chunk_shift; | ||
for i in start_index..=end_index { | ||
self.bits.insert(i.as_usize()); | ||
} | ||
} | ||
|
||
/// Check if the given offset might be in the set of ranges. May return `true` even if the | ||
/// offset is not present but there are nearby ranges present (within the `chunk_size` | ||
/// specified to `new()`). If this returns `false`, the offset is definitely not present. | ||
#[inline] | ||
pub fn maybe_present(&self, value: u64) -> bool { | ||
let index = value.wrapping_shr(self.chunk_shift); | ||
self.bits.contains(index.as_usize()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
use std::sync::Arc; | ||
|
||
use async_trait::async_trait; | ||
use tokio::sync::AcquireError; | ||
use tokio::sync::Semaphore; | ||
|
||
pub struct SplittableOwnedSemaphorePermit { | ||
sem: Arc<Semaphore>, | ||
permits: u32, | ||
} | ||
|
||
#[async_trait] | ||
pub trait SemaphoreExt { | ||
async fn acquire_splittable( | ||
self: Arc<Self>, | ||
n: u32, | ||
) -> Result<SplittableOwnedSemaphorePermit, AcquireError>; | ||
} | ||
|
||
#[async_trait] | ||
impl SemaphoreExt for tokio::sync::Semaphore { | ||
/// Like `acquire_many_owned()`, but allows the returned guard to be split into multiple | ||
/// guards, each representing a subset of the N permits. | ||
async fn acquire_splittable( | ||
self: Arc<Self>, | ||
n: u32, | ||
) -> Result<SplittableOwnedSemaphorePermit, AcquireError> { | ||
self.clone().acquire_many_owned(n).await?.forget(); | ||
Ok(SplittableOwnedSemaphorePermit { | ||
sem: self, | ||
permits: n, | ||
}) | ||
} | ||
} | ||
|
||
impl SplittableOwnedSemaphorePermit { | ||
/// Split off N permits from this permit to a new instance. The new permit will have N | ||
/// permits, and this permit will have N fewer permits. This allows some of the permits to | ||
/// be released separately. | ||
/// | ||
/// # Panics | ||
/// Panics if the number of permits to release is greater than the number of permits. | ||
pub fn split(&mut self, n: u32) -> Self { | ||
self.permits -= n; | ||
Self { | ||
sem: self.sem.clone(), | ||
permits: n, | ||
} | ||
} | ||
|
||
/// Forgets the permit **without** releasing it back to the semaphore. This can be used to | ||
/// reduce the amount of permits available from a semaphore. | ||
pub fn forget(mut self) { | ||
self.permits = 0; | ||
} | ||
} | ||
|
||
impl Drop for SplittableOwnedSemaphorePermit { | ||
fn drop(&mut self) { | ||
self.sem.add_permits(self.permits as usize); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.