nvme_disk: Add more error checks in read().
This commit is contained in:
@@ -182,7 +182,7 @@ nvme_disk_init_device(void* _info, void** _cookie)
|
|||||||
int err = nvme_ctrlr_stat(info->ctrlr, &cstat);
|
int err = nvme_ctrlr_stat(info->ctrlr, &cstat);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
TRACE_ERROR("failed to get controller information!\n");
|
TRACE_ERROR("failed to get controller information!\n");
|
||||||
return -err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: export more than just the first namespace!
|
// TODO: export more than just the first namespace!
|
||||||
@@ -196,7 +196,7 @@ nvme_disk_init_device(void* _info, void** _cookie)
|
|||||||
err = nvme_ns_stat(info->ns, &nsstat);
|
err = nvme_ns_stat(info->ns, &nsstat);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
TRACE_ERROR("failed to get namespace information!\n");
|
TRACE_ERROR("failed to get namespace information!\n");
|
||||||
return -err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// store capacity information
|
// store capacity information
|
||||||
@@ -268,9 +268,9 @@ nvme_disk_free(void* cookie)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
disk_read_callback(bool* done, const struct nvme_cpl*)
|
disk_read_callback(status_t* status, const struct nvme_cpl* cpl)
|
||||||
{
|
{
|
||||||
*done = true;
|
*status = nvme_cpl_is_error(cpl) ? B_IO_ERROR : B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -280,28 +280,39 @@ nvme_disk_read(void* cookie, off_t pos, void* buffer, size_t* _length)
|
|||||||
CALLED();
|
CALLED();
|
||||||
nvme_disk_handle* handle = (nvme_disk_handle*)cookie;
|
nvme_disk_handle* handle = (nvme_disk_handle*)cookie;
|
||||||
|
|
||||||
bool done = false;
|
status_t status = EINPROGRESS;
|
||||||
size_t rounded_len = ROUNDUP(*_length, handle->info->block_size);
|
|
||||||
|
|
||||||
|
// libnvme does transfers in units of device sectors, so we must
|
||||||
|
// round up the length to the sector size, and then allocate a
|
||||||
|
// bounce buffer.
|
||||||
|
const size_t block_size = handle->info->block_size;
|
||||||
|
size_t rounded_len = ROUNDUP(*_length, block_size);
|
||||||
void* real_buffer;
|
void* real_buffer;
|
||||||
if (rounded_len == *_length && !IS_USER_ADDRESS(buffer))
|
if (rounded_len == *_length && !IS_USER_ADDRESS(buffer))
|
||||||
real_buffer = buffer;
|
real_buffer = buffer;
|
||||||
else
|
else
|
||||||
real_buffer = malloc(rounded_len);
|
real_buffer = malloc(rounded_len);
|
||||||
|
|
||||||
|
if (real_buffer == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
MutexLocker _(handle->info->qpair_mtx);
|
MutexLocker _(handle->info->qpair_mtx);
|
||||||
int ret = nvme_ns_read(handle->info->ns, handle->info->qpair,
|
int ret = nvme_ns_read(handle->info->ns, handle->info->qpair,
|
||||||
real_buffer, pos / handle->info->block_size, rounded_len / handle->info->block_size,
|
real_buffer, pos / block_size, rounded_len / block_size,
|
||||||
(nvme_cmd_cb)disk_read_callback, &done, 0);
|
(nvme_cmd_cb)disk_read_callback, &status, 0);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
while (!done) {
|
while (status == EINPROGRESS) {
|
||||||
nvme_ioqp_poll(handle->info->qpair, 1);
|
nvme_ioqp_poll(handle->info->qpair, 1);
|
||||||
snooze(1);
|
snooze(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != B_OK) {
|
||||||
|
*_length = 0;
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t status = B_OK;
|
|
||||||
if (real_buffer != buffer) {
|
if (real_buffer != buffer) {
|
||||||
if (IS_USER_ADDRESS(buffer))
|
if (IS_USER_ADDRESS(buffer))
|
||||||
status = user_memcpy(buffer, real_buffer, *_length);
|
status = user_memcpy(buffer, real_buffer, *_length);
|
||||||
|
|||||||
Reference in New Issue
Block a user