From 663948966c47fdc1ef9df7a4592cfe0d40b91c0a Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 18 Aug 2008 23:09:10 +0000 Subject: [PATCH] Added method vfs_asynchronous_write_pages(), which, unsurprisingly, writes the given page iovecs asynchronously. The new class AsyncIOCallback is used to inform the caller when the request has been finished. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27055 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/vfs.h | 38 ++++++++++++++- src/system/kernel/fs/vfs_request_io.cpp | 64 +++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/headers/private/kernel/vfs.h b/headers/private/kernel/vfs.h index e8c621c700..0c4467a1c6 100644 --- a/headers/private/kernel/vfs.h +++ b/headers/private/kernel/vfs.h @@ -251,10 +251,44 @@ extern status_t _user_socketpair(int family, int type, int protocol, extern status_t _user_get_next_socket_stat(int family, uint32 *cookie, struct net_stat *stat); -/* vfs entry points... */ - #ifdef __cplusplus } #endif + +#ifdef __cplusplus + +class AsyncIOCallback { +public: + virtual ~AsyncIOCallback(); + + virtual void IOFinished(status_t status, + bool partialTransfer, + size_t bytesTransferred) = 0; + + void operator delete(void* address, size_t size); + + static status_t IORequestCallback(void* data, + io_request* request, status_t status, + bool partialTransfer, + size_t transferEndOffset); +}; + + +class StackableAsyncIOCallback : public AsyncIOCallback { +public: + StackableAsyncIOCallback(AsyncIOCallback* next); + +protected: + AsyncIOCallback* fNextCallback; +}; + + +status_t vfs_asynchronous_write_pages(struct vnode* vnode, void* cookie, + off_t pos, const iovec* vecs, size_t count, size_t numBytes, + uint32 flags, AsyncIOCallback* callback); + + +#endif // __cplusplus + #endif /* _KERNEL_VFS_H */ diff --git a/src/system/kernel/fs/vfs_request_io.cpp b/src/system/kernel/fs/vfs_request_io.cpp index 8ad94da6d2..3074f3c475 100644 --- a/src/system/kernel/fs/vfs_request_io.cpp +++ b/src/system/kernel/fs/vfs_request_io.cpp @@ -14,6 +14,44 @@ #endif +// #pragma mark - AsyncIOCallback + + +AsyncIOCallback::~AsyncIOCallback() +{ +} + + +void +AsyncIOCallback::operator delete(void* address, size_t size) +{ + io_request_free(address); +} + + +/* static */ status_t +AsyncIOCallback::IORequestCallback(void* data, io_request* request, + status_t status, bool partialTransfer, size_t transferEndOffset) +{ + ((AsyncIOCallback*)data)->IOFinished(status, partialTransfer, + transferEndOffset); + return B_OK; +} + + +// #pragma mark - StackableAsyncIOCallback + + +StackableAsyncIOCallback::StackableAsyncIOCallback(AsyncIOCallback* next) + : + fNextCallback(next) +{ +} + + +// #pragma mark - + + struct iterative_io_cookie { struct vnode* vnode; file_descriptor* descriptor; @@ -379,6 +417,32 @@ vfs_synchronous_io(io_request* request, } +status_t +vfs_asynchronous_write_pages(struct vnode* vnode, void* cookie, off_t pos, + const iovec* vecs, size_t count, size_t numBytes, uint32 flags, + AsyncIOCallback* callback) +{ + IORequest* request = IORequest::Create((flags & B_VIP_IO_REQUEST) != 0); + if (request == NULL) { + callback->IOFinished(B_NO_MEMORY, true, 0); + return B_NO_MEMORY; + } + + status_t status = request->Init(pos, vecs, count, numBytes, true, + flags | B_DELETE_IO_REQUEST); + if (status != B_OK) { + delete request; + callback->IOFinished(status, true, 0); + return status; + } + + request->SetFinishedCallback(&AsyncIOCallback::IORequestCallback, + callback); + + return vfs_vnode_io(vnode, cookie, request); +} + + // #pragma mark - public API