diff --git a/headers/private/userlandfs/private/Requests.h b/headers/private/userlandfs/private/Requests.h index 5126133730..265cd5940b 100644 --- a/headers/private/userlandfs/private/Requests.h +++ b/headers/private/userlandfs/private/Requests.h @@ -59,6 +59,10 @@ enum { DO_IO_REPLY, CANCEL_IO_REQUEST, CANCEL_IO_REPLY, + ITERATIVE_IO_GET_VECS_REQUEST, + ITERATIVE_IO_GET_VECS_REPLY, + ITERATIVE_IO_FINISHED_REQUEST, + ITERATIVE_IO_FINISHED_REPLY, // nodes IOCTL_REQUEST, @@ -547,6 +551,8 @@ class DoIORequest : public FileRequest { public: DoIORequest() : FileRequest(DO_IO_REQUEST) {} + off_t offset; + size_t length; int32 request; bool isWrite; }; @@ -571,6 +577,49 @@ public: CancelIOReply() : ReplyRequest(CANCEL_IO_REPLY) {} }; +// IterativeIOGetVecsRequest +class IterativeIOGetVecsRequest : public VolumeRequest { +public: + IterativeIOGetVecsRequest() + : VolumeRequest(ITERATIVE_IO_GET_VECS_REQUEST) {} + + void* cookie; + off_t offset; + int32 request; + size_t size; + uint32 vecCount; +}; + +// IterativeIOGetVecsReply +class IterativeIOGetVecsReply : public ReplyRequest { +public: + IterativeIOGetVecsReply() : ReplyRequest(ITERATIVE_IO_GET_VECS_REPLY) {} + + enum { MAX_VECS = 8 }; + + file_io_vec vecs[MAX_VECS]; + uint32 vecCount; +}; + +// IterativeIOFinishedRequest +class IterativeIOFinishedRequest : public VolumeRequest { +public: + IterativeIOFinishedRequest() + : VolumeRequest(ITERATIVE_IO_FINISHED_REQUEST) {} + + void* cookie; + int32 request; + status_t status; + bool partialTransfer; + size_t bytesTransferred; +}; + +// IterativeIOFinishedReply +class IterativeIOFinishedReply : public ReplyRequest { +public: + IterativeIOFinishedReply() : ReplyRequest(ITERATIVE_IO_FINISHED_REPLY) {} +}; + // #pragma mark - nodes @@ -1751,13 +1800,14 @@ public: class DoIterativeFDIORequest : public Request { public: DoIterativeFDIORequest() : Request(DO_ITERATIVE_FD_IO_REQUEST) {} - status_t GetAddressInfos(AddressInfo* infos, int32* count); + + enum { MAX_VECS = 8 }; dev_t nsid; int fd; int32 request; void* cookie; - Address vecs; + file_io_vec vecs[MAX_VECS]; uint32 vecCount; }; @@ -1853,6 +1903,14 @@ do_for_request(Request* request, Task& task) return task((CancelIORequest*)request); case CANCEL_IO_REPLY: return task((CancelIOReply*)request); + case ITERATIVE_IO_GET_VECS_REQUEST: + return task((IterativeIOGetVecsRequest*)request); + case ITERATIVE_IO_GET_VECS_REPLY: + return task((IterativeIOGetVecsReply*)request); + case ITERATIVE_IO_FINISHED_REQUEST: + return task((IterativeIOFinishedRequest*)request); + case ITERATIVE_IO_FINISHED_REPLY: + return task((IterativeIOFinishedReply*)request); // nodes case IOCTL_REQUEST: return task((IOCtlRequest*)request); @@ -2217,6 +2275,10 @@ using UserlandFSUtil::DoIORequest; using UserlandFSUtil::DoIOReply; using UserlandFSUtil::CancelIORequest; using UserlandFSUtil::CancelIOReply; +using UserlandFSUtil::IterativeIOGetVecsRequest; +using UserlandFSUtil::IterativeIOGetVecsReply; +using UserlandFSUtil::IterativeIOFinishedRequest; +using UserlandFSUtil::IterativeIOFinishedReply; // nodes using UserlandFSUtil::IOCtlRequest; using UserlandFSUtil::IOCtlReply; diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Jamfile b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Jamfile index fddf3f5d10..4adb28565f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Jamfile +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Jamfile @@ -1,13 +1,15 @@ SubDir HAIKU_TOP src add-ons kernel file_systems userlandfs kernel_add_on ; local userlandFSTop = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems - userlandfs ] ; + userlandfs ] ; local userlandFSIncludes = [ PrivateHeaders userlandfs ] ; UsePrivateHeaders shared ; UsePrivateKernelHeaders ; SubDirHdrs [ FDirName $(userlandFSIncludes) private ] ; SubDirHdrs [ FDirName $(userlandFSIncludes) shared ] ; +SubDirHdrs [ FDirName $(HAIKU_TOP) src system kernel device_manager ] ; + # for IORequest.h SEARCH_SOURCE += [ FDirName $(userlandFSTop) private ] ; SEARCH_SOURCE += [ FDirName $(userlandFSTop) shared ] ; diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp index 730b0d4558..a64c884fda 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp @@ -716,16 +716,13 @@ KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request) status_t result = _GetVolume(request->nsid, &volume); VolumePutter _(volume); - const file_io_vec* vecs = (const file_io_vec*)request->vecs.GetData(); - size_t vecsSize = request->vecs.GetSize(); uint32 vecCount = request->vecCount; - - if (result == B_OK && vecsSize / sizeof(file_io_vec) < vecCount) + if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS) result = B_BAD_VALUE; if (result == B_OK) { result = volume->DoIterativeFDIO(request->fd, request->request, - request->cookie, vecs, vecCount); + request->cookie, request->vecs, vecCount); } // prepare the reply diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp index 44113b6beb..5ffbe7fecf 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/Volume.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include @@ -17,6 +19,8 @@ #include // kernel private +#include "IORequest.h" // kernel internal + #include "Compatibility.h" #include "Debug.h" #include "FileSystem.h" @@ -157,20 +161,29 @@ struct Volume::IterativeFDIOCookie : public Referenceable { int fd; int32 requestID; void* clientCookie; + off_t offset; const file_io_vec* vecs; uint32 vecCount; IterativeFDIOCookie(Volume* volume, int fd, int32 requestID, - void* clientCookie, const file_io_vec* vecs, uint32 vecCount) + void* clientCookie, off_t offset, const file_io_vec* vecs, + uint32 vecCount) : volume(volume), fd(fd), requestID(requestID), clientCookie(clientCookie), + offset(offset), vecs(vecs), vecCount(vecCount) { } + + ~IterativeFDIOCookie() + { + if (fd >= 0) + close(fd); + } }; @@ -621,7 +634,7 @@ Volume::DoIterativeFDIO(int fd, int32 requestID, void* clientCookie, // create a cookie IterativeFDIOCookie* cookie = new(std::nothrow) IterativeFDIOCookie( - this, fd, requestID, clientCookie, vecs, vecCount); + this, fd, requestID, clientCookie, request->Offset(), vecs, vecCount); if (cookie == NULL) { close(fd); RETURN_ERROR(B_NO_MEMORY); @@ -630,6 +643,8 @@ Volume::DoIterativeFDIO(int fd, int32 requestID, void* clientCookie, // we need another reference, so we can still access the cookie below cookie->AddReference(); +// TODO: Up to this point we're responsible for calling the finished hook on +// error! // call the kernel function error = do_iterative_fd_io(fd, request, &_IterativeFDIOGetVecs, &_IterativeFDIOFinished, cookie); @@ -1067,6 +1082,8 @@ Volume::DoIO(void* _node, void* cookie, io_request* ioRequest) request->node = vnode->clientNode; request->fileCookie = cookie; request->request = requestID; + request->offset = ioRequest->Offset(); + request->length = ioRequest->Length(); // send the request KernelRequestHandler handler(this, DO_IO_REPLY); @@ -4406,18 +4423,135 @@ Volume::_FindIORequest(io_request* request, int32* requestID) /*static*/ status_t -Volume::_IterativeFDIOGetVecs(void* cookie, io_request* request, off_t offset, - size_t size, struct file_io_vec* vecs, size_t* _count) +Volume::_IterativeFDIOGetVecs(void* _cookie, io_request* ioRequest, + off_t offset, size_t size, struct file_io_vec* vecs, size_t* _count) { - // TODO: Implement! - return B_UNSUPPORTED; + IterativeFDIOCookie* cookie = (IterativeFDIOCookie*)_cookie; + Volume* volume = cookie->volume; + + MutexLocker locker(volume->fLock); + + // If there are vecs cached in the cookie and the offset matches, return + // those. + if (cookie->vecs != NULL) { + size_t vecCount = 0; + if (offset == cookie->offset) { + // good, copy the vecs + while (size > 0 && vecCount < cookie->vecCount + && vecCount < *_count) { + off_t maxSize = std::min((off_t)size, + cookie->vecs[vecCount].length); + vecs[vecCount].offset = cookie->vecs[vecCount].offset; + vecs[vecCount].length = maxSize; + + size -= maxSize; + vecCount++; + } + } + + cookie->vecs = NULL; + cookie->vecCount = 0; + + // got some vecs? -- then we're done + if (vecCount > 0) { + *_count = vecCount; + return B_OK; + } + } + + // we have to ask the client FS + int32 requestID = cookie->requestID; + void* clientCookie = cookie->clientCookie; + locker.Unlock(); + + // get a free port + RequestPort* port = volume->fFileSystem->GetPortPool()->AcquirePort(); + if (!port) + return B_ERROR; + PortReleaser _(volume->fFileSystem->GetPortPool(), port); + + // prepare the request + RequestAllocator allocator(port->GetPort()); + IterativeIOGetVecsRequest* request; + status_t error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->volume = volume->fUserlandVolume; + request->cookie = clientCookie; + request->offset = offset; + request->request = requestID; + request->size = size; + size_t maxVecs = std::min(*_count, + (size_t)IterativeIOGetVecsReply::MAX_VECS); + request->vecCount = maxVecs; + + // send the request + KernelRequestHandler handler(volume, ITERATIVE_IO_GET_VECS_REPLY); + IterativeIOGetVecsReply* reply; + error = volume->_SendRequest(port, &allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + if (reply->error != B_OK) + return reply->error; + uint32 vecCount = reply->vecCount; + if (vecCount < 0 || vecCount > maxVecs) + return B_BAD_DATA; + + memcpy(vecs, reply->vecs, vecCount * sizeof(file_io_vec)); + *_count = vecCount; + + return B_OK; } /*static*/ status_t -Volume::_IterativeFDIOFinished(void* cookie, io_request* request, +Volume::_IterativeFDIOFinished(void* _cookie, io_request* ioRequest, status_t status, bool partialTransfer, size_t bytesTransferred) { - // TODO: Implement! - return B_UNSUPPORTED; + IterativeFDIOCookie* cookie = (IterativeFDIOCookie*)_cookie; + Volume* volume = cookie->volume; + + // At any rate, we're done with the cookie after this call -- it will not + // be used anymore. + Reference _(cookie, true); + + // We also want to dispose of the request. + IORequestRemover _2(volume, cookie->requestID); + + // get a free port + RequestPort* port = volume->fFileSystem->GetPortPool()->AcquirePort(); + if (!port) + return B_ERROR; + PortReleaser _3(volume->fFileSystem->GetPortPool(), port); + + // prepare the request + RequestAllocator allocator(port->GetPort()); + IterativeIOFinishedRequest* request; + status_t error = AllocateRequest(allocator, &request); + if (error != B_OK) + return error; + + request->volume = volume->fUserlandVolume; + request->cookie = cookie->clientCookie; + request->request = cookie->requestID; + request->status = status; + request->partialTransfer = partialTransfer; + request->bytesTransferred = bytesTransferred; + + // send the request + KernelRequestHandler handler(volume, ITERATIVE_IO_FINISHED_REPLY); + IterativeIOFinishedReply* reply; + error = volume->_SendRequest(port, &allocator, &handler, (Request**)&reply); + if (error != B_OK) + return error; + RequestReleaser requestReleaser(port, reply); + + // process the reply + if (reply->error != B_OK) + return reply->error; + return B_OK; } 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 30fe0866c5..922a7319d5 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp @@ -313,14 +313,6 @@ 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 - @@ -542,9 +534,13 @@ UserlandFSUtil::is_kernel_request(uint32 type) // asynchronous I/O case DO_IO_REQUEST: case CANCEL_IO_REQUEST: + case ITERATIVE_IO_GET_VECS_REQUEST: + case ITERATIVE_IO_FINISHED_REQUEST: return true; case DO_IO_REPLY: case CANCEL_IO_REPLY: + case ITERATIVE_IO_GET_VECS_REPLY: + case ITERATIVE_IO_FINISHED_REPLY: return false; // nodes case IOCTL_REQUEST: @@ -779,9 +775,13 @@ UserlandFSUtil::is_userland_request(uint32 type) // asynchronous I/O case DO_IO_REQUEST: case CANCEL_IO_REQUEST: + case ITERATIVE_IO_GET_VECS_REQUEST: + case ITERATIVE_IO_FINISHED_REQUEST: return false; case DO_IO_REPLY: case CANCEL_IO_REPLY: + case ITERATIVE_IO_GET_VECS_REPLY: + case ITERATIVE_IO_FINISHED_REPLY: return true; // nodes case IOCTL_REQUEST: 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 071a57fc14..ff7024f2ec 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/IORequestInfo.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/IORequestInfo.h @@ -11,11 +11,15 @@ namespace UserlandFS { struct IORequestInfo { + off_t offset; + size_t length; int32 id; bool isWrite; - IORequestInfo(int32 id, bool isWrite) + IORequestInfo(int32 id, bool isWrite, off_t offset, size_t length) : + offset(offset), + length(length), id(id), isWrite(isWrite) { @@ -23,6 +27,8 @@ struct IORequestInfo { IORequestInfo(const IORequestInfo& other) : + offset(other.offset), + length(other.length), id(other.id), isWrite(other.isWrite) { 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 23aa900e0a..f9f95d39a4 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp @@ -2,6 +2,8 @@ #include "UserlandRequestHandler.h" +#include + #include "AutoDeleter.h" #include "Compatibility.h" #include "Debug.h" @@ -13,6 +15,7 @@ #include "SingleReplyRequestHandler.h" #include "Volume.h" + // constructor UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem) : RequestHandler(), @@ -75,6 +78,10 @@ UserlandRequestHandler::HandleRequest(Request* request) return _HandleRequest((DoIORequest*)request); case CANCEL_IO_REQUEST: return _HandleRequest((CancelIORequest*)request); + case ITERATIVE_IO_GET_VECS_REQUEST: + return _HandleRequest((IterativeIOGetVecsRequest*)request); + case ITERATIVE_IO_FINISHED_REQUEST: + return _HandleRequest((IterativeIOFinishedRequest*)request); // nodes case IOCTL_REQUEST: @@ -552,7 +559,8 @@ UserlandRequestHandler::_HandleRequest(DoIORequest* request) if (result == B_OK) { RequestThreadContext context(volume); - IORequestInfo requestInfo(request->request, request->isWrite); + IORequestInfo requestInfo(request->request, request->isWrite, + request->offset, request->length); result = volume->DoIO(request->node, request->fileCookie, requestInfo); } @@ -599,6 +607,78 @@ UserlandRequestHandler::_HandleRequest(CancelIORequest* request) } +// _HandleRequest +status_t +UserlandRequestHandler::_HandleRequest(IterativeIOGetVecsRequest* request) +{ + // check and execute the request + status_t result = B_OK; + Volume* volume = (Volume*)request->volume; + if (!volume) + result = B_BAD_VALUE; + + file_io_vec vecs[IterativeIOGetVecsReply::MAX_VECS]; + size_t vecCount = IterativeIOGetVecsReply::MAX_VECS; + if (result == B_OK) { + RequestThreadContext context(volume); + result = volume->IterativeIOGetVecs(request->cookie, request->request, + request->offset, request->size, vecs, &vecCount); + if (result == B_OK) { + vecCount = std::min(vecCount, + (uint32)IterativeIOGetVecsReply::MAX_VECS); + } + } + + // prepare the reply + RequestAllocator allocator(fPort->GetPort()); + IterativeIOGetVecsReply* reply; + status_t error = AllocateRequest(allocator, &reply); + if (error != B_OK) + RETURN_ERROR(error); + + reply->error = result; + if (result == B_OK) { + memcpy(reply->vecs, vecs, vecCount * sizeof(file_io_vec)); + reply->vecCount = vecCount; + } else + reply->vecCount = 0; + + // send the reply + return _SendReply(allocator, false); +} + + +// _HandleRequest +status_t +UserlandRequestHandler::_HandleRequest(IterativeIOFinishedRequest* request) +{ + // check and execute the request + status_t result = B_OK; + Volume* volume = (Volume*)request->volume; + if (!volume) + result = B_BAD_VALUE; + + if (result == B_OK) { + RequestThreadContext context(volume); + result = volume->IterativeIOFinished(request->cookie, request->request, + request->status, request->partialTransfer, + request->bytesTransferred); + } + + // prepare the reply + RequestAllocator allocator(fPort->GetPort()); + IterativeIOFinishedReply* reply; + status_t error = AllocateRequest(allocator, &reply); + if (error != B_OK) + RETURN_ERROR(error); + + reply->error = result; + + // send the reply + return _SendReply(allocator, false); +} + + // #pragma mark - nodes diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h index 4d320531f2..d6847d0c4f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h @@ -22,6 +22,8 @@ class FSRemoveVNodeRequest; // asynchronous I/O class DoIORequest; class CancelIORequest; +class IterativeIOGetVecsRequest; +class IterativeIOFinishedRequest; // nodes class IOCtlRequest; class SetFlagsRequest; @@ -121,6 +123,10 @@ private: // asynchronous I/O status_t _HandleRequest(DoIORequest* request); status_t _HandleRequest(CancelIORequest* request); + status_t _HandleRequest( + IterativeIOGetVecsRequest* request); + status_t _HandleRequest( + IterativeIOFinishedRequest* request); // nodes status_t _HandleRequest(IOCtlRequest* request); 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 93b8a1ca64..d9e46de1b8 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.cpp @@ -206,6 +206,22 @@ Volume::CancelIO(void* node, void* cookie, int32 ioRequestID) } +status_t +Volume::IterativeIOGetVecs(void* cookie, int32 requestID, off_t offset, + size_t size, struct file_io_vec* vecs, size_t* _count) +{ + return B_BAD_VALUE; +} + + +status_t +Volume::IterativeIOFinished(void* cookie, int32 requestID, status_t status, + bool partialTransfer, size_t bytesTransferred) +{ + return B_BAD_VALUE; +} + + // #pragma mark - nodes 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 f645cb639f..3d45ca5383 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Volume.h @@ -58,6 +58,13 @@ public: const IORequestInfo& requestInfo); virtual status_t CancelIO(void* node, void* cookie, int32 ioRequestID); + virtual status_t IterativeIOGetVecs(void* cookie, + int32 requestID, off_t offset, size_t size, + struct file_io_vec* vecs, size_t* _count); + virtual status_t IterativeIOFinished(void* cookie, + int32 requestID, status_t status, + bool partialTransfer, + size_t bytesTransferred); // nodes virtual status_t IOCtl(void* node, void* cookie, 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 e7ee8b5096..533f20db47 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 @@ -406,6 +406,58 @@ HaikuKernelVolume::CancelIO(void* _node, void* cookie, int32 ioRequestID) } +// IterativeIOGetVecs +status_t +HaikuKernelVolume::IterativeIOGetVecs(void* _cookie, int32 requestID, + off_t offset, size_t size, struct file_io_vec* vecs, size_t* _count) +{ + HaikuKernelIterativeFDIOCookie* cookie + = (HaikuKernelIterativeFDIOCookie*)_cookie; + + // get the request + HaikuKernelIORequest* request = _FileSystem()->GetIORequest(requestID); + if (request == NULL) + RETURN_ERROR(B_BAD_VALUE); + + // call the callback + status_t error = cookie->getVecs(cookie->cookie, (io_request*)request, + offset, size, vecs, _count); + + // put the reference we got above + _FileSystem()->PutIORequest(request, 1); + + return error; +} + + +// IterativeIOFinished +status_t +HaikuKernelVolume::IterativeIOFinished(void* _cookie, int32 requestID, + status_t status, bool partialTransfer, size_t bytesTransferred) +{ + HaikuKernelIterativeFDIOCookie* cookie + = (HaikuKernelIterativeFDIOCookie*)_cookie; + + // we're definitely done with the cookie, now + ObjectDeleter _(cookie); + + // get the request + HaikuKernelIORequest* request = _FileSystem()->GetIORequest(requestID); + if (request == NULL) + RETURN_ERROR(B_BAD_VALUE); + + // call the callback + status_t error = cookie->finished(cookie->cookie, (io_request*)request, + status, partialTransfer, bytesTransferred); + + // We're done with the request, too, so put the reference we got above and + // the one added by DoIO(). + _FileSystem()->PutIORequest(request, 2); + + return error; +} + + // #pragma mark - nodes 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 090ff550da..d5216ed8f4 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 @@ -65,6 +65,13 @@ public: const IORequestInfo& requestInfo); virtual status_t CancelIO(void* node, void* cookie, int32 ioRequestID); + virtual status_t IterativeIOGetVecs(void* cookie, + int32 requestID, off_t offset, size_t size, + struct file_io_vec* vecs, size_t* _count); + virtual status_t IterativeIOFinished(void* cookie, + int32 requestID, status_t status, + bool partialTransfer, + size_t bytesTransferred); // nodes virtual status_t IOCtl(void* node, void* cookie, 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 2dfe27254e..340210017c 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 @@ -274,18 +274,17 @@ status_t do_iterative_fd_io(int fd, io_request *_request, iterative_io_get_vecs getVecs, iterative_io_finished finished, void *_cookie) { -#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; + // get the first vecs already -- this saves a guaranteed trip back from + // kernel to userland + file_io_vec fileVecs[DoIterativeFDIORequest::MAX_VECS]; + uint32 fileVecCount = DoIterativeFDIORequest::MAX_VECS; + status_t error = getVecs(_cookie, _request, request->offset, + request->length, fileVecs, &fileVecCount); + if (error != B_OK) + return error; + // create a cookie HaikuKernelIterativeFDIOCookie* cookie = new(std::nothrow) HaikuKernelIterativeFDIOCookie(fd, request, getVecs, @@ -296,8 +295,10 @@ do_iterative_fd_io(int fd, io_request *_request, iterative_io_get_vecs getVecs, } // send the request - status_t error = UserlandFS::KernelEmu::do_iterative_fd_io( - request->volume->GetID(), fd, request->id, cookie, NULL, 0); +// TODO: Up to this point we should call the finished hook on error! + error = UserlandFS::KernelEmu::do_iterative_fd_io( + request->volume->GetID(), fd, request->id, cookie, fileVecs, + fileVecCount); if (error != B_OK) { delete cookie; return error; 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 4d2213319d..9a0957687a 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 @@ -6,6 +6,8 @@ #include #include +#include + #include "FileSystem.h" #include "RequestPort.h" #include "Requests.h" @@ -862,14 +864,12 @@ UserlandFS::KernelEmu::do_iterative_fd_io(dev_t volumeID, int fd, 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; + vecCount = std::min(vecCount, (uint32)DoIterativeFDIORequest::MAX_VECS); + memcpy(request->vecs, vecs, sizeof(file_io_vec) * vecCount); } + request->vecCount = vecCount; // send the request UserlandRequestHandler handler(fileSystem, DO_ITERATIVE_FD_IO_REPLY); @@ -877,7 +877,7 @@ UserlandFS::KernelEmu::do_iterative_fd_io(dev_t volumeID, int fd, 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! +// TODO: Up to this point we should call the finished hook on error! RequestReleaser requestReleaser(port, reply); // process the reply