mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 07:48:11 +00:00
Kernel: Fix storage device read/write for request length < block size
The current implementation of read/write will fail in StorageDevice when the request length is less than the block size of the underlying device. Fix it by calculating the offset within a block for such cases and using it for copying data from the bounce buffer.
This commit is contained in:
parent
34db0dab41
commit
36363b1a37
1 changed files with 10 additions and 2 deletions
|
@ -30,6 +30,7 @@ StringView StorageDevice::class_name() const
|
|||
ErrorOr<size_t> StorageDevice::read(OpenFileDescription&, u64 offset, UserOrKernelBuffer& outbuf, size_t len)
|
||||
{
|
||||
u64 index = offset >> block_size_log();
|
||||
off_t offset_within_block = 0;
|
||||
size_t whole_blocks = len >> block_size_log();
|
||||
size_t remaining = len - (whole_blocks << block_size_log());
|
||||
|
||||
|
@ -40,6 +41,9 @@ ErrorOr<size_t> StorageDevice::read(OpenFileDescription&, u64 offset, UserOrKern
|
|||
remaining = 0;
|
||||
}
|
||||
|
||||
if (len < block_size())
|
||||
offset_within_block = offset - (index << block_size_log());
|
||||
|
||||
dbgln_if(STORAGE_DEVICE_DEBUG, "StorageDevice::read() index={}, whole_blocks={}, remaining={}", index, whole_blocks, remaining);
|
||||
|
||||
if (whole_blocks > 0) {
|
||||
|
@ -78,7 +82,7 @@ ErrorOr<size_t> StorageDevice::read(OpenFileDescription&, u64 offset, UserOrKern
|
|||
default:
|
||||
break;
|
||||
}
|
||||
TRY(outbuf.write(data.data(), pos, remaining));
|
||||
TRY(outbuf.write(data.offset_pointer(offset_within_block), pos, remaining));
|
||||
}
|
||||
|
||||
return pos + remaining;
|
||||
|
@ -92,6 +96,7 @@ bool StorageDevice::can_read(const OpenFileDescription&, u64 offset) const
|
|||
ErrorOr<size_t> StorageDevice::write(OpenFileDescription&, u64 offset, const UserOrKernelBuffer& inbuf, size_t len)
|
||||
{
|
||||
u64 index = offset >> block_size_log();
|
||||
off_t offset_within_block = 0;
|
||||
size_t whole_blocks = len >> block_size_log();
|
||||
size_t remaining = len - (whole_blocks << block_size_log());
|
||||
|
||||
|
@ -102,6 +107,9 @@ ErrorOr<size_t> StorageDevice::write(OpenFileDescription&, u64 offset, const Use
|
|||
remaining = 0;
|
||||
}
|
||||
|
||||
if (len < block_size())
|
||||
offset_within_block = offset - (index << block_size_log());
|
||||
|
||||
// We try to allocate the temporary block buffer for partial writes *before* we start any full block writes,
|
||||
// to try and prevent partial writes
|
||||
Optional<ByteBuffer> partial_write_block;
|
||||
|
@ -151,7 +159,7 @@ ErrorOr<size_t> StorageDevice::write(OpenFileDescription&, u64 offset, const Use
|
|||
}
|
||||
}
|
||||
|
||||
TRY(inbuf.read(partial_write_block->data(), pos, remaining));
|
||||
TRY(inbuf.read(partial_write_block->offset_pointer(offset_within_block), pos, remaining));
|
||||
|
||||
{
|
||||
auto write_request = TRY(try_make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Write, index + whole_blocks, 1, data_buffer, block_size()));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue