Struct DataObjectHandle

Source
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>

Source

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

Source

pub fn attribute_id(&self) -> u64

Source

pub fn overwrite_ranges(&self) -> &AllocatedRanges

Source

pub fn is_verified_file(&self) -> bool

Source

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.

Source

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.

Source

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(_).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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

Source

pub async fn txn_write<'a>( &'a self, transaction: &mut Transaction<'a>, offset: u64, buf: BufferRef<'_>, ) -> Result<(), Error>

Source

pub async fn multi_write<'a>( &'a self, transaction: &mut Transaction<'a>, attribute_id: u64, ranges: &[Range<u64>], buf: MutableBufferRef<'_>, ) -> Result<(), Error>

Source

pub async fn overwrite( &self, offset: u64, buf: MutableBufferRef<'_>, allow_allocations: bool, ) -> Result<(), Error>

Source

pub async fn txn_update_size<'a>( &'a self, transaction: &mut Transaction<'a>, new_size: u64, update_has_overwrite_extents: Option<bool>, ) -> Result<(), Error>

Source

pub fn truncate_overwrite_ranges( &self, size: u64, ) -> Result<Option<bool>, Error>

Source

pub async fn shrink<'a>( &'a self, transaction: &mut Transaction<'a>, size: u64, update_has_overwrite_extents: Option<bool>, ) -> Result<NeedsTrim, Error>

Source

pub async fn grow<'a>( &'a self, transaction: &mut Transaction<'a>, old_size: u64, size: u64, ) -> Result<(), Error>

Source

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.

Source

pub async fn update_attributes<'a>( &self, transaction: &mut Transaction<'a>, node_attributes: Option<&MutableNodeAttributes>, change_time: Option<Timestamp>, ) -> Result<(), Error>

Source

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.

Source

pub async fn new_transaction<'b>(&self) -> Result<Transaction<'b>, Error>

Source

pub async fn new_transaction_with_options<'b>( &self, options: Options<'b>, ) -> Result<Transaction<'b>, Error>

Source

pub async fn flush_device(&self) -> Result<(), Error>

Flushes the underlying device. This is expensive and should be used sparingly.

Source

pub async fn read_attr( &self, attribute_id: u64, ) -> Result<Option<Box<[u8]>>, Error>

Reads an entire attribute.

Source

pub async fn write_attr( &self, attribute_id: u64, data: &[u8], ) -> Result<(), Error>

Writes an entire attribute. This always uses the volume data key.

Source

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.

Source

pub async fn get_properties(&self) -> Result<ObjectProperties, Error>

Source

pub async fn contents(&self, limit: usize) -> Result<Box<[u8]>, Error>

Source

pub async fn device_extents(&self) -> Result<Vec<(u64, Range<u64>)>, Error>

Returns the set of file_offset->extent mappings for this file. This operation is potentially expensive and should generally be avoided.

Methods from Deref<Target = StoreObjectHandle<S>>§

Source

pub fn owner(&self) -> &Arc<S>

Source

pub fn store(&self) -> &ObjectStore

Source

pub fn trace(&self) -> bool

Source

pub fn is_encrypted(&self) -> bool

Source

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.

Source

pub async fn new_transaction_with_options<'b>( &self, attribute_id: u64, options: Options<'b>, ) -> Result<Transaction<'b>, Error>

Source

pub async fn new_transaction<'b>( &self, attribute_id: u64, ) -> Result<Transaction<'b>, Error>

Source

pub async fn flush_device(&self) -> Result<(), Error>

Flushes the underlying device. This is expensive and should be used sparingly.

Source

pub async fn update_allocated_size( &self, transaction: &mut Transaction<'_>, allocated: u64, deallocated: u64, ) -> Result<(), Error>

Source

pub async fn update_attributes<'a>( &self, transaction: &mut Transaction<'a>, node_attributes: Option<&MutableNodeAttributes>, change_time: Option<Timestamp>, ) -> Result<(), Error>

Source

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.

Source

pub async fn align_buffer( &self, attribute_id: u64, offset: u64, buf: BufferRef<'_>, ) -> Result<(Range<u64>, Buffer<'_>), Error>

Source

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.

Source

pub async fn read_and_decrypt( &self, device_offset: u64, file_offset: u64, buffer: MutableBufferRef<'_>, key_id: u64, block_bitmap: Option<BitVec>, ) -> Result<(), Error>

Source

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.

Source

pub async fn read( &self, attribute_id: u64, offset: u64, buf: MutableBufferRef<'_>, ) -> Result<usize, Error>

Source

pub async fn read_attr( &self, attribute_id: u64, ) -> Result<Option<Box<[u8]>>, Error>

Reads an entire attribute.

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub async fn list_extended_attributes(&self) -> Result<Vec<Vec<u8>>, Error>

Source

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.

Source

pub async fn get_extended_attribute( &self, name: Vec<u8>, ) -> Result<Vec<u8>, Error>

Source

pub async fn set_extended_attribute( &self, name: Vec<u8>, value: Vec<u8>, mode: SetExtendedAttributeMode, ) -> Result<(), Error>

Source

pub async fn remove_extended_attribute( &self, name: Vec<u8>, ) -> Result<(), Error>

Source

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>

Source§

fn will_apply_mutation( &self, mutation: &Mutation, _object_id: u64, _manager: &ObjectManager, )

Source§

impl<S: HandleOwner> Deref for DataObjectHandle<S>

Source§

type Target = StoreObjectHandle<S>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<S: HandleOwner> JournalHandle for DataObjectHandle<S>

Source§

fn end_offset(&self) -> Option<u64>

The end offset of the last extent in the JournalHandle. Used only for validating extents (which will be skipped if None is returned). Note this is equivalent in value to ReadObjectHandle::get_size, when present.
Source§

fn push_extent(&mut self, _added_offset: u64, _device_range: Range<u64>)

Adds an extent to the current end of the journal stream. 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)

Discards all extents which were added in a transaction at offset >= |discard_offset|.
Source§

impl<S: HandleOwner> ObjectHandle for DataObjectHandle<S>

Source§

fn set_trace(&self, v: bool)

Sets tracing for this object.
Source§

fn object_id(&self) -> u64

Returns the object identifier for this object which will be unique for the store that the object is contained in, but not necessarily unique within the entire system.
Source§

fn allocate_buffer(&self, size: usize) -> BufferFuture<'_>

Allocates a buffer for doing I/O (read and write) for the object.
Source§

fn block_size(&self) -> u64

Returns the filesystem block size, which should be at least as big as the device block size, but not necessarily the same.
Source§

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,

Fills |buf| with up to |buf.len()| bytes read from |offset| on the underlying device. |offset| and |buf| must both be block-aligned.
Source§

fn get_size(&self) -> u64

Returns the size of the object.
Source§

impl<S: HandleOwner> WriteObjectHandle for DataObjectHandle<S>

Source§

async fn write_or_append( &self, offset: Option<u64>, buf: BufferRef<'_>, ) -> Result<u64, Error>

Writes |buf.len())| bytes at |offset| (or the end of the file), returning the object size after writing. The writes may be cached, in which case a later call to |flush| is necessary to persist the writes.
Source§

async fn truncate(&self, size: u64) -> Result<(), Error>

Truncates the object to |size| bytes. The truncate may be cached, in which case a later call to |flush| is necessary to persist the truncate.
Source§

async fn flush(&self) -> Result<(), Error>

Flushes all pending data and metadata updates for the object.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T, D> Encode<Ambiguous1, D> for T
where D: ResourceDialect,

Source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
Source§

impl<T, D> Encode<Ambiguous2, D> for T
where D: ResourceDialect,

Source§

unsafe fn encode( self, _encoder: &mut Encoder<'_, D>, _offset: usize, _depth: Depth, ) -> Result<(), Error>

Encodes the object into the encoder’s buffers. Any handles stored in the object are swapped for Handle::INVALID. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V