* Implemented forwarding the do_iterative_fd_io() callbacks to userland.
* Pass the request offset and length with the DoIORequest. This allows us to already get the first vecs for do_iterative_fd_io() in userland, saving a trip back and forth. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29546 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -59,6 +59,10 @@ enum {
|
|||||||
DO_IO_REPLY,
|
DO_IO_REPLY,
|
||||||
CANCEL_IO_REQUEST,
|
CANCEL_IO_REQUEST,
|
||||||
CANCEL_IO_REPLY,
|
CANCEL_IO_REPLY,
|
||||||
|
ITERATIVE_IO_GET_VECS_REQUEST,
|
||||||
|
ITERATIVE_IO_GET_VECS_REPLY,
|
||||||
|
ITERATIVE_IO_FINISHED_REQUEST,
|
||||||
|
ITERATIVE_IO_FINISHED_REPLY,
|
||||||
|
|
||||||
// nodes
|
// nodes
|
||||||
IOCTL_REQUEST,
|
IOCTL_REQUEST,
|
||||||
@@ -547,6 +551,8 @@ class DoIORequest : public FileRequest {
|
|||||||
public:
|
public:
|
||||||
DoIORequest() : FileRequest(DO_IO_REQUEST) {}
|
DoIORequest() : FileRequest(DO_IO_REQUEST) {}
|
||||||
|
|
||||||
|
off_t offset;
|
||||||
|
size_t length;
|
||||||
int32 request;
|
int32 request;
|
||||||
bool isWrite;
|
bool isWrite;
|
||||||
};
|
};
|
||||||
@@ -571,6 +577,49 @@ public:
|
|||||||
CancelIOReply() : ReplyRequest(CANCEL_IO_REPLY) {}
|
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
|
// #pragma mark - nodes
|
||||||
|
|
||||||
@@ -1751,13 +1800,14 @@ public:
|
|||||||
class DoIterativeFDIORequest : public Request {
|
class DoIterativeFDIORequest : public Request {
|
||||||
public:
|
public:
|
||||||
DoIterativeFDIORequest() : Request(DO_ITERATIVE_FD_IO_REQUEST) {}
|
DoIterativeFDIORequest() : Request(DO_ITERATIVE_FD_IO_REQUEST) {}
|
||||||
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
|
||||||
|
enum { MAX_VECS = 8 };
|
||||||
|
|
||||||
dev_t nsid;
|
dev_t nsid;
|
||||||
int fd;
|
int fd;
|
||||||
int32 request;
|
int32 request;
|
||||||
void* cookie;
|
void* cookie;
|
||||||
Address vecs;
|
file_io_vec vecs[MAX_VECS];
|
||||||
uint32 vecCount;
|
uint32 vecCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1853,6 +1903,14 @@ do_for_request(Request* request, Task& task)
|
|||||||
return task((CancelIORequest*)request);
|
return task((CancelIORequest*)request);
|
||||||
case CANCEL_IO_REPLY:
|
case CANCEL_IO_REPLY:
|
||||||
return task((CancelIOReply*)request);
|
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
|
// nodes
|
||||||
case IOCTL_REQUEST:
|
case IOCTL_REQUEST:
|
||||||
return task((IOCtlRequest*)request);
|
return task((IOCtlRequest*)request);
|
||||||
@@ -2217,6 +2275,10 @@ using UserlandFSUtil::DoIORequest;
|
|||||||
using UserlandFSUtil::DoIOReply;
|
using UserlandFSUtil::DoIOReply;
|
||||||
using UserlandFSUtil::CancelIORequest;
|
using UserlandFSUtil::CancelIORequest;
|
||||||
using UserlandFSUtil::CancelIOReply;
|
using UserlandFSUtil::CancelIOReply;
|
||||||
|
using UserlandFSUtil::IterativeIOGetVecsRequest;
|
||||||
|
using UserlandFSUtil::IterativeIOGetVecsReply;
|
||||||
|
using UserlandFSUtil::IterativeIOFinishedRequest;
|
||||||
|
using UserlandFSUtil::IterativeIOFinishedReply;
|
||||||
// nodes
|
// nodes
|
||||||
using UserlandFSUtil::IOCtlRequest;
|
using UserlandFSUtil::IOCtlRequest;
|
||||||
using UserlandFSUtil::IOCtlReply;
|
using UserlandFSUtil::IOCtlReply;
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel file_systems userlandfs kernel_add_on ;
|
SubDir HAIKU_TOP src add-ons kernel file_systems userlandfs kernel_add_on ;
|
||||||
|
|
||||||
local userlandFSTop = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems
|
local userlandFSTop = [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems
|
||||||
userlandfs ] ;
|
userlandfs ] ;
|
||||||
local userlandFSIncludes = [ PrivateHeaders userlandfs ] ;
|
local userlandFSIncludes = [ PrivateHeaders userlandfs ] ;
|
||||||
|
|
||||||
UsePrivateHeaders shared ;
|
UsePrivateHeaders shared ;
|
||||||
UsePrivateKernelHeaders ;
|
UsePrivateKernelHeaders ;
|
||||||
SubDirHdrs [ FDirName $(userlandFSIncludes) private ] ;
|
SubDirHdrs [ FDirName $(userlandFSIncludes) private ] ;
|
||||||
SubDirHdrs [ FDirName $(userlandFSIncludes) shared ] ;
|
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) private ] ;
|
||||||
SEARCH_SOURCE += [ FDirName $(userlandFSTop) shared ] ;
|
SEARCH_SOURCE += [ FDirName $(userlandFSTop) shared ] ;
|
||||||
|
|||||||
@@ -716,16 +716,13 @@ KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request)
|
|||||||
status_t result = _GetVolume(request->nsid, &volume);
|
status_t result = _GetVolume(request->nsid, &volume);
|
||||||
VolumePutter _(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;
|
uint32 vecCount = request->vecCount;
|
||||||
|
if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS)
|
||||||
if (result == B_OK && vecsSize / sizeof(file_io_vec) < vecCount)
|
|
||||||
result = B_BAD_VALUE;
|
result = B_BAD_VALUE;
|
||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
result = volume->DoIterativeFDIO(request->fd, request->request,
|
result = volume->DoIterativeFDIO(request->fd, request->request,
|
||||||
request->cookie, vecs, vecCount);
|
request->cookie, request->vecs, vecCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare the reply
|
// prepare the reply
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <fs_cache.h>
|
#include <fs_cache.h>
|
||||||
|
|
||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
@@ -17,6 +19,8 @@
|
|||||||
|
|
||||||
#include <fs/fd.h> // kernel private
|
#include <fs/fd.h> // kernel private
|
||||||
|
|
||||||
|
#include "IORequest.h" // kernel internal
|
||||||
|
|
||||||
#include "Compatibility.h"
|
#include "Compatibility.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
@@ -157,20 +161,29 @@ struct Volume::IterativeFDIOCookie : public Referenceable {
|
|||||||
int fd;
|
int fd;
|
||||||
int32 requestID;
|
int32 requestID;
|
||||||
void* clientCookie;
|
void* clientCookie;
|
||||||
|
off_t offset;
|
||||||
const file_io_vec* vecs;
|
const file_io_vec* vecs;
|
||||||
uint32 vecCount;
|
uint32 vecCount;
|
||||||
|
|
||||||
IterativeFDIOCookie(Volume* volume, int fd, int32 requestID,
|
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),
|
volume(volume),
|
||||||
fd(fd),
|
fd(fd),
|
||||||
requestID(requestID),
|
requestID(requestID),
|
||||||
clientCookie(clientCookie),
|
clientCookie(clientCookie),
|
||||||
|
offset(offset),
|
||||||
vecs(vecs),
|
vecs(vecs),
|
||||||
vecCount(vecCount)
|
vecCount(vecCount)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~IterativeFDIOCookie()
|
||||||
|
{
|
||||||
|
if (fd >= 0)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -621,7 +634,7 @@ Volume::DoIterativeFDIO(int fd, int32 requestID, void* clientCookie,
|
|||||||
|
|
||||||
// create a cookie
|
// create a cookie
|
||||||
IterativeFDIOCookie* cookie = new(std::nothrow) IterativeFDIOCookie(
|
IterativeFDIOCookie* cookie = new(std::nothrow) IterativeFDIOCookie(
|
||||||
this, fd, requestID, clientCookie, vecs, vecCount);
|
this, fd, requestID, clientCookie, request->Offset(), vecs, vecCount);
|
||||||
if (cookie == NULL) {
|
if (cookie == NULL) {
|
||||||
close(fd);
|
close(fd);
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
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
|
// we need another reference, so we can still access the cookie below
|
||||||
cookie->AddReference();
|
cookie->AddReference();
|
||||||
|
|
||||||
|
// TODO: Up to this point we're responsible for calling the finished hook on
|
||||||
|
// error!
|
||||||
// call the kernel function
|
// call the kernel function
|
||||||
error = do_iterative_fd_io(fd, request, &_IterativeFDIOGetVecs,
|
error = do_iterative_fd_io(fd, request, &_IterativeFDIOGetVecs,
|
||||||
&_IterativeFDIOFinished, cookie);
|
&_IterativeFDIOFinished, cookie);
|
||||||
@@ -1067,6 +1082,8 @@ Volume::DoIO(void* _node, void* cookie, io_request* ioRequest)
|
|||||||
request->node = vnode->clientNode;
|
request->node = vnode->clientNode;
|
||||||
request->fileCookie = cookie;
|
request->fileCookie = cookie;
|
||||||
request->request = requestID;
|
request->request = requestID;
|
||||||
|
request->offset = ioRequest->Offset();
|
||||||
|
request->length = ioRequest->Length();
|
||||||
|
|
||||||
// send the request
|
// send the request
|
||||||
KernelRequestHandler handler(this, DO_IO_REPLY);
|
KernelRequestHandler handler(this, DO_IO_REPLY);
|
||||||
@@ -4406,18 +4423,135 @@ Volume::_FindIORequest(io_request* request, int32* requestID)
|
|||||||
|
|
||||||
|
|
||||||
/*static*/ status_t
|
/*static*/ status_t
|
||||||
Volume::_IterativeFDIOGetVecs(void* cookie, io_request* request, off_t offset,
|
Volume::_IterativeFDIOGetVecs(void* _cookie, io_request* ioRequest,
|
||||||
size_t size, struct file_io_vec* vecs, size_t* _count)
|
off_t offset, size_t size, struct file_io_vec* vecs, size_t* _count)
|
||||||
{
|
{
|
||||||
// TODO: Implement!
|
IterativeFDIOCookie* cookie = (IterativeFDIOCookie*)_cookie;
|
||||||
return B_UNSUPPORTED;
|
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
|
/*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)
|
status_t status, bool partialTransfer, size_t bytesTransferred)
|
||||||
{
|
{
|
||||||
// TODO: Implement!
|
IterativeFDIOCookie* cookie = (IterativeFDIOCookie*)_cookie;
|
||||||
return B_UNSUPPORTED;
|
Volume* volume = cookie->volume;
|
||||||
|
|
||||||
|
// At any rate, we're done with the cookie after this call -- it will not
|
||||||
|
// be used anymore.
|
||||||
|
Reference<IterativeFDIOCookie> _(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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,14 +313,6 @@ FileCacheWriteRequest::GetAddressInfos(AddressInfo* infos, int32* count)
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DoIterativeFDIORequest
|
|
||||||
status_t
|
|
||||||
DoIterativeFDIORequest::GetAddressInfos(AddressInfo* infos, int32* count)
|
|
||||||
{
|
|
||||||
ADD_ADDRESS(vecs);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
@@ -542,9 +534,13 @@ UserlandFSUtil::is_kernel_request(uint32 type)
|
|||||||
// asynchronous I/O
|
// asynchronous I/O
|
||||||
case DO_IO_REQUEST:
|
case DO_IO_REQUEST:
|
||||||
case CANCEL_IO_REQUEST:
|
case CANCEL_IO_REQUEST:
|
||||||
|
case ITERATIVE_IO_GET_VECS_REQUEST:
|
||||||
|
case ITERATIVE_IO_FINISHED_REQUEST:
|
||||||
return true;
|
return true;
|
||||||
case DO_IO_REPLY:
|
case DO_IO_REPLY:
|
||||||
case CANCEL_IO_REPLY:
|
case CANCEL_IO_REPLY:
|
||||||
|
case ITERATIVE_IO_GET_VECS_REPLY:
|
||||||
|
case ITERATIVE_IO_FINISHED_REPLY:
|
||||||
return false;
|
return false;
|
||||||
// nodes
|
// nodes
|
||||||
case IOCTL_REQUEST:
|
case IOCTL_REQUEST:
|
||||||
@@ -779,9 +775,13 @@ UserlandFSUtil::is_userland_request(uint32 type)
|
|||||||
// asynchronous I/O
|
// asynchronous I/O
|
||||||
case DO_IO_REQUEST:
|
case DO_IO_REQUEST:
|
||||||
case CANCEL_IO_REQUEST:
|
case CANCEL_IO_REQUEST:
|
||||||
|
case ITERATIVE_IO_GET_VECS_REQUEST:
|
||||||
|
case ITERATIVE_IO_FINISHED_REQUEST:
|
||||||
return false;
|
return false;
|
||||||
case DO_IO_REPLY:
|
case DO_IO_REPLY:
|
||||||
case CANCEL_IO_REPLY:
|
case CANCEL_IO_REPLY:
|
||||||
|
case ITERATIVE_IO_GET_VECS_REPLY:
|
||||||
|
case ITERATIVE_IO_FINISHED_REPLY:
|
||||||
return true;
|
return true;
|
||||||
// nodes
|
// nodes
|
||||||
case IOCTL_REQUEST:
|
case IOCTL_REQUEST:
|
||||||
|
|||||||
@@ -11,11 +11,15 @@
|
|||||||
namespace UserlandFS {
|
namespace UserlandFS {
|
||||||
|
|
||||||
struct IORequestInfo {
|
struct IORequestInfo {
|
||||||
|
off_t offset;
|
||||||
|
size_t length;
|
||||||
int32 id;
|
int32 id;
|
||||||
bool isWrite;
|
bool isWrite;
|
||||||
|
|
||||||
IORequestInfo(int32 id, bool isWrite)
|
IORequestInfo(int32 id, bool isWrite, off_t offset, size_t length)
|
||||||
:
|
:
|
||||||
|
offset(offset),
|
||||||
|
length(length),
|
||||||
id(id),
|
id(id),
|
||||||
isWrite(isWrite)
|
isWrite(isWrite)
|
||||||
{
|
{
|
||||||
@@ -23,6 +27,8 @@ struct IORequestInfo {
|
|||||||
|
|
||||||
IORequestInfo(const IORequestInfo& other)
|
IORequestInfo(const IORequestInfo& other)
|
||||||
:
|
:
|
||||||
|
offset(other.offset),
|
||||||
|
length(other.length),
|
||||||
id(other.id),
|
id(other.id),
|
||||||
isWrite(other.isWrite)
|
isWrite(other.isWrite)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "UserlandRequestHandler.h"
|
#include "UserlandRequestHandler.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "AutoDeleter.h"
|
#include "AutoDeleter.h"
|
||||||
#include "Compatibility.h"
|
#include "Compatibility.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
@@ -13,6 +15,7 @@
|
|||||||
#include "SingleReplyRequestHandler.h"
|
#include "SingleReplyRequestHandler.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem)
|
UserlandRequestHandler::UserlandRequestHandler(FileSystem* fileSystem)
|
||||||
: RequestHandler(),
|
: RequestHandler(),
|
||||||
@@ -75,6 +78,10 @@ UserlandRequestHandler::HandleRequest(Request* request)
|
|||||||
return _HandleRequest((DoIORequest*)request);
|
return _HandleRequest((DoIORequest*)request);
|
||||||
case CANCEL_IO_REQUEST:
|
case CANCEL_IO_REQUEST:
|
||||||
return _HandleRequest((CancelIORequest*)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
|
// nodes
|
||||||
case IOCTL_REQUEST:
|
case IOCTL_REQUEST:
|
||||||
@@ -552,7 +559,8 @@ UserlandRequestHandler::_HandleRequest(DoIORequest* request)
|
|||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
RequestThreadContext context(volume);
|
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);
|
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
|
// #pragma mark - nodes
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ class FSRemoveVNodeRequest;
|
|||||||
// asynchronous I/O
|
// asynchronous I/O
|
||||||
class DoIORequest;
|
class DoIORequest;
|
||||||
class CancelIORequest;
|
class CancelIORequest;
|
||||||
|
class IterativeIOGetVecsRequest;
|
||||||
|
class IterativeIOFinishedRequest;
|
||||||
// nodes
|
// nodes
|
||||||
class IOCtlRequest;
|
class IOCtlRequest;
|
||||||
class SetFlagsRequest;
|
class SetFlagsRequest;
|
||||||
@@ -121,6 +123,10 @@ private:
|
|||||||
// asynchronous I/O
|
// asynchronous I/O
|
||||||
status_t _HandleRequest(DoIORequest* request);
|
status_t _HandleRequest(DoIORequest* request);
|
||||||
status_t _HandleRequest(CancelIORequest* request);
|
status_t _HandleRequest(CancelIORequest* request);
|
||||||
|
status_t _HandleRequest(
|
||||||
|
IterativeIOGetVecsRequest* request);
|
||||||
|
status_t _HandleRequest(
|
||||||
|
IterativeIOFinishedRequest* request);
|
||||||
|
|
||||||
// nodes
|
// nodes
|
||||||
status_t _HandleRequest(IOCtlRequest* request);
|
status_t _HandleRequest(IOCtlRequest* request);
|
||||||
|
|||||||
@@ -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
|
// #pragma mark - nodes
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,13 @@ public:
|
|||||||
const IORequestInfo& requestInfo);
|
const IORequestInfo& requestInfo);
|
||||||
virtual status_t CancelIO(void* node, void* cookie,
|
virtual status_t CancelIO(void* node, void* cookie,
|
||||||
int32 ioRequestID);
|
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
|
// nodes
|
||||||
virtual status_t IOCtl(void* node, void* cookie,
|
virtual status_t IOCtl(void* node, void* cookie,
|
||||||
|
|||||||
@@ -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<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->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
|
// #pragma mark - nodes
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,13 @@ public:
|
|||||||
const IORequestInfo& requestInfo);
|
const IORequestInfo& requestInfo);
|
||||||
virtual status_t CancelIO(void* node, void* cookie,
|
virtual status_t CancelIO(void* node, void* cookie,
|
||||||
int32 ioRequestID);
|
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
|
// nodes
|
||||||
virtual status_t IOCtl(void* node, void* cookie,
|
virtual status_t IOCtl(void* node, void* cookie,
|
||||||
|
|||||||
@@ -274,18 +274,17 @@ 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)
|
||||||
{
|
{
|
||||||
#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;
|
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
|
// create a cookie
|
||||||
HaikuKernelIterativeFDIOCookie* cookie
|
HaikuKernelIterativeFDIOCookie* cookie
|
||||||
= new(std::nothrow) HaikuKernelIterativeFDIOCookie(fd, request, getVecs,
|
= 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
|
// send the request
|
||||||
status_t error = UserlandFS::KernelEmu::do_iterative_fd_io(
|
// TODO: Up to this point we should call the finished hook on error!
|
||||||
request->volume->GetID(), fd, request->id, cookie, NULL, 0);
|
error = UserlandFS::KernelEmu::do_iterative_fd_io(
|
||||||
|
request->volume->GetID(), fd, request->id, cookie, fileVecs,
|
||||||
|
fileVecCount);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
delete cookie;
|
delete cookie;
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
#include "RequestPort.h"
|
#include "RequestPort.h"
|
||||||
#include "Requests.h"
|
#include "Requests.h"
|
||||||
@@ -862,14 +864,12 @@ UserlandFS::KernelEmu::do_iterative_fd_io(dev_t volumeID, int fd,
|
|||||||
request->fd = fd;
|
request->fd = fd;
|
||||||
request->request = requestID;
|
request->request = requestID;
|
||||||
request->cookie = cookie;
|
request->cookie = cookie;
|
||||||
request->vecCount = vecCount;
|
|
||||||
|
|
||||||
if (vecCount > 0) {
|
if (vecCount > 0) {
|
||||||
error = allocator.AllocateData(request->vecs, vecs,
|
vecCount = std::min(vecCount, (uint32)DoIterativeFDIORequest::MAX_VECS);
|
||||||
vecCount * sizeof(file_io_vec), sizeof(off_t), false);
|
memcpy(request->vecs, vecs, sizeof(file_io_vec) * vecCount);
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
request->vecCount = vecCount;
|
||||||
|
|
||||||
// send the request
|
// send the request
|
||||||
UserlandRequestHandler handler(fileSystem, DO_ITERATIVE_FD_IO_REPLY);
|
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);
|
error = port->SendRequest(&allocator, &handler, (Request**)&reply);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
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);
|
RequestReleaser requestReleaser(port, reply);
|
||||||
|
|
||||||
// process the reply
|
// process the reply
|
||||||
|
|||||||
Reference in New Issue
Block a user