pub struct DataObjectHandle<S: HandleOwner> { /* private fields */ }
Expand description
DataObjectHandle is a typed handle for file-like objects that store data in the default data attribute. In addition to traditional files, this means things like the journal, superblocks, and layer files.
It caches the content size of the data attribute it was configured for, and has helpers for complex extent manipulation, as well as implementations of ReadObjectHandle and WriteObjectHandle.
Implementations§
Source§impl<S: HandleOwner> DataObjectHandle<S>
impl<S: HandleOwner> DataObjectHandle<S>
pub fn new( owner: Arc<S>, object_id: u64, permanent_keys: bool, attribute_id: u64, size: u64, fsverity_state: FsverityState, options: HandleOptions, trace: bool, overwrite_ranges: Vec<Range<u64>>, ) -> Self
pub fn attribute_id(&self) -> u64
pub fn overwrite_ranges(&self) -> &AllocatedRanges
pub fn is_verified_file(&self) -> bool
Sourcepub fn set_fsverity_state_started(&self) -> Result<(), Error>
pub fn set_fsverity_state_started(&self) -> Result<(), Error>
Sets self.fsverity_state
to FsverityState::Started. Called at the top of enable_verity
.
If another caller has already started but not completed enabled_verity
, returns
FxfsError::AlreadyBound. If another caller has already completed enable_verity
, returns
FxfsError::AlreadyExists.
Sourcepub fn set_fsverity_state_pending(
&self,
descriptor: FsverityMetadata,
merkle_tree: Box<[u8]>,
)
pub fn set_fsverity_state_pending( &self, descriptor: FsverityMetadata, merkle_tree: Box<[u8]>, )
Sets self.fsverity_state
to Pending. Must be called before finalize_fsverity_state()
.
Asserts that the prior state of self.fsverity_state
was FsverityState::Started
.
Sourcepub fn finalize_fsverity_state(&self)
pub fn finalize_fsverity_state(&self)
Sets self.fsverity_state
to Some. Panics if the prior state of self.fsverity_state
was
not FsverityState::Pending(_)
.
Sourcepub fn set_fsverity_state_some(
&self,
descriptor: FsverityMetadata,
merkle_tree: Box<[u8]>,
)
pub fn set_fsverity_state_some( &self, descriptor: FsverityMetadata, merkle_tree: Box<[u8]>, )
Sets self.fsverity_state
directly to Some without going through the entire state machine.
Used to set self.fsverity_state
on open of a verified file.
Sourcepub async fn extend<'a>(
&'a self,
transaction: &mut Transaction<'a>,
device_range: Range<u64>,
) -> Result<(), Error>
pub async fn extend<'a>( &'a self, transaction: &mut Transaction<'a>, device_range: Range<u64>, ) -> Result<(), Error>
Extend the file with the given extent. The only use case for this right now is for files that must exist at certain offsets on the device, such as super-blocks.
Sourcepub async fn zero(
&self,
transaction: &mut Transaction<'_>,
range: Range<u64>,
) -> Result<(), Error>
pub async fn zero( &self, transaction: &mut Transaction<'_>, range: Range<u64>, ) -> Result<(), Error>
Zeroes the given range. The range must be aligned. Returns the amount of data deallocated.
Sourcepub async fn get_descriptor(
&self,
) -> Result<Option<(VerificationOptions, Vec<u8>)>, Error>
pub async fn get_descriptor( &self, ) -> Result<Option<(VerificationOptions, Vec<u8>)>, Error>
The cached value for self.fsverity_state
is set either in open_object
or on
enable_verity
. If set, translates self.fsverity_state.descriptor
into an
fio::VerificationOptions instance and a root hash. Otherwise, returns None.
Sourcepub async fn enable_verity(
&self,
options: VerificationOptions,
) -> Result<(), Error>
pub async fn enable_verity( &self, options: VerificationOptions, ) -> Result<(), Error>
Reads the data attribute and computes a merkle tree from the data. The values of the
parameters required to build the merkle tree are supplied by descriptor
(i.e. salt,
hash_algorithm, etc.) Writes the leaf nodes of the merkle tree to an attribute with id
FSVERITY_MERKLE_ATTRIBUTE_ID
. Updates the root_hash of the descriptor
according to the
computed merkle tree and then replaces the ObjectValue of the data attribute with
ObjectValue::VerifiedAttribute, which stores the descriptor
inline.
Sourcepub async fn allocate(&self, range: Range<u64>) -> Result<(), Error>
pub async fn allocate(&self, range: Range<u64>) -> Result<(), Error>
Pre-allocate disk space for the given logical file range. If any part of the allocation range is beyond the end of the file, the file size is updated.
Sourcepub async fn is_allocated(
&self,
start_offset: u64,
) -> Result<(bool, u64), Error>
pub async fn is_allocated( &self, start_offset: u64, ) -> Result<(bool, u64), Error>
Return information on a contiguous set of extents that has the same allocation status,
starting from start_offset
. The information returned is if this set of extents are marked
allocated/not allocated and also the size of this set (in bytes). This is used when
querying slices for volumes.
This function expects start_offset
to be aligned to block size
pub async fn txn_write<'a>( &'a self, transaction: &mut Transaction<'a>, offset: u64, buf: BufferRef<'_>, ) -> Result<(), Error>
pub async fn multi_write<'a>( &'a self, transaction: &mut Transaction<'a>, attribute_id: u64, ranges: &[Range<u64>], buf: MutableBufferRef<'_>, ) -> Result<(), Error>
pub async fn overwrite( &self, offset: u64, buf: MutableBufferRef<'_>, allow_allocations: bool, ) -> Result<(), Error>
pub async fn txn_update_size<'a>( &'a self, transaction: &mut Transaction<'a>, new_size: u64, update_has_overwrite_extents: Option<bool>, ) -> Result<(), Error>
pub fn truncate_overwrite_ranges( &self, size: u64, ) -> Result<Option<bool>, Error>
pub async fn shrink<'a>( &'a self, transaction: &mut Transaction<'a>, size: u64, update_has_overwrite_extents: Option<bool>, ) -> Result<NeedsTrim, Error>
pub async fn grow<'a>( &'a self, transaction: &mut Transaction<'a>, old_size: u64, size: u64, ) -> Result<(), Error>
Sourcepub async fn preallocate_range<'a>(
&'a self,
transaction: &mut Transaction<'a>,
file_range: &mut Range<u64>,
) -> Result<Vec<Range<u64>>, Error>
pub async fn preallocate_range<'a>( &'a self, transaction: &mut Transaction<'a>, file_range: &mut Range<u64>, ) -> Result<Vec<Range<u64>>, Error>
Attempts to pre-allocate a file_range
of bytes for this object.
Returns a set of device ranges (i.e. potentially multiple extents).
It may not be possible to preallocate the entire requested range in one request due to limitations on transaction size. In such cases, we will preallocate as much as we can up to some (arbitrary, internal) limit on transaction size.
file_range.start
is modified to point at the end of the logical range
that was preallocated such that repeated calls to preallocate_range
with new
transactions can be used to preallocate ranges of any size.
Requested range must be a multiple of block size.
pub async fn update_attributes<'a>( &self, transaction: &mut Transaction<'a>, node_attributes: Option<&MutableNodeAttributes>, change_time: Option<Timestamp>, ) -> Result<(), Error>
Sourcepub fn default_transaction_options<'b>(&self) -> Options<'b>
pub fn default_transaction_options<'b>(&self) -> Options<'b>
Get the default set of transaction options for this object. This is mostly the overall
default, modified by any HandleOptions
held by this handle.
pub async fn new_transaction<'b>(&self) -> Result<Transaction<'b>, Error>
pub async fn new_transaction_with_options<'b>( &self, options: Options<'b>, ) -> Result<Transaction<'b>, Error>
Sourcepub async fn flush_device(&self) -> Result<(), Error>
pub async fn flush_device(&self) -> Result<(), Error>
Flushes the underlying device. This is expensive and should be used sparingly.
Sourcepub async fn read_attr(
&self,
attribute_id: u64,
) -> Result<Option<Box<[u8]>>, Error>
pub async fn read_attr( &self, attribute_id: u64, ) -> Result<Option<Box<[u8]>>, Error>
Reads an entire attribute.
Sourcepub async fn write_attr(
&self,
attribute_id: u64,
data: &[u8],
) -> Result<(), Error>
pub async fn write_attr( &self, attribute_id: u64, data: &[u8], ) -> Result<(), Error>
Writes an entire attribute. This always uses the volume data key.
Sourcepub async fn truncate_with_options(
&self,
options: Options<'_>,
size: u64,
) -> Result<(), Error>
pub async fn truncate_with_options( &self, options: Options<'_>, size: u64, ) -> Result<(), Error>
Truncates a file to a given size (growing/shrinking as required).
Nb: Most code will want to call truncate() instead. This method is used to update the super block – a case where we must borrow metadata space.
pub async fn get_properties(&self) -> Result<ObjectProperties, Error>
pub async fn contents(&self, limit: usize) -> Result<Box<[u8]>, Error>
Methods from Deref<Target = StoreObjectHandle<S>>§
pub fn owner(&self) -> &Arc<S>
pub fn store(&self) -> &ObjectStore
pub fn trace(&self) -> bool
pub fn is_encrypted(&self) -> bool
Sourcepub fn default_transaction_options<'b>(&self) -> Options<'b>
pub fn default_transaction_options<'b>(&self) -> Options<'b>
Get the default set of transaction options for this object. This is mostly the overall
default, modified by any HandleOptions
held by this handle.
pub async fn new_transaction_with_options<'b>( &self, attribute_id: u64, options: Options<'b>, ) -> Result<Transaction<'b>, Error>
pub async fn new_transaction<'b>( &self, attribute_id: u64, ) -> Result<Transaction<'b>, Error>
Sourcepub async fn flush_device(&self) -> Result<(), Error>
pub async fn flush_device(&self) -> Result<(), Error>
Flushes the underlying device. This is expensive and should be used sparingly.
pub async fn update_allocated_size( &self, transaction: &mut Transaction<'_>, allocated: u64, deallocated: u64, ) -> Result<(), Error>
pub async fn update_attributes<'a>( &self, transaction: &mut Transaction<'a>, node_attributes: Option<&MutableNodeAttributes>, change_time: Option<Timestamp>, ) -> Result<(), Error>
Sourcepub async fn zero(
&self,
transaction: &mut Transaction<'_>,
attribute_id: u64,
range: Range<u64>,
) -> Result<(), Error>
pub async fn zero( &self, transaction: &mut Transaction<'_>, attribute_id: u64, range: Range<u64>, ) -> Result<(), Error>
Zeroes the given range. The range must be aligned. Returns the amount of data deallocated.
pub async fn align_buffer( &self, attribute_id: u64, offset: u64, buf: BufferRef<'_>, ) -> Result<(Range<u64>, Buffer<'_>), Error>
Sourcepub async fn shrink(
&self,
transaction: &mut Transaction<'_>,
attribute_id: u64,
size: u64,
) -> Result<NeedsTrim, Error>
pub async fn shrink( &self, transaction: &mut Transaction<'_>, attribute_id: u64, size: u64, ) -> Result<NeedsTrim, Error>
Trim an attribute’s extents, potentially adding a graveyard trim entry if more trimming is needed, so the transaction can be committed without worrying about leaking data.
This doesn’t update the size stored in the attribute value - the caller is responsible for doing that to keep the size up to date.
pub async fn read_and_decrypt( &self, device_offset: u64, file_offset: u64, buffer: MutableBufferRef<'_>, key_id: u64, block_bitmap: Option<BitVec>, ) -> Result<(), Error>
Sourcepub async fn get_key(&self, key_id: Option<u64>) -> Result<Option<Key>, Error>
pub async fn get_key(&self, key_id: Option<u64>) -> Result<Option<Key>, Error>
Returns the specified key. If key_id
is None, it will try and return the fscrypt key if
it is present, or the volume key if it isn’t. If the fscrypt key is present, but the key
cannot be unwrapped, then this will return FxfsError::NoKey
. If the volume is not
encrypted, this returns None.
pub async fn read( &self, attribute_id: u64, offset: u64, buf: MutableBufferRef<'_>, ) -> Result<usize, Error>
Sourcepub async fn read_attr(
&self,
attribute_id: u64,
) -> Result<Option<Box<[u8]>>, Error>
pub async fn read_attr( &self, attribute_id: u64, ) -> Result<Option<Box<[u8]>>, Error>
Reads an entire attribute.
Sourcepub async fn write_at(
&self,
attribute_id: u64,
offset: u64,
buf: MutableBufferRef<'_>,
key_id: Option<u64>,
device_offset: u64,
) -> Result<MaybeChecksums, Error>
pub async fn write_at( &self, attribute_id: u64, offset: u64, buf: MutableBufferRef<'_>, key_id: Option<u64>, device_offset: u64, ) -> Result<MaybeChecksums, Error>
Writes potentially unaligned data at device_offset
and returns checksums if requested.
The data will be encrypted if necessary. buf
is mutable as an optimization, since the
write may require encryption, we can encrypt the buffer in-place rather than copying to
another buffer if the write is already aligned.
NOTE: This will not create keys if they are missing (it will fail with an error if that happens to be the case).
Sourcepub async fn multi_write(
&self,
transaction: &mut Transaction<'_>,
attribute_id: u64,
key_id: Option<u64>,
ranges: &[Range<u64>],
buf: MutableBufferRef<'_>,
) -> Result<(), Error>
pub async fn multi_write( &self, transaction: &mut Transaction<'_>, attribute_id: u64, key_id: Option<u64>, ranges: &[Range<u64>], buf: MutableBufferRef<'_>, ) -> Result<(), Error>
Writes to multiple ranges with data provided in buf
. The buffer can be modified in place
if encryption takes place. The ranges must all be aligned and no change to content size is
applied; the caller is responsible for updating size if required. If key_id
is None, it
means pick the default key for the object which is the fscrypt key if present, or the volume
data key, or no key if it’s an unencrypted file.
Sourcepub async fn multi_overwrite<'a>(
&'a self,
transaction: &mut Transaction<'a>,
attr_id: u64,
ranges: &[Range<u64>],
buf: MutableBufferRef<'_>,
) -> Result<(), Error>
pub async fn multi_overwrite<'a>( &'a self, transaction: &mut Transaction<'a>, attr_id: u64, ranges: &[Range<u64>], buf: MutableBufferRef<'_>, ) -> Result<(), Error>
Write data to overwrite extents with the provided set of ranges. This makes a strong assumption that the ranges are actually going to be already allocated overwrite extents and will error out or do something wrong if they aren’t. It also assumes the ranges passed to it are sorted.
Sourcepub async fn write_new_attr_in_batches<'a>(
&'a self,
transaction: &mut Transaction<'a>,
attribute_id: u64,
data: &[u8],
batch_size: usize,
) -> Result<(), Error>
pub async fn write_new_attr_in_batches<'a>( &'a self, transaction: &mut Transaction<'a>, attribute_id: u64, data: &[u8], batch_size: usize, ) -> Result<(), Error>
Writes an attribute that should not already exist and therefore does not require trimming.
Breaks up the write into multiple transactions if data.len()
is larger than batch_size
.
If writing the attribute requires multiple transactions, adds the attribute to the
graveyard. The caller is responsible for removing the attribute from the graveyard when it
commits the last transaction. This always writes using a key wrapped with the volume data
key.
Sourcepub async fn write_attr(
&self,
transaction: &mut Transaction<'_>,
attribute_id: u64,
data: &[u8],
) -> Result<NeedsTrim, Error>
pub async fn write_attr( &self, transaction: &mut Transaction<'_>, attribute_id: u64, data: &[u8], ) -> Result<NeedsTrim, Error>
Writes an entire attribute. Returns whether or not the attribute needs to continue being trimmed - if the new data is shorter than the old data, this will trim any extents beyond the end of the new size, but if there were too many for a single transaction, a commit needs to be made before trimming again, so the responsibility is left to the caller so as to not accidentally split the transaction when it’s not in a consistent state. This will write using the volume data key; the fscrypt key is not supported.
pub async fn list_extended_attributes(&self) -> Result<Vec<Vec<u8>>, Error>
Sourcepub async fn get_inline_selinux_context(
&self,
) -> Result<Option<SelinuxContext>, Error>
pub async fn get_inline_selinux_context( &self, ) -> Result<Option<SelinuxContext>, Error>
Looks up the values for the extended attribute fio::SELINUX_CONTEXT_NAME
, returning it
if it is found inline. If it is not inline, it will request use of the
get_extended_attributes
method. If the entry doesn’t exist at all, returns None.
pub async fn get_extended_attribute( &self, name: Vec<u8>, ) -> Result<Vec<u8>, Error>
pub async fn set_extended_attribute( &self, name: Vec<u8>, value: Vec<u8>, mode: SetExtendedAttributeMode, ) -> Result<(), Error>
pub async fn remove_extended_attribute( &self, name: Vec<u8>, ) -> Result<(), Error>
Sourcepub fn pre_fetch_keys(&self) -> Option<impl Future<Output = ()>>
pub fn pre_fetch_keys(&self) -> Option<impl Future<Output = ()>>
Returns a future that will pre-fetches the keys so as to avoid paying the performance penalty later. Must ensure that the object is not removed before the future completes.
Trait Implementations§
Source§impl<S: HandleOwner> AssociatedObject for DataObjectHandle<S>
impl<S: HandleOwner> AssociatedObject for DataObjectHandle<S>
fn will_apply_mutation( &self, mutation: &Mutation, _object_id: u64, _manager: &ObjectManager, )
Source§impl<S: HandleOwner> Deref for DataObjectHandle<S>
impl<S: HandleOwner> Deref for DataObjectHandle<S>
Source§impl<S: HandleOwner> JournalHandle for DataObjectHandle<S>
impl<S: HandleOwner> JournalHandle for DataObjectHandle<S>
Source§fn end_offset(&self) -> Option<u64>
fn end_offset(&self) -> Option<u64>
Source§fn push_extent(&mut self, _added_offset: u64, _device_range: Range<u64>)
fn push_extent(&mut self, _added_offset: u64, _device_range: Range<u64>)
added_offset
is the offset into the journal of the transaction which added this extent,
used for discard_extents.Source§fn discard_extents(&mut self, _discard_offset: u64)
fn discard_extents(&mut self, _discard_offset: u64)
Source§impl<S: HandleOwner> ObjectHandle for DataObjectHandle<S>
impl<S: HandleOwner> ObjectHandle for DataObjectHandle<S>
Source§fn object_id(&self) -> u64
fn object_id(&self) -> u64
Source§fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>
fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>
Source§fn block_size(&self) -> u64
fn block_size(&self) -> u64
Source§impl<S: HandleOwner> ReadObjectHandle for DataObjectHandle<S>
impl<S: HandleOwner> ReadObjectHandle for DataObjectHandle<S>
Source§fn read<'life0, 'life1, 'async_trait>(
&'life0 self,
offset: u64,
buf: MutableBufferRef<'life1>,
) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn read<'life0, 'life1, 'async_trait>(
&'life0 self,
offset: u64,
buf: MutableBufferRef<'life1>,
) -> Pin<Box<dyn Future<Output = Result<usize, Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§impl<S: HandleOwner> WriteObjectHandle for DataObjectHandle<S>
impl<S: HandleOwner> WriteObjectHandle for DataObjectHandle<S>
Source§async fn write_or_append(
&self,
offset: Option<u64>,
buf: BufferRef<'_>,
) -> Result<u64, Error>
async fn write_or_append( &self, offset: Option<u64>, buf: BufferRef<'_>, ) -> Result<u64, Error>
Auto Trait Implementations§
impl<S> !Freeze for DataObjectHandle<S>
impl<S> !RefUnwindSafe for DataObjectHandle<S>
impl<S> Send for DataObjectHandle<S>
impl<S> Sync for DataObjectHandle<S>
impl<S> Unpin for DataObjectHandle<S>
impl<S> UnwindSafe for DataObjectHandle<S>where
S: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T, D> Encode<Ambiguous1, D> for Twhere
D: ResourceDialect,
impl<T, D> Encode<Ambiguous1, D> for Twhere
D: ResourceDialect,
Source§impl<T, D> Encode<Ambiguous2, D> for Twhere
D: ResourceDialect,
impl<T, D> Encode<Ambiguous2, D> for Twhere
D: ResourceDialect,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more