* It is now supported that I/O operations and requests are only handled
partially (e.g. due to hitting the end of file). The respective
classes have grown new methods and attributes to deal with that. The
"finished" callbacks have got additional parameters to indicate
whether the transfer was only partial and how much has been
transferred. Other callbacks and functions have a size_t* in/out
parameter instead of a simple size_t, now.
* vfs_{read,write}_pages() do now use the I/O request framework instead
of the underlying FS's {read,write}_pages() hooks (those should be
unused now). Furthermore they've got an additional "flags" parameter,
which is passed to IORequest::Init(), i.e. it allows to specify that
the given vecs refer to physical addresses.
* The file cache's read_into_cache() reads directly into physical
pages, now.
* Fixed bug in DoIO::IO(): The offset was not adjusted, so that all
pages were incorrectly transferred from/to the same location.
* Fixed broken subrequest scheduling loop head in
do_iterative_fd_io_iterate().
* Adjusted the test driver and implemented its io() hook. Using this
driver I/O requests are passed all the way from the VFS/VM to the
driver and through the I/O scheduler. It even seems to work. :-)
* Added missing const to the iovec* parameter of the IORequest::Init()
methods.
* Disabled some debug output by default. Added new optional debug
output.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26692 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -299,7 +299,7 @@ typedef status_t (*iterative_io_get_vecs)(void *cookie, io_request* request,
|
|||||||
off_t offset, size_t size, struct file_io_vec *vecs,
|
off_t offset, size_t size, struct file_io_vec *vecs,
|
||||||
size_t *_count);
|
size_t *_count);
|
||||||
typedef status_t (*iterative_io_finished)(void* cookie, io_request* request,
|
typedef status_t (*iterative_io_finished)(void* cookie, io_request* request,
|
||||||
status_t status);
|
status_t status, bool partialTransfer, size_t bytesTransferred);
|
||||||
|
|
||||||
extern status_t new_vnode(fs_volume *volume, ino_t vnodeID, void *privateNode,
|
extern status_t new_vnode(fs_volume *volume, ino_t vnodeID, void *privateNode,
|
||||||
fs_vnode_ops *ops);
|
fs_vnode_ops *ops);
|
||||||
|
|||||||
@@ -334,7 +334,8 @@ typedef fssh_status_t (*fssh_iterative_io_get_vecs)(void *cookie,
|
|||||||
fssh_io_request* request, fssh_off_t offset, fssh_size_t size,
|
fssh_io_request* request, fssh_off_t offset, fssh_size_t size,
|
||||||
struct fssh_file_io_vec *vecs, fssh_size_t *_count);
|
struct fssh_file_io_vec *vecs, fssh_size_t *_count);
|
||||||
typedef fssh_status_t (*fssh_iterative_io_finished)(void* cookie,
|
typedef fssh_status_t (*fssh_iterative_io_finished)(void* cookie,
|
||||||
fssh_io_request* request, fssh_status_t status);
|
fssh_io_request* request, fssh_status_t status,
|
||||||
|
bool partialTransfer, fssh_size_t bytesTransferred);
|
||||||
|
|
||||||
extern fssh_status_t fssh_new_vnode(fssh_fs_volume *volume,
|
extern fssh_status_t fssh_new_vnode(fssh_fs_volume *volume,
|
||||||
fssh_vnode_id vnodeID, void *privateNode,
|
fssh_vnode_id vnodeID, void *privateNode,
|
||||||
|
|||||||
@@ -94,13 +94,13 @@ void vfs_acquire_vnode(struct vnode *vnode);
|
|||||||
status_t vfs_get_cookie_from_fd(int fd, void **_cookie);
|
status_t vfs_get_cookie_from_fd(int fd, void **_cookie);
|
||||||
bool vfs_can_page(struct vnode *vnode, void *cookie);
|
bool vfs_can_page(struct vnode *vnode, void *cookie);
|
||||||
status_t vfs_read_pages(struct vnode *vnode, void *cookie, off_t pos,
|
status_t vfs_read_pages(struct vnode *vnode, void *cookie, off_t pos,
|
||||||
const iovec *vecs, size_t count, size_t *_numBytes);
|
const iovec *vecs, size_t count, uint32 flags, size_t *_numBytes);
|
||||||
status_t vfs_write_pages(struct vnode *vnode, void *cookie, off_t pos,
|
status_t vfs_write_pages(struct vnode *vnode, void *cookie, off_t pos,
|
||||||
const iovec *vecs, size_t count, size_t *_numBytes);
|
const iovec *vecs, size_t count, uint32 flags, size_t *_numBytes);
|
||||||
status_t vfs_vnode_io(struct vnode* vnode, void* cookie, io_request* request);
|
status_t vfs_vnode_io(struct vnode* vnode, void* cookie, io_request* request);
|
||||||
status_t vfs_synchronous_io(io_request* request,
|
status_t vfs_synchronous_io(io_request* request,
|
||||||
status_t (*doIO)(void* cookie, off_t offset, void* buffer,
|
status_t (*doIO)(void* cookie, off_t offset, void* buffer,
|
||||||
size_t length),
|
size_t* length),
|
||||||
void* cookie);
|
void* cookie);
|
||||||
status_t vfs_get_vnode_cache(struct vnode *vnode, struct VMCache **_cache,
|
status_t vfs_get_vnode_cache(struct vnode *vnode, struct VMCache **_cache,
|
||||||
bool allocate);
|
bool allocate);
|
||||||
|
|||||||
@@ -454,7 +454,8 @@ bfs_iterative_io_get_vecs(void* cookie, io_request *request, off_t offset,
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
bfs_iterative_io_finished(void *cookie, io_request *request, status_t status)
|
bfs_iterative_io_finished(void *cookie, io_request *request, status_t status,
|
||||||
|
bool partialTransfer, size_t bytesTransferred)
|
||||||
{
|
{
|
||||||
Inode *inode = (Inode*)cookie;
|
Inode *inode = (Inode*)cookie;
|
||||||
|
|
||||||
|
|||||||
Vendored
+2
@@ -1,5 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src system kernel cache ;
|
SubDir HAIKU_TOP src system kernel cache ;
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(SUBDIR) $(DOTDOT) device_manager ] ;
|
||||||
|
|
||||||
KernelMergeObject kernel_cache.o :
|
KernelMergeObject kernel_cache.o :
|
||||||
block_cache.cpp
|
block_cache.cpp
|
||||||
file_cache.cpp
|
file_cache.cpp
|
||||||
|
|||||||
+25
-35
@@ -24,6 +24,8 @@
|
|||||||
#include <vm_page.h>
|
#include <vm_page.h>
|
||||||
#include <vm_cache.h>
|
#include <vm_cache.h>
|
||||||
|
|
||||||
|
#include "io_requests.h"
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_FILE_CACHE
|
//#define TRACE_FILE_CACHE
|
||||||
#ifdef TRACE_FILE_CACHE
|
#ifdef TRACE_FILE_CACHE
|
||||||
@@ -196,12 +198,8 @@ read_into_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
|
|
||||||
cache->InsertPage(page, offset + pos);
|
cache->InsertPage(page, offset + pos);
|
||||||
|
|
||||||
addr_t virtualAddress;
|
add_to_iovec(vecs, vecCount, MAX_IO_VECS,
|
||||||
if (vm_get_physical_page(page->physical_page_number * B_PAGE_SIZE,
|
page->physical_page_number * B_PAGE_SIZE, B_PAGE_SIZE);
|
||||||
&virtualAddress, PHYSICAL_PAGE_CAN_WAIT) < B_OK)
|
|
||||||
panic("could not get physical page");
|
|
||||||
|
|
||||||
add_to_iovec(vecs, vecCount, MAX_IO_VECS, virtualAddress, B_PAGE_SIZE);
|
|
||||||
// TODO: check if the array is large enough (currently panics)!
|
// TODO: check if the array is large enough (currently panics)!
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,22 +209,12 @@ read_into_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
|
|
||||||
// read file into reserved pages
|
// read file into reserved pages
|
||||||
status_t status = vfs_read_pages(ref->vnode, cookie, offset, vecs,
|
status_t status = vfs_read_pages(ref->vnode, cookie, offset, vecs,
|
||||||
vecCount, &numBytes);
|
vecCount, B_PHYSICAL_IO_REQUEST, &numBytes);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
// reading failed, free allocated pages
|
// reading failed, free allocated pages
|
||||||
|
|
||||||
dprintf("file_cache: read pages failed: %s\n", strerror(status));
|
dprintf("file_cache: read pages failed: %s\n", strerror(status));
|
||||||
|
|
||||||
for (int32 i = 0; i < vecCount; i++) {
|
|
||||||
addr_t base = (addr_t)vecs[i].iov_base;
|
|
||||||
size_t size = vecs[i].iov_len;
|
|
||||||
|
|
||||||
for (size_t pos = 0; pos < size;
|
|
||||||
pos += B_PAGE_SIZE, base += B_PAGE_SIZE) {
|
|
||||||
vm_put_physical_page(base);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cache->Lock();
|
cache->Lock();
|
||||||
|
|
||||||
for (int32 i = 0; i < pageIndex; i++) {
|
for (int32 i = 0; i < pageIndex; i++) {
|
||||||
@@ -240,23 +228,24 @@ read_into_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
|
|
||||||
// copy the pages if needed and unmap them again
|
// copy the pages if needed and unmap them again
|
||||||
|
|
||||||
for (int32 i = 0; i < vecCount; i++) {
|
for (int32 i = 0; i < pageIndex; i++) {
|
||||||
addr_t base = (addr_t)vecs[i].iov_base;
|
|
||||||
size_t size = vecs[i].iov_len;
|
|
||||||
|
|
||||||
// copy to user buffer if necessary
|
|
||||||
if (useBuffer && bufferSize != 0) {
|
if (useBuffer && bufferSize != 0) {
|
||||||
size_t bytes = min_c(bufferSize, size - pageOffset);
|
addr_t virtualAddress;
|
||||||
|
if (vm_get_physical_page(
|
||||||
|
pages[i]->physical_page_number * B_PAGE_SIZE,
|
||||||
|
&virtualAddress, PHYSICAL_PAGE_CAN_WAIT) < B_OK) {
|
||||||
|
panic("could not get physical page");
|
||||||
|
}
|
||||||
|
|
||||||
user_memcpy((void *)buffer, (void *)(base + pageOffset), bytes);
|
size_t bytes = min_c(bufferSize, (size_t)B_PAGE_SIZE - pageOffset);
|
||||||
|
|
||||||
|
user_memcpy((void*)buffer, (void*)(virtualAddress + pageOffset),
|
||||||
|
bytes);
|
||||||
buffer += bytes;
|
buffer += bytes;
|
||||||
bufferSize -= bytes;
|
bufferSize -= bytes;
|
||||||
pageOffset = 0;
|
pageOffset = 0;
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t pos = 0; pos < size; pos += B_PAGE_SIZE,
|
vm_put_physical_page(virtualAddress);
|
||||||
base += B_PAGE_SIZE) {
|
|
||||||
vm_put_physical_page(base);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,7 +283,8 @@ read_from_file(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
vm_page_unreserve_pages(lastReservedPages);
|
vm_page_unreserve_pages(lastReservedPages);
|
||||||
|
|
||||||
status_t status = vfs_read_pages(ref->vnode, cookie, offset + pageOffset,
|
status_t status = vfs_read_pages(ref->vnode, cookie, offset + pageOffset,
|
||||||
&vec, 1, &bufferSize);
|
&vec, 1, 0, &bufferSize);
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
reserve_pages(ref, reservePages, false);
|
reserve_pages(ref, reservePages, false);
|
||||||
|
|
||||||
@@ -360,7 +350,7 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
iovec readVec = { vecs[0].iov_base, B_PAGE_SIZE };
|
iovec readVec = { vecs[0].iov_base, B_PAGE_SIZE };
|
||||||
size_t bytesRead = B_PAGE_SIZE;
|
size_t bytesRead = B_PAGE_SIZE;
|
||||||
|
|
||||||
status = vfs_read_pages(ref->vnode, cookie, offset, &readVec, 1,
|
status = vfs_read_pages(ref->vnode, cookie, offset, &readVec, 1, 0,
|
||||||
&bytesRead);
|
&bytesRead);
|
||||||
// ToDo: handle errors for real!
|
// ToDo: handle errors for real!
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
@@ -385,7 +375,7 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
|
|
||||||
status = vfs_read_pages(ref->vnode, cookie,
|
status = vfs_read_pages(ref->vnode, cookie,
|
||||||
PAGE_ALIGN(offset + pageOffset + bufferSize) - B_PAGE_SIZE,
|
PAGE_ALIGN(offset + pageOffset + bufferSize) - B_PAGE_SIZE,
|
||||||
&readVec, 1, &bytesRead);
|
&readVec, 1, 0, &bytesRead);
|
||||||
// ToDo: handle errors for real!
|
// ToDo: handle errors for real!
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
panic("vfs_read_pages() failed: %s!\n", strerror(status));
|
panic("vfs_read_pages() failed: %s!\n", strerror(status));
|
||||||
@@ -420,7 +410,7 @@ write_to_cache(file_cache_ref *ref, void *cookie, off_t offset,
|
|||||||
if (writeThrough) {
|
if (writeThrough) {
|
||||||
// write cached pages back to the file if we were asked to do that
|
// write cached pages back to the file if we were asked to do that
|
||||||
status_t status = vfs_write_pages(ref->vnode, cookie, offset, vecs,
|
status_t status = vfs_write_pages(ref->vnode, cookie, offset, vecs,
|
||||||
vecCount, &numBytes);
|
vecCount, 0, &numBytes);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
// ToDo: remove allocated pages, ...?
|
// ToDo: remove allocated pages, ...?
|
||||||
panic("file_cache: remove allocated pages! write pages failed: %s\n",
|
panic("file_cache: remove allocated pages! write pages failed: %s\n",
|
||||||
@@ -463,7 +453,7 @@ write_to_file(file_cache_ref *ref, void *cookie, off_t offset, int32 pageOffset,
|
|||||||
addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages,
|
addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages,
|
||||||
size_t reservePages)
|
size_t reservePages)
|
||||||
{
|
{
|
||||||
size_t chunkSize;
|
size_t chunkSize = 0;
|
||||||
if (!useBuffer) {
|
if (!useBuffer) {
|
||||||
// we need to allocate a zero buffer
|
// we need to allocate a zero buffer
|
||||||
// TODO: use smaller buffers if this fails
|
// TODO: use smaller buffers if this fails
|
||||||
@@ -491,7 +481,7 @@ write_to_file(file_cache_ref *ref, void *cookie, off_t offset, int32 pageOffset,
|
|||||||
chunkSize = bufferSize;
|
chunkSize = bufferSize;
|
||||||
|
|
||||||
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
||||||
&vec, 1, &chunkSize);
|
&vec, 1, 0, &chunkSize);
|
||||||
if (status < B_OK)
|
if (status < B_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -502,7 +492,7 @@ write_to_file(file_cache_ref *ref, void *cookie, off_t offset, int32 pageOffset,
|
|||||||
free((void*)buffer);
|
free((void*)buffer);
|
||||||
} else {
|
} else {
|
||||||
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
||||||
&vec, 1, &bufferSize);
|
&vec, 1, 0, &bufferSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
|
|||||||
+2
-2
@@ -46,7 +46,7 @@ VMVnodeCache::Read(off_t offset, const iovec *vecs, size_t count,
|
|||||||
size_t bytesUntouched = *_numBytes;
|
size_t bytesUntouched = *_numBytes;
|
||||||
|
|
||||||
status_t status = vfs_read_pages(fVnode, NULL, offset, vecs, count,
|
status_t status = vfs_read_pages(fVnode, NULL, offset, vecs, count,
|
||||||
_numBytes);
|
0, _numBytes);
|
||||||
|
|
||||||
bytesUntouched -= *_numBytes;
|
bytesUntouched -= *_numBytes;
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ status_t
|
|||||||
VMVnodeCache::Write(off_t offset, const iovec *vecs, size_t count,
|
VMVnodeCache::Write(off_t offset, const iovec *vecs, size_t count,
|
||||||
size_t *_numBytes)
|
size_t *_numBytes)
|
||||||
{
|
{
|
||||||
return vfs_write_pages(fVnode, NULL, offset, vecs, count, _numBytes);
|
return vfs_write_pages(fVnode, NULL, offset, vecs, count, 0, _numBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,8 @@ IOScheduler::AbortRequest(IORequest* request, status_t status)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IOScheduler::OperationCompleted(IOOperation* operation, status_t status)
|
IOScheduler::OperationCompleted(IOOperation* operation, status_t status,
|
||||||
|
size_t transferredBytes)
|
||||||
{
|
{
|
||||||
InterruptsSpinLocker _(fFinisherLock);
|
InterruptsSpinLocker _(fFinisherLock);
|
||||||
|
|
||||||
@@ -148,6 +149,11 @@ IOScheduler::OperationCompleted(IOOperation* operation, status_t status)
|
|||||||
|
|
||||||
operation->SetStatus(status);
|
operation->SetStatus(status);
|
||||||
|
|
||||||
|
// set the bytes transferred (of the net data)
|
||||||
|
size_t partialBegin = operation->OriginalOffset() - operation->Offset();
|
||||||
|
operation->SetTransferredBytes(
|
||||||
|
transferredBytes > partialBegin ? transferredBytes - partialBegin : 0);
|
||||||
|
|
||||||
fCompletedOperations.Add(operation);
|
fCompletedOperations.Add(operation);
|
||||||
fFinishedOperationCondition.NotifyAll();
|
fFinishedOperationCondition.NotifyAll();
|
||||||
|
|
||||||
@@ -175,6 +181,7 @@ IOScheduler::_Finisher()
|
|||||||
|
|
||||||
if (!operation->Finish()) {
|
if (!operation->Finish()) {
|
||||||
TRACE(" operation: %p not finished yet\n", operation);
|
TRACE(" operation: %p not finished yet\n", operation);
|
||||||
|
operation->SetTransferredBytes(0);
|
||||||
// TODO: This must be done differently once the scheduler implements
|
// TODO: This must be done differently once the scheduler implements
|
||||||
// an actual scheduling policy (other than no-op).
|
// an actual scheduling policy (other than no-op).
|
||||||
fIOCallback(fIOCallbackData, operation);
|
fIOCallback(fIOCallbackData, operation);
|
||||||
@@ -183,8 +190,15 @@ IOScheduler::_Finisher()
|
|||||||
|
|
||||||
// notify request and remove operation
|
// notify request and remove operation
|
||||||
IORequest* request = operation->Parent();
|
IORequest* request = operation->Parent();
|
||||||
if (request != NULL)
|
if (request != NULL) {
|
||||||
request->OperationFinished(operation, operation->Status());
|
size_t operationOffset = operation->OriginalOffset()
|
||||||
|
- request->Offset();
|
||||||
|
request->OperationFinished(operation, operation->Status(),
|
||||||
|
operation->TransferredBytes() < operation->OriginalLength(),
|
||||||
|
operation->Status() == B_OK
|
||||||
|
? operationOffset + operation->OriginalLength()
|
||||||
|
: operationOffset);
|
||||||
|
}
|
||||||
|
|
||||||
// recycle the operation
|
// recycle the operation
|
||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public:
|
|||||||
void AbortRequest(IORequest* request,
|
void AbortRequest(IORequest* request,
|
||||||
status_t status = B_CANCELED);
|
status_t status = B_CANCELED);
|
||||||
void OperationCompleted(IOOperation* operation,
|
void OperationCompleted(IOOperation* operation,
|
||||||
status_t status);
|
status_t status, size_t transferredBytes);
|
||||||
// called by the driver when the operation
|
// called by the driver when the operation
|
||||||
// has been completed successfully or failed
|
// has been completed successfully or failed
|
||||||
// for some reason
|
// for some reason
|
||||||
|
|||||||
@@ -756,26 +756,18 @@ get_device_name(struct devfs_vnode* vnode, char* buffer, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
device_read(void* _cookie, off_t offset, void* buffer, size_t length)
|
device_read(void* _cookie, off_t offset, void* buffer, size_t* length)
|
||||||
{
|
{
|
||||||
synchronous_io_cookie* cookie = (synchronous_io_cookie*)_cookie;
|
synchronous_io_cookie* cookie = (synchronous_io_cookie*)_cookie;
|
||||||
|
return cookie->device->Read(cookie->cookie, offset, buffer, length);
|
||||||
size_t transferred = length;
|
|
||||||
status_t error = cookie->device->Read(cookie->cookie, offset, buffer,
|
|
||||||
&transferred);
|
|
||||||
return error == B_OK && transferred != length ? B_FILE_ERROR : error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
device_write(void* _cookie, off_t offset, void* buffer, size_t length)
|
device_write(void* _cookie, off_t offset, void* buffer, size_t* length)
|
||||||
{
|
{
|
||||||
synchronous_io_cookie* cookie = (synchronous_io_cookie*)_cookie;
|
synchronous_io_cookie* cookie = (synchronous_io_cookie*)_cookie;
|
||||||
|
return cookie->device->Write(cookie->cookie, offset, buffer, length);
|
||||||
size_t transferred = length;
|
|
||||||
status_t error = cookie->device->Write(cookie->cookie, offset, buffer,
|
|
||||||
&transferred);
|
|
||||||
return error == B_OK && transferred != length ? B_FILE_ERROR : error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1753,6 +1745,8 @@ static status_t
|
|||||||
devfs_io(fs_volume *volume, fs_vnode *_vnode, void *_cookie,
|
devfs_io(fs_volume *volume, fs_vnode *_vnode, void *_cookie,
|
||||||
io_request *request)
|
io_request *request)
|
||||||
{
|
{
|
||||||
|
TRACE(("[%ld] devfs_io(request: %p)\n", find_thread(NULL), request));
|
||||||
|
|
||||||
devfs_vnode* vnode = (devfs_vnode*)_vnode->private_node;
|
devfs_vnode* vnode = (devfs_vnode*)_vnode->private_node;
|
||||||
devfs_cookie* cookie = (devfs_cookie*)_cookie;
|
devfs_cookie* cookie = (devfs_cookie*)_cookie;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "io_requests.h"
|
#include "io_requests.h"
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_DMA_RESOURCE
|
//#define TRACE_DMA_RESOURCE
|
||||||
#ifdef TRACE_DMA_RESOURCE
|
#ifdef TRACE_DMA_RESOURCE
|
||||||
# define TRACE(x...) dprintf(x)
|
# define TRACE(x...) dprintf(x)
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#include "dma_resources.h"
|
#include "dma_resources.h"
|
||||||
|
|
||||||
|
|
||||||
#define TRACE_IO_REQUEST
|
//#define TRACE_IO_REQUEST
|
||||||
#ifdef TRACE_IO_REQUEST
|
#ifdef TRACE_IO_REQUEST
|
||||||
# define TRACE(x...) dprintf(x)
|
# define TRACE(x...) dprintf(x)
|
||||||
#else
|
#else
|
||||||
@@ -237,6 +237,8 @@ IOOperation::Prepare(IORequest* request)
|
|||||||
|
|
||||||
fParent = request;
|
fParent = request;
|
||||||
|
|
||||||
|
fTransferredBytes = 0;
|
||||||
|
|
||||||
// set initial phase
|
// set initial phase
|
||||||
fPhase = PHASE_DO_ALL;
|
fPhase = PHASE_DO_ALL;
|
||||||
if (fParent->IsWrite()) {
|
if (fParent->IsWrite()) {
|
||||||
@@ -522,8 +524,8 @@ IORequest::Init(off_t offset, void* buffer, size_t length, bool write,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
IORequest::Init(off_t offset, size_t firstVecOffset, iovec* vecs, size_t count,
|
IORequest::Init(off_t offset, size_t firstVecOffset, const iovec* vecs,
|
||||||
size_t length, bool write, uint32 flags)
|
size_t count, size_t length, bool write, uint32 flags)
|
||||||
{
|
{
|
||||||
fBuffer = IOBuffer::Create(count);
|
fBuffer = IOBuffer::Create(count);
|
||||||
if (fBuffer == NULL)
|
if (fBuffer == NULL)
|
||||||
@@ -533,9 +535,12 @@ IORequest::Init(off_t offset, size_t firstVecOffset, iovec* vecs, size_t count,
|
|||||||
|
|
||||||
fOffset = offset;
|
fOffset = offset;
|
||||||
fLength = length;
|
fLength = length;
|
||||||
|
fRelativeParentOffset = 0;
|
||||||
|
fTransferSize = 0;
|
||||||
fFlags = flags;
|
fFlags = flags;
|
||||||
fTeam = team_get_current_team_id();
|
fTeam = team_get_current_team_id();
|
||||||
fIsWrite = write;
|
fIsWrite = write;
|
||||||
|
fPartialTransfer = 0;
|
||||||
|
|
||||||
// these are for iteration
|
// these are for iteration
|
||||||
fVecIndex = 0;
|
fVecIndex = 0;
|
||||||
@@ -596,6 +601,8 @@ IORequest::CreateSubRequest(off_t parentOffset, off_t offset, size_t length,
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
subRequest->fRelativeParentOffset = parentOffset - fOffset;
|
||||||
|
|
||||||
_subRequest = subRequest;
|
_subRequest = subRequest;
|
||||||
subRequest->SetParent(this);
|
subRequest->SetParent(this);
|
||||||
|
|
||||||
@@ -671,20 +678,23 @@ IORequest::NotifyFinished()
|
|||||||
|
|
||||||
MutexLocker locker(fLock);
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
if (fStatus == B_OK && RemainingBytes() > 0) {
|
if (fStatus == B_OK && !fPartialTransfer && RemainingBytes() > 0) {
|
||||||
// The request is not really done yet. If it has an iteration callback,
|
// The request is not really done yet. If it has an iteration callback,
|
||||||
// call it.
|
// call it.
|
||||||
if (fIterationCallback != NULL) {
|
if (fIterationCallback != NULL) {
|
||||||
ResetStatus();
|
ResetStatus();
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
status_t error = fIterationCallback(fIterationCookie, this);
|
bool partialTransfer = false;
|
||||||
if (error == B_OK)
|
status_t error = fIterationCallback(fIterationCookie, this,
|
||||||
|
&partialTransfer);
|
||||||
|
if (error == B_OK && !partialTransfer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Iteration failed, which means we're responsible for notifying the
|
// Iteration failed, which means we're responsible for notifying the
|
||||||
// requests finished.
|
// requests finished.
|
||||||
locker.Lock();
|
locker.Lock();
|
||||||
fStatus = error;
|
fStatus = error;
|
||||||
|
fPartialTransfer = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -695,6 +705,8 @@ IORequest::NotifyFinished()
|
|||||||
io_request_finished_callback finishedCallback = fFinishedCallback;
|
io_request_finished_callback finishedCallback = fFinishedCallback;
|
||||||
void* finishedCookie = fFinishedCookie;
|
void* finishedCookie = fFinishedCookie;
|
||||||
status_t status = fStatus;
|
status_t status = fStatus;
|
||||||
|
size_t lastTransferredOffset = fRelativeParentOffset + fTransferSize;
|
||||||
|
bool partialTransfer = status != B_OK || fPartialTransfer;
|
||||||
|
|
||||||
// unblock waiters
|
// unblock waiters
|
||||||
fFinishedCondition.NotifyAll();
|
fFinishedCondition.NotifyAll();
|
||||||
@@ -702,12 +714,16 @@ IORequest::NotifyFinished()
|
|||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
// notify callback
|
// notify callback
|
||||||
if (finishedCallback != NULL)
|
if (finishedCallback != NULL) {
|
||||||
finishedCallback(finishedCookie, this, status);
|
finishedCallback(finishedCookie, this, status, partialTransfer,
|
||||||
|
lastTransferredOffset);
|
||||||
|
}
|
||||||
|
|
||||||
// notify parent
|
// notify parent
|
||||||
if (parent != NULL)
|
if (parent != NULL) {
|
||||||
parent->SubRequestFinished(this, status);
|
parent->SubRequestFinished(this, status, partialTransfer,
|
||||||
|
lastTransferredOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -742,7 +758,8 @@ IORequest::SetStatusAndNotify(status_t status)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IORequest::OperationFinished(IOOperation* operation, status_t status)
|
IORequest::OperationFinished(IOOperation* operation, status_t status,
|
||||||
|
bool partialTransfer, size_t transferEndOffset)
|
||||||
{
|
{
|
||||||
TRACE("IORequest::OperationFinished(%p, %#lx): request: %p\n", operation,
|
TRACE("IORequest::OperationFinished(%p, %#lx): request: %p\n", operation,
|
||||||
status, this);
|
status, this);
|
||||||
@@ -752,6 +769,12 @@ IORequest::OperationFinished(IOOperation* operation, status_t status)
|
|||||||
fChildren.Remove(operation);
|
fChildren.Remove(operation);
|
||||||
operation->SetParent(NULL);
|
operation->SetParent(NULL);
|
||||||
|
|
||||||
|
if (status != B_OK || partialTransfer) {
|
||||||
|
if (fTransferSize > transferEndOffset)
|
||||||
|
fTransferSize = transferEndOffset;
|
||||||
|
fPartialTransfer = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (status != B_OK && fStatus == 1)
|
if (status != B_OK && fStatus == 1)
|
||||||
fStatus = status;
|
fStatus = status;
|
||||||
|
|
||||||
@@ -773,13 +796,20 @@ IORequest::OperationFinished(IOOperation* operation, status_t status)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IORequest::SubRequestFinished(IORequest* request, status_t status)
|
IORequest::SubRequestFinished(IORequest* request, status_t status,
|
||||||
|
bool partialTransfer, size_t transferEndOffset)
|
||||||
{
|
{
|
||||||
TRACE("IORequest::SubrequestFinished(%p, %#lx): request: %p\n", request,
|
TRACE("IORequest::SubrequestFinished(%p, %#lx, %d, %lu): request: %p\n",
|
||||||
status, this);
|
request, status, partialTransfer, transferEndOffset, this);
|
||||||
|
|
||||||
MutexLocker locker(fLock);
|
MutexLocker locker(fLock);
|
||||||
|
|
||||||
|
if (status != B_OK || partialTransfer) {
|
||||||
|
if (fTransferSize > transferEndOffset)
|
||||||
|
fTransferSize = transferEndOffset;
|
||||||
|
fPartialTransfer = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (status != B_OK && fStatus == 1)
|
if (status != B_OK && fStatus == 1)
|
||||||
fStatus = status;
|
fStatus = status;
|
||||||
|
|
||||||
@@ -798,12 +828,26 @@ IORequest::SubRequestFinished(IORequest* request, status_t status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
IORequest::SetTransferredBytes(bool partialTransfer, size_t transferredBytes)
|
||||||
|
{
|
||||||
|
TRACE("%p->IORequest::SetTransferredBytes(%d, %lu)\n", this,
|
||||||
|
partialTransfer, transferredBytes);
|
||||||
|
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
fPartialTransfer = partialTransfer;
|
||||||
|
fTransferSize = transferredBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IORequest::Advance(size_t bySize)
|
IORequest::Advance(size_t bySize)
|
||||||
{
|
{
|
||||||
TRACE("IORequest::Advance(%lu): remaining: %lu -> %lu\n", bySize,
|
TRACE("IORequest::Advance(%lu): remaining: %lu -> %lu\n", bySize,
|
||||||
fRemainingBytes, fRemainingBytes - bySize);
|
fRemainingBytes, fRemainingBytes - bySize);
|
||||||
fRemainingBytes -= bySize;
|
fRemainingBytes -= bySize;
|
||||||
|
fTransferSize += bySize;
|
||||||
|
|
||||||
iovec* vecs = fBuffer->Vecs();
|
iovec* vecs = fBuffer->Vecs();
|
||||||
while (vecs[fVecIndex].iov_len - fVecOffset <= bySize) {
|
while (vecs[fVecIndex].iov_len - fVecOffset <= bySize) {
|
||||||
|
|||||||
@@ -125,6 +125,11 @@ public:
|
|||||||
size_t OriginalLength() const
|
size_t OriginalLength() const
|
||||||
{ return fOriginalLength; }
|
{ return fOriginalLength; }
|
||||||
|
|
||||||
|
size_t TransferredBytes() const
|
||||||
|
{ return fTransferredBytes; }
|
||||||
|
void SetTransferredBytes(size_t bytes)
|
||||||
|
{ fTransferredBytes = bytes; }
|
||||||
|
|
||||||
iovec* Vecs() const;
|
iovec* Vecs() const;
|
||||||
uint32 VecCount() const;
|
uint32 VecCount() const;
|
||||||
|
|
||||||
@@ -159,6 +164,7 @@ protected:
|
|||||||
off_t fOriginalOffset;
|
off_t fOriginalOffset;
|
||||||
size_t fLength;
|
size_t fLength;
|
||||||
size_t fOriginalLength;
|
size_t fOriginalLength;
|
||||||
|
size_t fTransferredBytes;
|
||||||
size_t fBlockSize;
|
size_t fBlockSize;
|
||||||
uint16 fSavedVecIndex;
|
uint16 fSavedVecIndex;
|
||||||
uint16 fSavedVecLength;
|
uint16 fSavedVecLength;
|
||||||
@@ -174,9 +180,10 @@ typedef DoublyLinkedList<IOOperation> IOOperationList;
|
|||||||
|
|
||||||
typedef struct IORequest io_request;
|
typedef struct IORequest io_request;
|
||||||
typedef status_t (*io_request_finished_callback)(void* data,
|
typedef status_t (*io_request_finished_callback)(void* data,
|
||||||
io_request* request, status_t status);
|
io_request* request, status_t status, bool partialTransfer,
|
||||||
|
size_t transferEndOffset);
|
||||||
typedef status_t (*io_request_iterate_callback)(void* data,
|
typedef status_t (*io_request_iterate_callback)(void* data,
|
||||||
io_request* request);
|
io_request* request, bool* _partialTransfer);
|
||||||
|
|
||||||
|
|
||||||
struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
|
struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
|
||||||
@@ -185,13 +192,14 @@ struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
|
|||||||
|
|
||||||
status_t Init(off_t offset, void* buffer, size_t length,
|
status_t Init(off_t offset, void* buffer, size_t length,
|
||||||
bool write, uint32 flags);
|
bool write, uint32 flags);
|
||||||
status_t Init(off_t offset, iovec* vecs, size_t count,
|
status_t Init(off_t offset, const iovec* vecs,
|
||||||
size_t length, bool write, uint32 flags)
|
size_t count, size_t length, bool write,
|
||||||
|
uint32 flags)
|
||||||
{ return Init(offset, 0, vecs, count,
|
{ return Init(offset, 0, vecs, count,
|
||||||
length, write, flags); }
|
length, write, flags); }
|
||||||
status_t Init(off_t offset, size_t firstVecOffset,
|
status_t Init(off_t offset, size_t firstVecOffset,
|
||||||
iovec* vecs, size_t count, size_t length,
|
const iovec* vecs, size_t count,
|
||||||
bool write, uint32 flags);
|
size_t length, bool write, uint32 flags);
|
||||||
|
|
||||||
status_t CreateSubRequest(off_t parentOffset,
|
status_t CreateSubRequest(off_t parentOffset,
|
||||||
off_t offset, size_t length,
|
off_t offset, size_t length,
|
||||||
@@ -217,12 +225,20 @@ struct IORequest : IORequestChunk, DoublyLinkedListLinkImpl<IORequest> {
|
|||||||
void SetStatusAndNotify(status_t status);
|
void SetStatusAndNotify(status_t status);
|
||||||
|
|
||||||
void OperationFinished(IOOperation* operation,
|
void OperationFinished(IOOperation* operation,
|
||||||
status_t status);
|
status_t status, bool partialTransfer,
|
||||||
|
size_t transferEndOffset);
|
||||||
void SubRequestFinished(IORequest* request,
|
void SubRequestFinished(IORequest* request,
|
||||||
status_t status);
|
status_t status, bool partialTransfer,
|
||||||
|
size_t transferEndOffset);
|
||||||
|
|
||||||
size_t RemainingBytes() const
|
size_t RemainingBytes() const
|
||||||
{ return fRemainingBytes; }
|
{ return fRemainingBytes; }
|
||||||
|
size_t TransferredBytes() const
|
||||||
|
{ return fTransferSize; }
|
||||||
|
bool IsPartialTransfer() const
|
||||||
|
{ return fPartialTransfer; }
|
||||||
|
void SetTransferredBytes(bool partialTransfer,
|
||||||
|
size_t transferredBytes);
|
||||||
|
|
||||||
bool IsWrite() const { return fIsWrite; }
|
bool IsWrite() const { return fIsWrite; }
|
||||||
bool IsRead() const { return !fIsWrite; }
|
bool IsRead() const { return !fIsWrite; }
|
||||||
@@ -265,11 +281,20 @@ private:
|
|||||||
IOBuffer* fBuffer;
|
IOBuffer* fBuffer;
|
||||||
off_t fOffset;
|
off_t fOffset;
|
||||||
size_t fLength;
|
size_t fLength;
|
||||||
|
size_t fTransferSize;
|
||||||
|
// After all subrequests/operations have
|
||||||
|
// finished, number of contiguous bytes at
|
||||||
|
// the beginning of the request that have
|
||||||
|
// actually been transferred.
|
||||||
|
size_t fRelativeParentOffset;
|
||||||
|
// offset of this request relative to its
|
||||||
|
// parent
|
||||||
IORequestChunkList fChildren;
|
IORequestChunkList fChildren;
|
||||||
int32 fPendingChildren;
|
int32 fPendingChildren;
|
||||||
uint32 fFlags;
|
uint32 fFlags;
|
||||||
team_id fTeam;
|
team_id fTeam;
|
||||||
bool fIsWrite;
|
bool fIsWrite;
|
||||||
|
bool fPartialTransfer;
|
||||||
|
|
||||||
io_request_finished_callback fFinishedCallback;
|
io_request_finished_callback fFinishedCallback;
|
||||||
void* fFinishedCookie;
|
void* fFinishedCookie;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#include <vm_cache.h>
|
#include <vm_cache.h>
|
||||||
|
|
||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
|
#include "io_requests.h"
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_VFS
|
//#define TRACE_VFS
|
||||||
@@ -3899,21 +3900,41 @@ vfs_can_page(struct vnode *vnode, void *cookie)
|
|||||||
|
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
vfs_read_pages(struct vnode *vnode, void *cookie, off_t pos, const iovec *vecs,
|
vfs_read_pages(struct vnode *vnode, void *cookie, off_t pos, const iovec *vecs,
|
||||||
size_t count, size_t *_numBytes)
|
size_t count, uint32 flags, size_t *_numBytes)
|
||||||
{
|
{
|
||||||
FUNCTION(("vfs_read_pages: vnode %p, vecs %p, pos %Ld\n", vnode, vecs, pos));
|
FUNCTION(("vfs_read_pages: vnode %p, vecs %p, pos %Ld\n", vnode, vecs,
|
||||||
|
pos));
|
||||||
|
|
||||||
return FS_CALL(vnode, read_pages, cookie, pos, vecs, count, _numBytes);
|
IORequest request;
|
||||||
|
status_t status = request.Init(pos, vecs, count, *_numBytes, false, flags);
|
||||||
|
if (status == B_OK) {
|
||||||
|
status = vfs_vnode_io(vnode, cookie, &request);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = request.Wait();
|
||||||
|
*_numBytes = request.TransferredBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
vfs_write_pages(struct vnode *vnode, void *cookie, off_t pos, const iovec *vecs,
|
vfs_write_pages(struct vnode *vnode, void *cookie, off_t pos, const iovec *vecs,
|
||||||
size_t count, size_t *_numBytes)
|
size_t count, uint32 flags, size_t *_numBytes)
|
||||||
{
|
{
|
||||||
FUNCTION(("vfs_write_pages: vnode %p, vecs %p, pos %Ld\n", vnode, vecs, pos));
|
FUNCTION(("vfs_write_pages: vnode %p, vecs %p, pos %Ld\n", vnode, vecs,
|
||||||
|
pos));
|
||||||
|
|
||||||
return FS_CALL(vnode, write_pages, cookie, pos, vecs, count, _numBytes);
|
IORequest request;
|
||||||
|
status_t status = request.Init(pos, vecs, count, *_numBytes, true, flags);
|
||||||
|
if (status == B_OK) {
|
||||||
|
status = vfs_vnode_io(vnode, cookie, &request);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = request.Wait();
|
||||||
|
*_numBytes = request.TransferredBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,13 @@
|
|||||||
|
|
||||||
// included by vfs.cpp
|
// included by vfs.cpp
|
||||||
|
|
||||||
#include "io_requests.h"
|
|
||||||
|
//#define TRACE_VFS_REQUEST_IO
|
||||||
|
#ifdef TRACE_VFS_REQUEST_IO
|
||||||
|
# define TRACE_RIO(x...) dprintf(x)
|
||||||
|
#else
|
||||||
|
# define TRACE_RIO(x...) do {} while (false)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct iterative_io_cookie {
|
struct iterative_io_cookie {
|
||||||
@@ -33,13 +39,14 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t IO(off_t offset, void* _buffer, size_t length)
|
status_t IO(off_t offset, void* _buffer, size_t* _length)
|
||||||
{
|
{
|
||||||
if (!fIsPhysical)
|
if (!fIsPhysical)
|
||||||
return InternalIO(offset, _buffer, length);
|
return InternalIO(offset, _buffer, _length);
|
||||||
|
|
||||||
// buffer points to physical address -- map pages
|
// buffer points to physical address -- map pages
|
||||||
addr_t buffer = (addr_t)_buffer;
|
addr_t buffer = (addr_t)_buffer;
|
||||||
|
size_t length = *_length;
|
||||||
|
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
addr_t pageOffset = buffer % B_PAGE_SIZE;
|
addr_t pageOffset = buffer % B_PAGE_SIZE;
|
||||||
@@ -50,23 +57,29 @@ public:
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
size_t toTransfer = min_c(length, B_PAGE_SIZE - pageOffset);
|
size_t toTransfer = min_c(length, B_PAGE_SIZE - pageOffset);
|
||||||
|
size_t transferred = toTransfer;
|
||||||
error = InternalIO(offset, (void*)(virtualAddress + pageOffset),
|
error = InternalIO(offset, (void*)(virtualAddress + pageOffset),
|
||||||
toTransfer);
|
&transferred);
|
||||||
|
|
||||||
vm_put_physical_page(virtualAddress);
|
vm_put_physical_page(virtualAddress);
|
||||||
|
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
buffer += toTransfer;
|
offset += transferred;
|
||||||
length -= toTransfer;
|
buffer += transferred;
|
||||||
|
length -= transferred;
|
||||||
|
|
||||||
|
if (transferred != toTransfer)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*_length -= length;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual status_t InternalIO(off_t offset, void* buffer, size_t length) = 0;
|
virtual status_t InternalIO(off_t offset, void* buffer, size_t* length) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool fWrite;
|
bool fWrite;
|
||||||
@@ -78,7 +91,7 @@ class CallbackIO : public DoIO {
|
|||||||
public:
|
public:
|
||||||
CallbackIO(bool write, bool isPhysical,
|
CallbackIO(bool write, bool isPhysical,
|
||||||
status_t (*doIO)(void* cookie, off_t offset, void* buffer,
|
status_t (*doIO)(void* cookie, off_t offset, void* buffer,
|
||||||
size_t length),
|
size_t* length),
|
||||||
void* cookie)
|
void* cookie)
|
||||||
:
|
:
|
||||||
DoIO(write, isPhysical),
|
DoIO(write, isPhysical),
|
||||||
@@ -88,13 +101,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual status_t InternalIO(off_t offset, void* buffer, size_t length)
|
virtual status_t InternalIO(off_t offset, void* buffer, size_t* length)
|
||||||
{
|
{
|
||||||
return fDoIO(fCookie, offset, buffer, length);
|
return fDoIO(fCookie, offset, buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t (*fDoIO)(void*, off_t, void*, size_t);
|
status_t (*fDoIO)(void*, off_t, void*, size_t*);
|
||||||
void* fCookie;
|
void* fCookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -110,20 +123,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual status_t InternalIO(off_t offset, void* buffer, size_t length)
|
virtual status_t InternalIO(off_t offset, void* buffer, size_t* length)
|
||||||
{
|
{
|
||||||
size_t bytesTransferred = length;
|
if (fWrite)
|
||||||
status_t error;
|
return FS_CALL(fVnode, write, fCookie, offset, buffer, length);
|
||||||
if (fWrite) {
|
|
||||||
error = FS_CALL(fVnode, write, fCookie, offset, buffer,
|
|
||||||
&bytesTransferred);
|
|
||||||
} else {
|
|
||||||
error = FS_CALL(fVnode, read, fCookie, offset, buffer,
|
|
||||||
&bytesTransferred);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error == B_OK && bytesTransferred != length
|
return FS_CALL(fVnode, read, fCookie, offset, buffer, length);
|
||||||
? B_FILE_ERROR : error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -133,8 +138,12 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
do_iterative_fd_io_iterate(void* _cookie, io_request* request)
|
do_iterative_fd_io_iterate(void* _cookie, io_request* request,
|
||||||
|
bool* _partialTransfer)
|
||||||
{
|
{
|
||||||
|
TRACE_RIO("[%ld] do_iterative_fd_io_iterate(request: %p)\n",
|
||||||
|
find_thread(NULL), request);
|
||||||
|
|
||||||
static const int32 kMaxSubRequests = 8;
|
static const int32 kMaxSubRequests = 8;
|
||||||
|
|
||||||
iterative_io_cookie* cookie = (iterative_io_cookie*)_cookie;
|
iterative_io_cookie* cookie = (iterative_io_cookie*)_cookie;
|
||||||
@@ -152,16 +161,23 @@ do_iterative_fd_io_iterate(void* _cookie, io_request* request)
|
|||||||
requestLength, vecs, &vecCount);
|
requestLength, vecs, &vecCount);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
if (vecCount == 0)
|
if (vecCount == 0) {
|
||||||
return B_FILE_ERROR;
|
*_partialTransfer = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
TRACE_RIO("[%ld] got %lu file vecs\n", find_thread(NULL), vecCount);
|
||||||
|
|
||||||
// create subrequests for the file vecs we've got
|
// create subrequests for the file vecs we've got
|
||||||
int32 subRequestCount = 0;
|
int32 subRequestCount = 0;
|
||||||
for (uint32 i = 0; i < vecCount && subRequestCount < kMaxSubRequests; i++) {
|
for (uint32 i = 0; i < vecCount && subRequestCount < kMaxSubRequests; i++) {
|
||||||
off_t vecOffset = vecs[i].offset;
|
off_t vecOffset = vecs[i].offset;
|
||||||
off_t vecLength = vecs[i].length;
|
off_t vecLength = min_c(vecs[i].length, requestLength);
|
||||||
|
TRACE_RIO("[%ld] vec %lu offset: %lld, length: %lld\n",
|
||||||
|
find_thread(NULL), i, vecOffset, vecLength);
|
||||||
|
|
||||||
while (vecLength > 0 && subRequestCount < kMaxSubRequests) {
|
while (vecLength > 0 && subRequestCount < kMaxSubRequests) {
|
||||||
|
TRACE_RIO("[%ld] creating subrequest: offset: %lld, length: "
|
||||||
|
"%lld\n", find_thread(NULL), vecOffset, vecLength);
|
||||||
IORequest* subRequest;
|
IORequest* subRequest;
|
||||||
error = request->CreateSubRequest(requestOffset, vecOffset,
|
error = request->CreateSubRequest(requestOffset, vecOffset,
|
||||||
vecLength, subRequest);
|
vecLength, subRequest);
|
||||||
@@ -186,9 +202,14 @@ do_iterative_fd_io_iterate(void* _cookie, io_request* request)
|
|||||||
cookie->request_offset = requestOffset;
|
cookie->request_offset = requestOffset;
|
||||||
|
|
||||||
// Schedule the subrequests.
|
// Schedule the subrequests.
|
||||||
for (IORequest* subRequest = request->FirstSubRequest();
|
IORequest* nextSubRequest = request->FirstSubRequest();
|
||||||
(subRequest = request->NextSubRequest(subRequest)) != NULL;) {
|
while (nextSubRequest != NULL) {
|
||||||
|
IORequest* subRequest = nextSubRequest;
|
||||||
|
nextSubRequest = request->NextSubRequest(subRequest);
|
||||||
|
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
|
TRACE_RIO("[%ld] scheduling subrequest: %p\n", find_thread(NULL),
|
||||||
|
subRequest);
|
||||||
error = FS_CALL(cookie->vnode, io, cookie->descriptor->cookie,
|
error = FS_CALL(cookie->vnode, io, cookie->descriptor->cookie,
|
||||||
subRequest);
|
subRequest);
|
||||||
} else {
|
} else {
|
||||||
@@ -205,18 +226,21 @@ do_iterative_fd_io_iterate(void* _cookie, io_request* request)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
do_iterative_fd_io_finish(void* _cookie, io_request* request, status_t status)
|
do_iterative_fd_io_finish(void* _cookie, io_request* request, status_t status,
|
||||||
|
bool partialTransfer, size_t transferEndOffset)
|
||||||
{
|
{
|
||||||
iterative_io_cookie* cookie = (iterative_io_cookie*)_cookie;
|
iterative_io_cookie* cookie = (iterative_io_cookie*)_cookie;
|
||||||
|
|
||||||
if (cookie->finished != NULL)
|
if (cookie->finished != NULL) {
|
||||||
cookie->finished(cookie->cookie, request, status);
|
cookie->finished(cookie->cookie, request, status, partialTransfer,
|
||||||
|
transferEndOffset);
|
||||||
|
}
|
||||||
|
|
||||||
put_fd(cookie->descriptor);
|
put_fd(cookie->descriptor);
|
||||||
|
|
||||||
if (cookie->next_finished_callback != NULL) {
|
if (cookie->next_finished_callback != NULL) {
|
||||||
cookie->next_finished_callback(cookie->next_finished_cookie, request,
|
cookie->next_finished_callback(cookie->next_finished_cookie, request,
|
||||||
status);
|
status, partialTransfer, transferEndOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete cookie;
|
delete cookie;
|
||||||
@@ -242,35 +266,39 @@ do_synchronous_iterative_vnode_io(struct vnode* vnode, void* openCookie,
|
|||||||
|
|
||||||
for (int32 i = 0; error == B_OK && length > 0 && i < vecCount; i++) {
|
for (int32 i = 0; error == B_OK && length > 0 && i < vecCount; i++) {
|
||||||
uint8* vecBase = (uint8*)vecs[i].iov_base;
|
uint8* vecBase = (uint8*)vecs[i].iov_base;
|
||||||
size_t vecLength = vecs[i].iov_len;
|
size_t vecLength = min_c(vecs[i].iov_len, length);
|
||||||
if (vecLength > length)
|
|
||||||
vecLength = length;
|
|
||||||
|
|
||||||
while (error == B_OK && vecLength > 0) {
|
while (error == B_OK && vecLength > 0) {
|
||||||
file_io_vec fileVecs[8];
|
file_io_vec fileVecs[8];
|
||||||
uint32 fileVecCount = 8;
|
uint32 fileVecCount = 8;
|
||||||
error = getVecs(cookie, request, offset, vecLength, fileVecs,
|
error = getVecs(cookie, request, offset, vecLength, fileVecs,
|
||||||
&fileVecCount);
|
&fileVecCount);
|
||||||
if (error == B_OK && fileVecCount == 0)
|
if (error != B_OK || fileVecCount == 0)
|
||||||
error = B_FILE_ERROR;
|
|
||||||
if (error != B_OK)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
for (uint32 k = 0; k < fileVecCount; k++) {
|
for (uint32 k = 0; k < fileVecCount; k++) {
|
||||||
const file_io_vec& fileVec = fileVecs[i];
|
const file_io_vec& fileVec = fileVecs[i];
|
||||||
error = io.IO(fileVec.offset, vecBase, fileVec.length);
|
size_t toTransfer = min_c(fileVec.length, length);
|
||||||
|
size_t transferred = toTransfer;
|
||||||
|
error = io.IO(fileVec.offset, vecBase, &transferred);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
offset += fileVec.length;
|
offset += transferred;
|
||||||
length -= fileVec.length;
|
length -= transferred;
|
||||||
vecBase += fileVec.length;
|
vecBase += transferred;
|
||||||
vecLength -= fileVec.length;
|
vecLength -= transferred;
|
||||||
|
|
||||||
|
if (transferred != toTransfer)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finished(cookie, request, error);
|
bool partial = length > 0;
|
||||||
|
size_t bytesTransferred = request->Length() - length;
|
||||||
|
request->SetTransferredBytes(partial, bytesTransferred);
|
||||||
|
finished(cookie, request, error, partial, bytesTransferred);
|
||||||
request->SetStatusAndNotify(error);
|
request->SetStatusAndNotify(error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -279,6 +307,9 @@ do_synchronous_iterative_vnode_io(struct vnode* vnode, void* openCookie,
|
|||||||
static status_t
|
static status_t
|
||||||
synchronous_io(io_request* request, DoIO& io)
|
synchronous_io(io_request* request, DoIO& io)
|
||||||
{
|
{
|
||||||
|
TRACE_RIO("[%ld] synchronous_io(request: %p (offset: %lld, length: %lu))\n",
|
||||||
|
find_thread(NULL), request, request->Offset(), request->Length());
|
||||||
|
|
||||||
IOBuffer* buffer = request->Buffer();
|
IOBuffer* buffer = request->Buffer();
|
||||||
|
|
||||||
iovec* vecs = buffer->Vecs();
|
iovec* vecs = buffer->Vecs();
|
||||||
@@ -288,20 +319,29 @@ synchronous_io(io_request* request, DoIO& io)
|
|||||||
|
|
||||||
for (int32 i = 0; length > 0 && i < vecCount; i++) {
|
for (int32 i = 0; length > 0 && i < vecCount; i++) {
|
||||||
void* vecBase = vecs[i].iov_base;
|
void* vecBase = vecs[i].iov_base;
|
||||||
size_t vecLength = vecs[i].iov_len;
|
size_t vecLength = min_c(vecs[i].iov_len, length);
|
||||||
if (vecLength > length)
|
|
||||||
vecLength = length;
|
|
||||||
|
|
||||||
status_t error = io.IO(offset, vecBase, vecLength);
|
TRACE_RIO("[%ld] I/O: offset: %lld, vecBase: %p, length: %lu\n",
|
||||||
|
find_thread(NULL), offset, vecBase, vecLength);
|
||||||
|
|
||||||
|
size_t transferred = vecLength;
|
||||||
|
status_t error = io.IO(offset, vecBase, &transferred);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
|
TRACE_RIO("[%ld] I/O failed: %#lx\n", find_thread(NULL), error);
|
||||||
request->SetStatusAndNotify(error);
|
request->SetStatusAndNotify(error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset += vecLength;
|
offset += transferred;
|
||||||
length -= vecLength;
|
length -= transferred;
|
||||||
|
|
||||||
|
if (transferred != length)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE_RIO("[%ld] synchronous_io() succeeded\n", find_thread(NULL));
|
||||||
|
|
||||||
|
request->SetTransferredBytes(length > 0, request->Length() - length);
|
||||||
request->SetStatusAndNotify(B_OK);
|
request->SetStatusAndNotify(B_OK);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -326,7 +366,7 @@ vfs_vnode_io(struct vnode* vnode, void* cookie, io_request* request)
|
|||||||
|
|
||||||
status_t
|
status_t
|
||||||
vfs_synchronous_io(io_request* request,
|
vfs_synchronous_io(io_request* request,
|
||||||
status_t (*doIO)(void* cookie, off_t offset, void* buffer, size_t length),
|
status_t (*doIO)(void* cookie, off_t offset, void* buffer, size_t* length),
|
||||||
void* cookie)
|
void* cookie)
|
||||||
{
|
{
|
||||||
IOBuffer* buffer = request->Buffer();
|
IOBuffer* buffer = request->Buffer();
|
||||||
@@ -359,10 +399,14 @@ status_t
|
|||||||
do_iterative_fd_io(int fd, io_request* request, iterative_io_get_vecs getVecs,
|
do_iterative_fd_io(int fd, io_request* request, iterative_io_get_vecs getVecs,
|
||||||
iterative_io_finished finished, void* cookie)
|
iterative_io_finished finished, void* cookie)
|
||||||
{
|
{
|
||||||
|
TRACE_RIO("[%ld] do_iterative_fd_io(fd: %d, request: %p (offset: %lld, "
|
||||||
|
"length: %ld))\n", find_thread(NULL), fd, request, request->Offset(),
|
||||||
|
request->Length());
|
||||||
|
|
||||||
struct vnode* vnode;
|
struct vnode* vnode;
|
||||||
file_descriptor* descriptor = get_fd_and_vnode(fd, &vnode, true);
|
file_descriptor* descriptor = get_fd_and_vnode(fd, &vnode, true);
|
||||||
if (descriptor == NULL) {
|
if (descriptor == NULL) {
|
||||||
finished(cookie, request, B_FILE_ERROR);
|
finished(cookie, request, B_FILE_ERROR, true, 0);
|
||||||
request->SetStatusAndNotify(B_FILE_ERROR);
|
request->SetStatusAndNotify(B_FILE_ERROR);
|
||||||
return B_FILE_ERROR;
|
return B_FILE_ERROR;
|
||||||
}
|
}
|
||||||
@@ -396,9 +440,17 @@ do_iterative_fd_io(int fd, io_request* request, iterative_io_get_vecs getVecs,
|
|||||||
request->SetFinishedCallback(&do_iterative_fd_io_finish, iterationCookie);
|
request->SetFinishedCallback(&do_iterative_fd_io_finish, iterationCookie);
|
||||||
request->SetIterationCallback(&do_iterative_fd_io_iterate, iterationCookie);
|
request->SetIterationCallback(&do_iterative_fd_io_iterate, iterationCookie);
|
||||||
|
|
||||||
status_t error = do_iterative_fd_io_iterate(iterationCookie, request);
|
bool partialTransfer = false;
|
||||||
if (error != B_OK) {
|
status_t error = do_iterative_fd_io_iterate(iterationCookie, request,
|
||||||
finished(cookie, request, error);
|
&partialTransfer);
|
||||||
|
if (error != B_OK || partialTransfer) {
|
||||||
|
if (partialTransfer) {
|
||||||
|
request->SetTransferredBytes(partialTransfer,
|
||||||
|
request->TransferredBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
finished(cookie, request, error, request->IsPartialTransfer(),
|
||||||
|
request->TransferredBytes());
|
||||||
request->SetStatusAndNotify(error);
|
request->SetStatusAndNotify(error);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ do_io(void* data, IOOperation* operation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sIOScheduler != NULL)
|
if (sIOScheduler != NULL)
|
||||||
sIOScheduler->OperationCompleted(operation, B_OK);
|
sIOScheduler->OperationCompleted(operation, B_OK, operation->Length());
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,7 +584,10 @@ Test::Run(DMAResource& resource)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.OperationFinished(&operation, operation.Status());
|
request.OperationFinished(&operation, operation.Status(),
|
||||||
|
false,
|
||||||
|
operation.OriginalOffset() - operation.Parent()->Offset()
|
||||||
|
+ operation.OriginalLength());
|
||||||
|
|
||||||
resultIndex++;
|
resultIndex++;
|
||||||
}
|
}
|
||||||
@@ -959,7 +962,7 @@ run_test()
|
|||||||
// #pragma mark - driver
|
// #pragma mark - driver
|
||||||
|
|
||||||
|
|
||||||
float
|
static float
|
||||||
dma_test_supports_device(device_node *parent)
|
dma_test_supports_device(device_node *parent)
|
||||||
{
|
{
|
||||||
const char* bus = NULL;
|
const char* bus = NULL;
|
||||||
@@ -971,7 +974,7 @@ dma_test_supports_device(device_node *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_register_device(device_node *parent)
|
dma_test_register_device(device_node *parent)
|
||||||
{
|
{
|
||||||
device_attr attrs[] = {
|
device_attr attrs[] = {
|
||||||
@@ -984,7 +987,7 @@ dma_test_register_device(device_node *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_init_driver(device_node *node, void **_driverCookie)
|
dma_test_init_driver(device_node *node, void **_driverCookie)
|
||||||
{
|
{
|
||||||
sAreaSize = 10 * 1024 * 1024;
|
sAreaSize = 10 * 1024 * 1024;
|
||||||
@@ -1000,14 +1003,14 @@ dma_test_init_driver(device_node *node, void **_driverCookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
dma_test_uninit_driver(void *driverCookie)
|
dma_test_uninit_driver(void *driverCookie)
|
||||||
{
|
{
|
||||||
delete_area(sArea);
|
delete_area(sArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_register_child_devices(void *driverCookie)
|
dma_test_register_child_devices(void *driverCookie)
|
||||||
{
|
{
|
||||||
return sDeviceManager->publish_device((device_node*)driverCookie,
|
return sDeviceManager->publish_device((device_node*)driverCookie,
|
||||||
@@ -1019,7 +1022,7 @@ dma_test_register_child_devices(void *driverCookie)
|
|||||||
// #pragma mark - device
|
// #pragma mark - device
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_init_device(void *driverCookie, void **_deviceCookie)
|
dma_test_init_device(void *driverCookie, void **_deviceCookie)
|
||||||
{
|
{
|
||||||
const dma_restrictions restrictions = {
|
const dma_restrictions restrictions = {
|
||||||
@@ -1063,13 +1066,13 @@ dma_test_init_device(void *driverCookie, void **_deviceCookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
dma_test_uninit_device(void *deviceCookie)
|
dma_test_uninit_device(void *deviceCookie)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_open(void *deviceCookie, const char *path, int openMode,
|
dma_test_open(void *deviceCookie, const char *path, int openMode,
|
||||||
void **_cookie)
|
void **_cookie)
|
||||||
{
|
{
|
||||||
@@ -1077,21 +1080,21 @@ dma_test_open(void *deviceCookie, const char *path, int openMode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_close(void *cookie)
|
dma_test_close(void *cookie)
|
||||||
{
|
{
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_free(void *cookie)
|
dma_test_free(void *cookie)
|
||||||
{
|
{
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_read(void *cookie, off_t pos, void *buffer, size_t *_length)
|
dma_test_read(void *cookie, off_t pos, void *buffer, size_t *_length)
|
||||||
{
|
{
|
||||||
size_t length = *_length;
|
size_t length = *_length;
|
||||||
@@ -1123,7 +1126,7 @@ dma_test_read(void *cookie, off_t pos, void *buffer, size_t *_length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
|
dma_test_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
|
||||||
{
|
{
|
||||||
size_t length = *_length;
|
size_t length = *_length;
|
||||||
@@ -1157,14 +1160,16 @@ dma_test_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_io(void *cookie, io_request *request)
|
dma_test_io(void *cookie, io_request *request)
|
||||||
{
|
{
|
||||||
return B_BAD_VALUE;
|
dprintf("dma_test_io(%p)\n", request);
|
||||||
|
|
||||||
|
return sIOScheduler->ScheduleRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
static status_t
|
||||||
dma_test_control(void *cookie, uint32 op, void *buffer, size_t length)
|
dma_test_control(void *cookie, uint32 op, void *buffer, size_t length)
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
@@ -1219,7 +1224,7 @@ module_dependency module_dependencies[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const static struct driver_module_info sDMATestDriverModule = {
|
static const struct driver_module_info sDMATestDriverModule = {
|
||||||
{
|
{
|
||||||
"drivers/disk/dma_resource_test/driver_v1",
|
"drivers/disk/dma_resource_test/driver_v1",
|
||||||
0,
|
0,
|
||||||
@@ -1233,7 +1238,7 @@ const static struct driver_module_info sDMATestDriverModule = {
|
|||||||
dma_test_register_child_devices
|
dma_test_register_child_devices
|
||||||
};
|
};
|
||||||
|
|
||||||
const static struct device_module_info sDMATestDeviceModule = {
|
static const struct device_module_info sDMATestDeviceModule = {
|
||||||
{
|
{
|
||||||
"drivers/disk/dma_resource_test/device_v1",
|
"drivers/disk/dma_resource_test/device_v1",
|
||||||
0,
|
0,
|
||||||
@@ -1250,7 +1255,7 @@ const static struct device_module_info sDMATestDeviceModule = {
|
|||||||
|
|
||||||
dma_test_read,
|
dma_test_read,
|
||||||
dma_test_write,
|
dma_test_write,
|
||||||
NULL, // io
|
dma_test_io,
|
||||||
|
|
||||||
dma_test_control,
|
dma_test_control,
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user