mirror of
https://github.com/RGBCube/serenity
synced 2025-07-19 18:57:40 +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)
|
ErrorOr<size_t> StorageDevice::read(OpenFileDescription&, u64 offset, UserOrKernelBuffer& outbuf, size_t len)
|
||||||
{
|
{
|
||||||
u64 index = offset >> block_size_log();
|
u64 index = offset >> block_size_log();
|
||||||
|
off_t offset_within_block = 0;
|
||||||
size_t whole_blocks = len >> block_size_log();
|
size_t whole_blocks = len >> block_size_log();
|
||||||
size_t remaining = len - (whole_blocks << 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;
|
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);
|
dbgln_if(STORAGE_DEVICE_DEBUG, "StorageDevice::read() index={}, whole_blocks={}, remaining={}", index, whole_blocks, remaining);
|
||||||
|
|
||||||
if (whole_blocks > 0) {
|
if (whole_blocks > 0) {
|
||||||
|
@ -78,7 +82,7 @@ ErrorOr<size_t> StorageDevice::read(OpenFileDescription&, u64 offset, UserOrKern
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TRY(outbuf.write(data.data(), pos, remaining));
|
TRY(outbuf.write(data.offset_pointer(offset_within_block), pos, remaining));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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)
|
ErrorOr<size_t> StorageDevice::write(OpenFileDescription&, u64 offset, const UserOrKernelBuffer& inbuf, size_t len)
|
||||||
{
|
{
|
||||||
u64 index = offset >> block_size_log();
|
u64 index = offset >> block_size_log();
|
||||||
|
off_t offset_within_block = 0;
|
||||||
size_t whole_blocks = len >> block_size_log();
|
size_t whole_blocks = len >> block_size_log();
|
||||||
size_t remaining = len - (whole_blocks << 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;
|
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,
|
// We try to allocate the temporary block buffer for partial writes *before* we start any full block writes,
|
||||||
// to try and prevent partial writes
|
// to try and prevent partial writes
|
||||||
Optional<ByteBuffer> partial_write_block;
|
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()));
|
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