/* * The I/O factory object manages access to index storage, which is a contiguous range of blocks on * a block device. * * The factory holds the open device and is responsible for closing it. The factory has methods to * make helper structures that can be used to access sections of the index.
*/ struct io_factory { struct block_device *bdev;
atomic_t ref_count;
};
/* The buffered reader allows efficient I/O by reading page-sized segments into a buffer. */ struct buffered_reader { struct io_factory *factory; struct dm_bufio_client *client; struct dm_buffer *buffer;
sector_t limit;
sector_t block_number;
u8 *start;
u8 *end;
};
#define MAX_READ_AHEAD_BLOCKS 4
/* * The buffered writer allows efficient I/O by buffering writes and committing page-sized segments * to storage.
*/ struct buffered_writer { struct io_factory *factory; struct dm_bufio_client *client; struct dm_buffer *buffer;
sector_t limit;
sector_t block_number;
u8 *start;
u8 *end; int error;
};
/* Free an I/O factory once all references have been released. */ void uds_put_io_factory(struct io_factory *factory)
{ if (atomic_add_return(-1, &factory->ref_count) <= 0)
vdo_free(factory);
}
/* Create a struct dm_bufio_client for an index region starting at offset. */ int uds_make_bufio(struct io_factory *factory, off_t block_offset, size_t block_size, unsignedint reserved_buffers, struct dm_bufio_client **client_ptr)
{ struct dm_bufio_client *client;
/* Create a buffered reader for an index region starting at offset. */ int uds_make_buffered_reader(struct io_factory *factory, off_t offset, u64 block_count, struct buffered_reader **reader_ptr)
{ int result; struct dm_bufio_client *client = NULL; struct buffered_reader *reader = NULL;
result = uds_make_bufio(factory, offset, UDS_BLOCK_SIZE, 1, &client); if (result != UDS_SUCCESS) return result;
result = vdo_allocate(1, struct buffered_reader, "buffered reader", &reader); if (result != VDO_SUCCESS) {
dm_bufio_client_destroy(client); return result;
}
/* * Verify that the next data on the reader matches the required value. If the value matches, the * matching contents are consumed. If the value does not match, the reader state is unchanged.
*/ int uds_verify_buffered_data(struct buffered_reader *reader, const u8 *value,
size_t length)
{ int result = UDS_SUCCESS;
size_t chunk_size;
sector_t start_block_number = reader->block_number; int start_offset = reader->end - reader->start;
while (length > 0) {
result = reset_reader(reader); if (result != UDS_SUCCESS) {
result = UDS_CORRUPT_DATA; break;
}
chunk_size = min(length, bytes_remaining_in_read_buffer(reader)); if (memcmp(value, reader->end, chunk_size) != 0) {
result = UDS_CORRUPT_DATA; break;
}
length -= chunk_size;
value += chunk_size;
reader->end += chunk_size;
}
if (result != UDS_SUCCESS)
position_reader(reader, start_block_number, start_offset);
return result;
}
/* Create a buffered writer for an index region starting at offset. */ int uds_make_buffered_writer(struct io_factory *factory, off_t offset, u64 block_count, struct buffered_writer **writer_ptr)
{ int result; struct dm_bufio_client *client = NULL; struct buffered_writer *writer;
result = uds_make_bufio(factory, offset, UDS_BLOCK_SIZE, 1, &client); if (result != UDS_SUCCESS) return result;
result = vdo_allocate(1, struct buffered_writer, "buffered writer", &writer); if (result != VDO_SUCCESS) {
dm_bufio_client_destroy(client); return result;
}
void uds_free_buffered_writer(struct buffered_writer *writer)
{ int result;
if (writer == NULL) return;
flush_previous_buffer(writer);
result = -dm_bufio_write_dirty_buffers(writer->client); if (result != UDS_SUCCESS)
vdo_log_warning_strerror(result, "%s: failed to sync storage", __func__);
/* * Append data to the buffer, writing as needed. If no data is provided, zeros are written instead. * If a write error occurs, it is recorded and returned on every subsequent write attempt.
*/ int uds_write_to_buffered_writer(struct buffered_writer *writer, const u8 *data,
size_t length)
{ int result = writer->error;
size_t chunk_size;
while ((length > 0) && (result == UDS_SUCCESS)) { if (writer->buffer == NULL) {
result = prepare_next_buffer(writer); continue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.