From 7c1ffcb9ec70c1bb997a4ecb9a9af82d5a657297 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 14 Mar 2009 02:32:25 +0000 Subject: [PATCH] * The nature of asynchronous I/O is to be asynchronous. So we can't store an on-stack structure for the request in a hash table when forwarding the io() hook. Create a new object (HaikuKernelIORequest) instead and store it in a hash table in HaikuKernelFileSystem. * Some work on the userland side of do_iterative_fd_io(). * Added some missing requests in UserlandFSUtil::is_{kernel,userland}_request(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29505 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/userlandfs/private/Requests.h | 39 ++++++- .../userlandfs/private/Requests.cpp | 70 ++++++++++++ .../userlandfs/server/IORequestInfo.h | 11 +- .../server/UserlandRequestHandler.cpp | 6 +- .../file_systems/userlandfs/server/Volume.cpp | 2 +- .../file_systems/userlandfs/server/Volume.h | 2 +- .../server/haiku/HaikuKernelFileSystem.cpp | 99 ++++++++++++++++- .../server/haiku/HaikuKernelFileSystem.h | 15 +++ .../server/haiku/HaikuKernelVolume.cpp | 100 ++++++++---------- .../server/haiku/HaikuKernelVolume.h | 8 +- .../server/haiku/haiku_kernel_emu.cpp | 51 ++++++--- .../userlandfs/server/kernel_emu.cpp | 47 ++++++++ .../userlandfs/server/kernel_emu.h | 19 ++-- 13 files changed, 373 insertions(+), 96 deletions(-) diff --git a/headers/private/userlandfs/private/Requests.h b/headers/private/userlandfs/private/Requests.h index ac94a24585..39f18cc336 100644 --- a/headers/private/userlandfs/private/Requests.h +++ b/headers/private/userlandfs/private/Requests.h @@ -227,6 +227,10 @@ enum { FILE_CACHE_WRITE_REQUEST, FILE_CACHE_WRITE_REPLY, + // I/O + DO_ITERATIVE_FD_IO_REQUEST, + DO_ITERATIVE_FD_IO_REPLY, + // general reply RECEIPT_ACK_REPLY, @@ -543,7 +547,7 @@ class DoIORequest : public FileRequest { public: DoIORequest() : FileRequest(DO_IO_REQUEST) {} - int32 ioRequest; + int32 request; bool isWrite; }; @@ -558,7 +562,7 @@ class CancelIORequest : public FileRequest { public: CancelIORequest() : FileRequest(CANCEL_IO_REQUEST) {} - int32 ioRequest; + int32 request; }; // CancelIOReply @@ -1740,6 +1744,29 @@ public: }; +// #pragma mark - I/O + + +// DoIterativeFDIORequest +class DoIterativeFDIORequest : public Request { +public: + DoIterativeFDIORequest() : Request(DO_ITERATIVE_FD_IO_REQUEST) {} + status_t GetAddressInfos(AddressInfo* infos, int32* count); + + int fd; + int32 request; + void* cookie; + Address vecs; + uint32 vecCount; +}; + +// DoIterativeFDIOReply +class DoIterativeFDIOReply : public ReplyRequest { +public: + DoIterativeFDIOReply() : ReplyRequest(DO_ITERATIVE_FD_IO_REPLY) {} +}; + + ////////////////// // General Reply @@ -2125,6 +2152,11 @@ do_for_request(Request* request, Task& task) return task((FileCacheWriteRequest*)request); case FILE_CACHE_WRITE_REPLY: return task((FileCacheWriteReply*)request); + // I/O + case DO_ITERATIVE_FD_IO_REQUEST: + return task((DoIterativeFDIORequest*)request); + case DO_ITERATIVE_FD_IO_REPLY: + return task((DoIterativeFDIOReply*)request); // general reply case RECEIPT_ACK_REPLY: return task((ReceiptAckReply*)request); @@ -2340,6 +2372,9 @@ using UserlandFSUtil::FileCacheReadRequest; using UserlandFSUtil::FileCacheReadReply; using UserlandFSUtil::FileCacheWriteRequest; using UserlandFSUtil::FileCacheWriteReply; +// I/O +using UserlandFSUtil::DoIterativeFDIORequest; +using UserlandFSUtil::DoIterativeFDIOReply; // general reply using UserlandFSUtil::ReceiptAckReply; diff --git a/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp b/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp index 1041c567f7..30fe0866c5 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp @@ -313,6 +313,14 @@ FileCacheWriteRequest::GetAddressInfos(AddressInfo* infos, int32* count) return B_OK; } +// DoIterativeFDIORequest +status_t +DoIterativeFDIORequest::GetAddressInfos(AddressInfo* infos, int32* count) +{ + ADD_ADDRESS(vecs); + return B_OK; +} + // #pragma mark - @@ -531,6 +539,13 @@ UserlandFSUtil::is_kernel_request(uint32 type) case WRITE_VNODE_REPLY: case FS_REMOVE_VNODE_REPLY: return false; + // asynchronous I/O + case DO_IO_REQUEST: + case CANCEL_IO_REQUEST: + return true; + case DO_IO_REPLY: + case CANCEL_IO_REPLY: + return false; // nodes case IOCTL_REQUEST: case SET_FLAGS_REQUEST: @@ -674,6 +689,7 @@ UserlandFSUtil::is_kernel_request(uint32 type) // vnodes case GET_VNODE_REQUEST: case PUT_VNODE_REQUEST: + case ACQUIRE_VNODE_REQUEST: case NEW_VNODE_REQUEST: case PUBLISH_VNODE_REQUEST: case REMOVE_VNODE_REQUEST: @@ -682,12 +698,35 @@ UserlandFSUtil::is_kernel_request(uint32 type) return false; case GET_VNODE_REPLY: case PUT_VNODE_REPLY: + case ACQUIRE_VNODE_REPLY: case NEW_VNODE_REPLY: case PUBLISH_VNODE_REPLY: case REMOVE_VNODE_REPLY: case UNREMOVE_VNODE_REPLY: case GET_VNODE_REMOVED_REPLY: return true; + // file cache + case FILE_CACHE_CREATE_REQUEST: + case FILE_CACHE_DELETE_REQUEST: + case FILE_CACHE_SET_ENABLED_REQUEST: + case FILE_CACHE_SET_SIZE_REQUEST: + case FILE_CACHE_SYNC_REQUEST: + case FILE_CACHE_READ_REQUEST: + case FILE_CACHE_WRITE_REQUEST: + return false; + case FILE_CACHE_CREATE_REPLY: + case FILE_CACHE_DELETE_REPLY: + case FILE_CACHE_SET_ENABLED_REPLY: + case FILE_CACHE_SET_SIZE_REPLY: + case FILE_CACHE_SYNC_REPLY: + case FILE_CACHE_READ_REPLY: + case FILE_CACHE_WRITE_REPLY: + return true; + // I/O + case DO_ITERATIVE_FD_IO_REQUEST: + return false; + case DO_ITERATIVE_FD_IO_REPLY: + return true; // general reply case RECEIPT_ACK_REPLY: @@ -737,6 +776,13 @@ UserlandFSUtil::is_userland_request(uint32 type) case WRITE_VNODE_REPLY: case FS_REMOVE_VNODE_REPLY: return true; + // asynchronous I/O + case DO_IO_REQUEST: + case CANCEL_IO_REQUEST: + return false; + case DO_IO_REPLY: + case CANCEL_IO_REPLY: + return true; // nodes case IOCTL_REQUEST: case SET_FLAGS_REQUEST: @@ -880,6 +926,7 @@ UserlandFSUtil::is_userland_request(uint32 type) // vnodes case GET_VNODE_REQUEST: case PUT_VNODE_REQUEST: + case ACQUIRE_VNODE_REQUEST: case NEW_VNODE_REQUEST: case PUBLISH_VNODE_REQUEST: case REMOVE_VNODE_REQUEST: @@ -888,12 +935,35 @@ UserlandFSUtil::is_userland_request(uint32 type) return true; case GET_VNODE_REPLY: case PUT_VNODE_REPLY: + case ACQUIRE_VNODE_REPLY: case NEW_VNODE_REPLY: case PUBLISH_VNODE_REPLY: case REMOVE_VNODE_REPLY: case UNREMOVE_VNODE_REPLY: case GET_VNODE_REMOVED_REPLY: return false; + // file cache + case FILE_CACHE_CREATE_REQUEST: + case FILE_CACHE_DELETE_REQUEST: + case FILE_CACHE_SET_ENABLED_REQUEST: + case FILE_CACHE_SET_SIZE_REQUEST: + case FILE_CACHE_SYNC_REQUEST: + case FILE_CACHE_READ_REQUEST: + case FILE_CACHE_WRITE_REQUEST: + return true; + case FILE_CACHE_CREATE_REPLY: + case FILE_CACHE_DELETE_REPLY: + case FILE_CACHE_SET_ENABLED_REPLY: + case FILE_CACHE_SET_SIZE_REPLY: + case FILE_CACHE_SYNC_REPLY: + case FILE_CACHE_READ_REPLY: + case FILE_CACHE_WRITE_REPLY: + return false; + // I/O + case DO_ITERATIVE_FD_IO_REQUEST: + return false; + case DO_ITERATIVE_FD_IO_REPLY: + return true; // general reply case RECEIPT_ACK_REPLY: diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/IORequestInfo.h b/src/add-ons/kernel/file_systems/userlandfs/server/IORequestInfo.h index 588c162f7d..071a57fc14 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/IORequestInfo.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/IORequestInfo.h @@ -5,12 +5,12 @@ #ifndef USERLAND_FS_IO_REQUEST_INFO_H #define USERLAND_FS_IO_REQUEST_INFO_H -#include +#include namespace UserlandFS { -struct IORequestInfo : HashTableLink { +struct IORequestInfo { int32 id; bool isWrite; @@ -20,6 +20,13 @@ struct IORequestInfo : HashTableLink { isWrite(isWrite) { } + + IORequestInfo(const IORequestInfo& other) + : + id(other.id), + isWrite(other.isWrite) + { + } }; } // namespace UserlandFS diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp index 1128c86f76..23aa900e0a 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp @@ -552,8 +552,8 @@ UserlandRequestHandler::_HandleRequest(DoIORequest* request) if (result == B_OK) { RequestThreadContext context(volume); - IORequestInfo requestInfo(request->ioRequest, request->isWrite); - result = volume->DoIO(request->node, request->fileCookie, &requestInfo); + IORequestInfo requestInfo(request->request, request->isWrite); + result = volume->DoIO(request->node, request->fileCookie, requestInfo); } // prepare the reply @@ -582,7 +582,7 @@ UserlandRequestHandler::_HandleRequest(CancelIORequest* request) if (result == B_OK) { RequestThreadContext context(volume); result = volume->CancelIO(request->node, request->fileCookie, - request->ioRequest); + request->request); } // prepare the reply diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp index 0c031cb991..93b8a1ca64 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp @@ -193,7 +193,7 @@ Volume::RemoveVNode(void* node, bool reenter) status_t -Volume::DoIO(void* node, void* cookie, IORequestInfo* requestInfo) +Volume::DoIO(void* node, void* cookie, const IORequestInfo& requestInfo) { return B_BAD_VALUE; } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h index c652ca2267..f645cb639f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h @@ -55,7 +55,7 @@ public: // asynchronous I/O virtual status_t DoIO(void* node, void* cookie, - IORequestInfo* requestInfo); + const IORequestInfo& requestInfo); virtual status_t CancelIO(void* node, void* cookie, int32 ioRequestID); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp index 07135ac158..c131dc8aba 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.cpp @@ -8,20 +8,50 @@ #include +#include + #include #include +#include "HaikuKernelIORequest.h" #include "HaikuKernelVolume.h" +// IORequestHashDefinition +struct HaikuKernelFileSystem::IORequestHashDefinition { + typedef int32 KeyType; + typedef HaikuKernelIORequest ValueType; + + size_t HashKey(int32 key) const + { return key; } + size_t Hash(const HaikuKernelIORequest* value) const + { return value->id; } + bool Compare(int32 key, const HaikuKernelIORequest* value) const + { return value->id == key; } + HashTableLink* + GetLink(HaikuKernelIORequest* value) const + { return value; } +}; + + +// IORequestTable +struct HaikuKernelFileSystem::IORequestTable + : public OpenHashTable { +}; + + // constructor HaikuKernelFileSystem::HaikuKernelFileSystem(file_system_module_info* fsModule) - : FileSystem(), - fFSModule(fsModule) + : + FileSystem(), + fFSModule(fsModule), + fIORequests(NULL), + fLock("HaikuKernelFileSystem") { _InitCapabilities(); } + // destructor HaikuKernelFileSystem::~HaikuKernelFileSystem() { @@ -29,19 +59,35 @@ HaikuKernelFileSystem::~HaikuKernelFileSystem() if (fFSModule->info.std_ops) fFSModule->info.std_ops(B_MODULE_UNINIT); + delete fIORequests; + // TODO: Call the cleanup methods (condition vars, block cache)! } + // Init status_t HaikuKernelFileSystem::Init() { + status_t error = fLock.InitCheck(); + if (error != B_OK) + RETURN_ERROR(error); + // init condition variables condition_variable_init(); // TODO: Call the cleanup methods, if something goes wrong! // init block cache - status_t error = block_cache_init(); + error = block_cache_init(); + if (error != B_OK) + RETURN_ERROR(error); + + // create I/O request map + fIORequests = new(std::nothrow) IORequestTable; + if (fIORequests == NULL) + RETURN_ERROR(B_NO_MEMORY); + + error = fIORequests->Init(); if (error != B_OK) RETURN_ERROR(error); @@ -56,6 +102,7 @@ HaikuKernelFileSystem::Init() return B_OK; } + // CreateVolume status_t HaikuKernelFileSystem::CreateVolume(Volume** _volume, dev_t id) @@ -79,6 +126,7 @@ HaikuKernelFileSystem::CreateVolume(Volume** _volume, dev_t id) return B_OK; } + // DeleteVolume status_t HaikuKernelFileSystem::DeleteVolume(Volume* volume) @@ -89,6 +137,51 @@ HaikuKernelFileSystem::DeleteVolume(Volume* volume) return B_OK; } + +// AddIORequest +status_t +HaikuKernelFileSystem::AddIORequest(HaikuKernelIORequest* request) +{ + AutoLocker _(fLock); + + // check, if a request with that ID is already in the map + if (fIORequests->Lookup(request->id) != NULL) + RETURN_ERROR(B_BAD_VALUE); + + fIORequests->Insert(request); + return B_OK; +} + + +// GetIORequest +HaikuKernelIORequest* +HaikuKernelFileSystem::GetIORequest(int32 requestID) +{ + AutoLocker _(fLock); + + HaikuKernelIORequest* request = fIORequests->Lookup(requestID); + if (request != NULL) + request->refCount++; + + return request; +} + + +// PutIORequest +void +HaikuKernelFileSystem::PutIORequest(HaikuKernelIORequest* request, + int32 refCount) +{ + AutoLocker locker(fLock); + + if ((request->refCount -= refCount) <= 0) { + fIORequests->Remove(request); + locker.Unlock(); + delete request; + } +} + + // _InitCapabilities void HaikuKernelFileSystem::_InitCapabilities() diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.h index 1eb4e49ae6..d74bfde55a 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelFileSystem.h @@ -3,12 +3,16 @@ #ifndef USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H #define USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H +#include "Locker.h" + #include "../FileSystem.h" struct file_system_module_info; namespace UserlandFS { +struct HaikuKernelIORequest; + class HaikuKernelFileSystem : public FileSystem { public: HaikuKernelFileSystem( @@ -20,11 +24,22 @@ public: virtual status_t CreateVolume(Volume** volume, dev_t id); virtual status_t DeleteVolume(Volume* volume); + status_t AddIORequest(HaikuKernelIORequest* request); + HaikuKernelIORequest* GetIORequest(int32 requestID); + void PutIORequest(HaikuKernelIORequest* request, + int32 refCount = 1); + +private: + class IORequestHashDefinition; + class IORequestTable; + private: void _InitCapabilities(); private: file_system_module_info* fFSModule; + IORequestTable* fIORequests; + Locker fLock; }; } // namespace UserlandFS diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp index 29ccbf8a35..65fe7a9326 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.cpp @@ -15,6 +15,8 @@ #include "../IORequestInfo.h" #include "../kernel_emu.h" +#include "HaikuKernelFileSystem.h" +#include "HaikuKernelIORequest.h" #include "HaikuKernelNode.h" @@ -24,26 +26,12 @@ class HaikuKernelVolume::NodeMap }; -// IORequestHashDefinition -struct HaikuKernelVolume::IORequestHashDefinition { - typedef int32 KeyType; - typedef IORequestInfo ValueType; - - size_t HashKey(int32 key) const - { return key; } - size_t Hash(const IORequestInfo* value) const - { return value->id; } - bool Compare(int32 key, const IORequestInfo* value) const - { return value->id == key; } - HashTableLink* GetLink(IORequestInfo* value) const - { return value; } -}; - - -// IORequestTable -struct HaikuKernelVolume::IORequestTable - : public OpenHashTable { -}; +// _FileSystem +inline HaikuKernelFileSystem* +HaikuKernelVolume::_FileSystem() const +{ + return static_cast(fFileSystem); +} // constructor @@ -52,8 +40,7 @@ HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id, : Volume(fileSystem, id), fFSModule(fsModule), - fNodes(NULL), - fIORequests(NULL) + fNodes(NULL) { fVolume.id = id; fVolume.partition = -1; @@ -71,7 +58,6 @@ HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id, HaikuKernelVolume::~HaikuKernelVolume() { delete fNodes; - delete fIORequests; } @@ -82,14 +68,7 @@ HaikuKernelVolume::Init() fNodes = new(std::nothrow) NodeMap; if (fNodes == NULL) return B_NO_MEMORY; - status_t error = fNodes->InitCheck(); - if (error != B_OK) - return error; - - fIORequests = new(std::nothrow) IORequestTable; - if (fIORequests == NULL) - return B_NO_MEMORY; - return fIORequests->Init(); + return fNodes->InitCheck(); } @@ -184,14 +163,6 @@ HaikuKernelVolume::NodeWithID(ino_t vnodeID) const } -IORequestInfo* -HaikuKernelVolume::IORequestInfoWithID(int32 id) const -{ - AutoLocker locker(fNodes); - return fIORequests->Lookup(id); -} - - // #pragma mark - // #pragma mark ----- FS ----- @@ -374,30 +345,39 @@ HaikuKernelVolume::RemoveVNode(void* _node, bool reenter) status_t -HaikuKernelVolume::DoIO(void* _node, void* cookie, IORequestInfo* requestInfo) +HaikuKernelVolume::DoIO(void* _node, void* cookie, + const IORequestInfo& requestInfo) { HaikuKernelNode* node = (HaikuKernelNode*)_node; if (!node->ops->io) return B_BAD_VALUE; - // add the info to the table - AutoLocker locker(fNodes); - if (fIORequests->Lookup(requestInfo->id)) - RETURN_ERROR(B_BAD_VALUE); + // create a request object + HaikuKernelIORequest* request + = new(std::nothrow) HaikuKernelIORequest(requestInfo); + if (request == NULL) + RETURN_ERROR(B_NO_MEMORY); - fIORequests->Insert(requestInfo); - locker.Unlock(); + status_t error = _FileSystem()->AddIORequest(request); + if (error != B_OK) { + delete request; + RETURN_ERROR(error); + } // call the hook - status_t error = node->ops->io(&fVolume, node, cookie, - (io_request*)(addr_t)requestInfo->id); + error = node->ops->io(&fVolume, node, cookie, (io_request*)request); - // remove the info from the table - locker.Lock(); - fIORequests->Remove(requestInfo); + // directly put our reference to the request, if the call failed + if (error != B_OK) { + _FileSystem()->PutIORequest(request); + RETURN_ERROR(error); + } - return error; + // TODO: ATM we don't release our reference when the request is finished + // normally! + + return B_OK; } @@ -409,8 +389,20 @@ HaikuKernelVolume::CancelIO(void* _node, void* cookie, int32 ioRequestID) if (!node->ops->cancel_io) return B_BAD_VALUE; - return node->ops->cancel_io(&fVolume, node, cookie, - (io_request*)(addr_t)ioRequestID); + // get the request + HaikuKernelIORequest* request = _FileSystem()->GetIORequest(ioRequestID); + if (request == NULL) + RETURN_ERROR(B_BAD_VALUE); + + // call the hook + status_t error = node->ops->cancel_io(&fVolume, node, cookie, + (io_request*)request); + + // put the request -- once for the reference we got above, once for the + // reference we've got in DoIO() + _FileSystem()->PutIORequest(request, 2); + + return error; } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h index ad2f1bbc5a..090ff550da 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/HaikuKernelVolume.h @@ -9,6 +9,7 @@ namespace UserlandFS { +class HaikuKernelFileSystem; class HaikuKernelNode; @@ -34,7 +35,6 @@ public: void UndoPublishVNode(HaikuKernelNode* node); HaikuKernelNode* NodeWithID(ino_t vnodeID) const; - IORequestInfo* IORequestInfoWithID(int32 id) const; // FS virtual status_t Mount(const char* device, uint32 flags, @@ -62,7 +62,7 @@ public: // asynchronous I/O virtual status_t DoIO(void* node, void* cookie, - IORequestInfo* requestInfo); + const IORequestInfo& requestInfo); virtual status_t CancelIO(void* node, void* cookie, int32 ioRequestID); @@ -185,17 +185,15 @@ private: }; class NodeMap; - class IORequestHashDefinition; - class IORequestTable; private: void _InitCapabilities(); + inline HaikuKernelFileSystem* _FileSystem() const; private: file_system_module_info* fFSModule; FSVolume fVolume; NodeMap* fNodes; - IORequestTable* fIORequests; }; diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp index fb0be0c57c..ec1e528b03 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp @@ -21,6 +21,7 @@ #include "../kernel_emu.h" #include "../RequestThread.h" +#include "HaikuKernelIORequest.h" #include "HaikuKernelNode.h" #include "HaikuKernelVolume.h" #include "vfs.h" @@ -270,11 +271,39 @@ do_fd_io(int fd, io_request *request) // do_iterative_fd_io status_t -do_iterative_fd_io(int fd, io_request *request, iterative_io_get_vecs getVecs, - iterative_io_finished finished, void *cookie) +do_iterative_fd_io(int fd, io_request *_request, iterative_io_get_vecs getVecs, + iterative_io_finished finished, void *_cookie) { - // TODO: Implement! - return B_UNSUPPORTED; +#if 0 + // get some vecs already + file_io_vec fileVecs[8]; + uint32 fileVecCount = 8; + status_t error = getVecs(_cookie, _request, offset, vecLength, fileVecs, + &fileVecCount); +// TODO: We don't have the offset here. We should pass it along in the +// DoIORequest. +#endif + + HaikuKernelIORequest* request = (HaikuKernelIORequest*)_request; + + // create a cookie + HaikuKernelIterativeFDIOCookie* cookie + = new(std::nothrow) HaikuKernelIterativeFDIOCookie(fd, request, getVecs, + finished, _cookie); + if (cookie == NULL) { + finished(_cookie, _request, B_NO_MEMORY, false, 0); + return B_NO_MEMORY; + } + + // send the request + status_t error = UserlandFS::KernelEmu::do_iterative_fd_io(fd, request->id, + cookie, NULL, 0); + if (error != B_OK) { + delete cookie; + return error; + } + + return B_OK; } @@ -284,19 +313,7 @@ do_iterative_fd_io(int fd, io_request *request, iterative_io_get_vecs getVecs, bool io_request_is_write(const io_request* request) { - // get the volume - RequestThread* thread = RequestThread::GetCurrentThread(); - if (thread == NULL || thread->GetContext() == NULL) - return false; - - HaikuKernelVolume* volume = dynamic_cast( - thread->GetContext()->GetVolume()); - if (volume == NULL) - return false; - - // get the request info - IORequestInfo* info = volume->IORequestInfoWithID((int32)(addr_t)request); - return info != NULL && info->isWrite; + return ((HaikuKernelIORequest*)request)->isWrite; } diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp index 34ea17351c..a552f8c95e 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp @@ -837,6 +837,53 @@ UserlandFS::KernelEmu::file_cache_write(dev_t mountID, ino_t vnodeID, } +// #pragma mark - I/O + + +status_t +UserlandFS::KernelEmu::do_iterative_fd_io(int fd, int32 requestID, void* cookie, + const file_io_vec* vecs, uint32 vecCount) +{ + // get the request port and the file system + RequestPort* port; + FileSystem* fileSystem; + status_t error = get_port_and_fs(&port, &fileSystem); + if (error != B_OK) + return error; + + // prepare the request + RequestAllocator allocator(port->GetPort()); + DoIterativeFDIORequest* request; + error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->fd = fd; + request->request = requestID; + request->cookie = cookie; + request->vecCount = vecCount; + + if (vecCount > 0) { + error = allocator.AllocateData(request->vecs, vecs, + vecCount * sizeof(file_io_vec), sizeof(off_t), false); + if (error != B_OK) + return error; + } + + // send the request + UserlandRequestHandler handler(fileSystem, DO_ITERATIVE_FD_IO_REPLY); + DoIterativeFDIOReply* reply; + error = port->SendRequest(&allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; +// TODO: Up to this point we should call the finished hook or error! + RequestReleaser requestReleaser(port, reply); + + // process the reply + return reply->error; +} + + // #pragma mark - diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h index 778a847311..7acabd9910 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h @@ -5,6 +5,7 @@ #include struct selectsync; +struct file_io_vec; namespace UserlandFS { namespace KernelEmu { @@ -31,18 +32,20 @@ status_t remove_vnode(dev_t nsid, ino_t vnid); status_t unremove_vnode(dev_t nsid, ino_t vnid); status_t get_vnode_removed(dev_t nsid, ino_t vnid, bool* removed); -extern status_t file_cache_create(dev_t mountID, ino_t vnodeID, off_t size); -extern status_t file_cache_delete(dev_t mountID, ino_t vnodeID); -extern status_t file_cache_set_enabled(dev_t mountID, ino_t vnodeID, - bool enabled); -extern status_t file_cache_set_size(dev_t mountID, ino_t vnodeID, off_t size); -extern status_t file_cache_sync(dev_t mountID, ino_t vnodeID); +status_t file_cache_create(dev_t mountID, ino_t vnodeID, off_t size); +status_t file_cache_delete(dev_t mountID, ino_t vnodeID); +status_t file_cache_set_enabled(dev_t mountID, ino_t vnodeID, bool enabled); +status_t file_cache_set_size(dev_t mountID, ino_t vnodeID, off_t size); +status_t file_cache_sync(dev_t mountID, ino_t vnodeID); -extern status_t file_cache_read(dev_t mountID, ino_t vnodeID, void *cookie, +status_t file_cache_read(dev_t mountID, ino_t vnodeID, void *cookie, off_t offset, void *bufferBase, size_t *_size); -extern status_t file_cache_write(dev_t mountID, ino_t vnodeID, void *cookie, +status_t file_cache_write(dev_t mountID, ino_t vnodeID, void *cookie, off_t offset, const void *buffer, size_t *_size); +status_t do_iterative_fd_io(int fd, int32 requestID, void* cookie, + const file_io_vec* vecs, uint32 vecCount); + void kernel_debugger(const char *message); void vpanic(const char *format, va_list args); void panic(const char *format, ...) __attribute__ ((format (__printf__, 1, 2)));