mmc_disk: Refactor read/write/io hooks.

* Move geometry fetching to open(); it was not done
   in io() and was duplicated in multiple places.

 * Clean up clamping and bounds checking.

 * Use IORequest::TransferredBytes().

 Change-Id: I4157e516098dc0362c1478abd21a545c1f235cd7
This commit is contained in:
Augustin Cavalier
2023-04-27 16:24:02 -04:00
parent e0f07d3ce0
commit be67f14dcb
@@ -360,11 +360,22 @@ mmc_block_open(void* _info, const char* path, int openMode, void** _cookie)
// allocate cookie // allocate cookie
mmc_disk_handle* handle = new(std::nothrow) mmc_disk_handle; mmc_disk_handle* handle = new(std::nothrow) mmc_disk_handle;
*_cookie = handle; *_cookie = handle;
if (handle == NULL) { if (handle == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
}
handle->info = info; handle->info = info;
if (handle->info->geometry.bytes_per_sector == 0) {
status_t error = mmc_block_get_geometry(handle->info,
&handle->info->geometry);
if (error != B_OK) {
TRACE("Failed to get disk capacity");
delete handle;
*_cookie = NULL;
return error;
}
}
return B_OK; return B_OK;
} }
@@ -391,30 +402,19 @@ mmc_block_free(void* cookie)
static status_t static status_t
mmc_block_read(void* cookie, off_t pos, void* buffer, size_t* _length) mmc_block_read(void* cookie, off_t position, void* buffer, size_t* _length)
{ {
CALLED(); CALLED();
mmc_disk_handle* handle = (mmc_disk_handle*)cookie; mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
size_t length = *_length; size_t length = *_length;
if (position >= handle->info->DeviceSize())
if (handle->info->geometry.bytes_per_sector == 0) { return ERANGE;
status_t error = mmc_block_get_geometry(handle->info, if ((position + (off_t)length) > handle->info->DeviceSize())
&handle->info->geometry); length = (handle->info->DeviceSize() - position);
if (error != B_OK) {
TRACE("Failed to get disk capacity");
return error;
}
}
// Do not allow reading past device end
if (pos >= handle->info->DeviceSize())
return B_BAD_VALUE;
if (pos + (off_t)length > handle->info->DeviceSize())
length = handle->info->DeviceSize() - pos;
IORequest request; IORequest request;
status_t status = request.Init(pos, (addr_t)buffer, length, false, 0); status_t status = request.Init(position, (addr_t)buffer, length, false, 0);
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -423,8 +423,7 @@ mmc_block_read(void* cookie, off_t pos, void* buffer, size_t* _length)
return status; return status;
status = request.Wait(0, 0); status = request.Wait(0, 0);
if (status == B_OK) *_length = request.TransferredBytes();
*_length = length;
return status; return status;
} }
@@ -437,20 +436,10 @@ mmc_block_write(void* cookie, off_t position, const void* buffer,
mmc_disk_handle* handle = (mmc_disk_handle*)cookie; mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
size_t length = *_length; size_t length = *_length;
if (handle->info->geometry.bytes_per_sector == 0) {
status_t error = mmc_block_get_geometry(handle->info,
&handle->info->geometry);
if (error != B_OK) {
TRACE("Failed to get disk capacity");
return error;
}
}
if (position >= handle->info->DeviceSize()) if (position >= handle->info->DeviceSize())
return B_BAD_VALUE; return ERANGE;
if (position + (off_t)length > handle->info->DeviceSize()) if ((position + (off_t)length) > handle->info->DeviceSize())
length = handle->info->DeviceSize() - position; length = (handle->info->DeviceSize() - position);
IORequest request; IORequest request;
status_t status = request.Init(position, (addr_t)buffer, length, true, 0); status_t status = request.Init(position, (addr_t)buffer, length, true, 0);
@@ -462,9 +451,7 @@ mmc_block_write(void* cookie, off_t position, const void* buffer,
return status; return status;
status = request.Wait(0, 0); status = request.Wait(0, 0);
if (status == B_OK) *_length = request.TransferredBytes();
*_length = length;
return status; return status;
} }
@@ -475,6 +462,9 @@ mmc_block_io(void* cookie, io_request* request)
CALLED(); CALLED();
mmc_disk_handle* handle = (mmc_disk_handle*)cookie; mmc_disk_handle* handle = (mmc_disk_handle*)cookie;
if ((request->Offset() + (off_t)request->Length()) > handle->info->DeviceSize())
return ERANGE;
return handle->info->scheduler->ScheduleRequest(request); return handle->info->scheduler->ScheduleRequest(request);
} }
@@ -591,13 +581,6 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
case B_GET_DEVICE_SIZE: case B_GET_DEVICE_SIZE:
{ {
// Legacy ioctl, use B_GET_GEOMETRY // Legacy ioctl, use B_GET_GEOMETRY
if (info->geometry.bytes_per_sector == 0) {
status_t error = mmc_block_get_geometry(info, &info->geometry);
if (error != B_OK) {
TRACE("Failed to get disk capacity");
return error;
}
}
uint64_t size = info->DeviceSize(); uint64_t size = info->DeviceSize();
if (size > SIZE_MAX) if (size > SIZE_MAX)
@@ -611,14 +594,6 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
if (buffer == NULL || length > sizeof(device_geometry)) if (buffer == NULL || length > sizeof(device_geometry))
return B_BAD_VALUE; return B_BAD_VALUE;
if (info->geometry.bytes_per_sector == 0) {
status_t error = mmc_block_get_geometry(info, &info->geometry);
if (error != B_OK) {
TRACE("Failed to get disk capacity");
return error;
}
}
return user_memcpy(buffer, &info->geometry, length); return user_memcpy(buffer, &info->geometry, length);
} }