* Implemented the userland side for propagating the io() and cancel_io() hooks.

* Implemented io_request_is_write().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29469 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-03-11 02:00:23 +00:00
parent b538ceb816
commit f1c6ce08f2
8 changed files with 241 additions and 4 deletions
@@ -0,0 +1,31 @@
/*
* Copyright 2009, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef USERLAND_FS_IO_REQUEST_INFO_H
#define USERLAND_FS_IO_REQUEST_INFO_H
#include <util/OpenHashTable.h>
namespace UserlandFS {
struct IORequestInfo : HashTableLink<IORequestInfo> {
int32 id;
bool isWrite;
IORequestInfo(int32 id, bool isWrite)
:
id(id),
isWrite(isWrite)
{
}
};
} // namespace UserlandFS
using UserlandFS::IORequestInfo;
#endif // USERLAND_FS_IO_REQUEST_INFO_H
@@ -6,6 +6,7 @@
#include "Compatibility.h"
#include "Debug.h"
#include "FileSystem.h"
#include "IORequestInfo.h"
#include "RequestPort.h"
#include "Requests.h"
#include "RequestThread.h"
@@ -69,6 +70,12 @@ UserlandRequestHandler::HandleRequest(Request* request)
case FS_REMOVE_VNODE_REQUEST:
return _HandleRequest((FSRemoveVNodeRequest*)request);
// asynchronous I/O
case DO_IO_REQUEST:
return _HandleRequest((DoIORequest*)request);
case CANCEL_IO_REQUEST:
return _HandleRequest((CancelIORequest*)request);
// nodes
case IOCTL_REQUEST:
return _HandleRequest((IOCtlRequest*)request);
@@ -531,6 +538,67 @@ UserlandRequestHandler::_HandleRequest(FSRemoveVNodeRequest* request)
}
// #pragma mark - asynchronous I/O
status_t
UserlandRequestHandler::_HandleRequest(DoIORequest* 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);
IORequestInfo requestInfo(request->ioRequest, request->isWrite);
result = volume->DoIO(request->node, request->fileCookie, &requestInfo);
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
DoIOReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
RETURN_ERROR(error);
reply->error = result;
// send the reply
return _SendReply(allocator, false);
}
status_t
UserlandRequestHandler::_HandleRequest(CancelIORequest* 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->CancelIO(request->node, request->fileCookie,
request->ioRequest);
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
CancelIOReply* 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
@@ -19,6 +19,9 @@ class GetVNodeNameRequest;
class ReadVNodeRequest;
class WriteVNodeRequest;
class FSRemoveVNodeRequest;
// asynchronous I/O
class DoIORequest;
class CancelIORequest;
// nodes
class IOCtlRequest;
class SetFlagsRequest;
@@ -115,6 +118,10 @@ private:
status_t _HandleRequest(WriteVNodeRequest* request);
status_t _HandleRequest(FSRemoveVNodeRequest* request);
// asynchronous I/O
status_t _HandleRequest(DoIORequest* request);
status_t _HandleRequest(CancelIORequest* request);
// nodes
status_t _HandleRequest(IOCtlRequest* request);
status_t _HandleRequest(SetFlagsRequest* request);
@@ -189,6 +189,23 @@ Volume::RemoveVNode(void* node, bool reenter)
}
// #pragma mark - asynchronous I/O
status_t
Volume::DoIO(void* node, void* cookie, IORequestInfo* requestInfo)
{
return B_BAD_VALUE;
}
status_t
Volume::CancelIO(void* node, void* cookie, int32 ioRequestID)
{
return B_BAD_VALUE;
}
// #pragma mark - nodes
@@ -14,6 +14,7 @@
namespace UserlandFS {
class FileSystem;
class IORequestInfo;
using UserlandFSUtil::FSVolumeCapabilities;
@@ -52,6 +53,12 @@ public:
virtual status_t WriteVNode(void* node, bool reenter);
virtual status_t RemoveVNode(void* node, bool reenter);
// asynchronous I/O
virtual status_t DoIO(void* node, void* cookie,
IORequestInfo* requestInfo);
virtual status_t CancelIO(void* node, void* cookie,
int32 ioRequestID);
// nodes
virtual status_t IOCtl(void* node, void* cookie,
uint32 command, void* buffer, size_t size);
@@ -12,6 +12,7 @@
#include "Debug.h"
#include "HashMap.h"
#include "../IORequestInfo.h"
#include "../kernel_emu.h"
#include "HaikuKernelNode.h"
@@ -23,13 +24,36 @@ 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<IORequestInfo>* GetLink(IORequestInfo* value) const
{ return value; }
};
// IORequestTable
struct HaikuKernelVolume::IORequestTable
: public OpenHashTable<IORequestHashDefinition> {
};
// constructor
HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
file_system_module_info* fsModule)
:
Volume(fileSystem, id),
fFSModule(fsModule),
fNodes(NULL)
fNodes(NULL),
fIORequests(NULL)
{
fVolume.id = id;
fVolume.partition = -1;
@@ -46,6 +70,8 @@ HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
// destructor
HaikuKernelVolume::~HaikuKernelVolume()
{
delete fNodes;
delete fIORequests;
}
@@ -56,8 +82,14 @@ 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;
return fNodes->InitCheck();
fIORequests = new(std::nothrow) IORequestTable;
if (fIORequests == NULL)
return B_NO_MEMORY;
return fIORequests->Init();
}
@@ -152,6 +184,14 @@ HaikuKernelVolume::NodeWithID(ino_t vnodeID) const
}
IORequestInfo*
HaikuKernelVolume::IORequestInfoWithID(int32 id) const
{
AutoLocker<NodeMap> locker(fNodes);
return fIORequests->Lookup(id);
}
// #pragma mark -
// #pragma mark ----- FS -----
@@ -330,6 +370,50 @@ HaikuKernelVolume::RemoveVNode(void* _node, bool reenter)
}
// #pragma mark - asynchronous I/O
status_t
HaikuKernelVolume::DoIO(void* _node, void* cookie, IORequestInfo* requestInfo)
{
HaikuKernelNode* node = (HaikuKernelNode*)_node;
if (!node->ops->io)
return B_BAD_VALUE;
// add the info to the table
AutoLocker<NodeMap> locker(fNodes);
if (fIORequests->Lookup(requestInfo->id))
RETURN_ERROR(B_BAD_VALUE);
fIORequests->Insert(requestInfo);
locker.Unlock();
// call the hook
status_t error = node->ops->io(&fVolume, node, cookie,
(io_request*)(addr_t)requestInfo->id);
// remove the info from the table
locker.Lock();
fIORequests->Remove(requestInfo);
return error;
}
status_t
HaikuKernelVolume::CancelIO(void* _node, void* cookie, int32 ioRequestID)
{
HaikuKernelNode* node = (HaikuKernelNode*)_node;
if (!node->ops->cancel_io)
return B_BAD_VALUE;
return node->ops->cancel_io(&fVolume, node, cookie,
(io_request*)(addr_t)ioRequestID);
}
// #pragma mark - nodes
@@ -34,6 +34,7 @@ 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,
@@ -59,6 +60,12 @@ public:
virtual status_t WriteVNode(void* node, bool reenter);
virtual status_t RemoveVNode(void* node, bool reenter);
// asynchronous I/O
virtual status_t DoIO(void* node, void* cookie,
IORequestInfo* requestInfo);
virtual status_t CancelIO(void* node, void* cookie,
int32 ioRequestID);
// nodes
virtual status_t IOCtl(void* node, void* cookie,
uint32 command, void* buffer, size_t size);
@@ -178,6 +185,8 @@ private:
};
class NodeMap;
class IORequestHashDefinition;
class IORequestTable;
private:
void _InitCapabilities();
@@ -186,6 +195,7 @@ private:
file_system_module_info* fFSModule;
FSVolume fVolume;
NodeMap* fNodes;
IORequestTable* fIORequests;
};
@@ -17,7 +17,9 @@
#include "Debug.h"
#include "../FileSystem.h"
#include "../IORequestInfo.h"
#include "../kernel_emu.h"
#include "../RequestThread.h"
#include "HaikuKernelNode.h"
#include "HaikuKernelVolume.h"
@@ -282,8 +284,19 @@ do_iterative_fd_io(int fd, io_request *request, iterative_io_get_vecs getVecs,
bool
io_request_is_write(const io_request* request)
{
// TODO: Implement!
return false;
// get the volume
RequestThread* thread = RequestThread::GetCurrentThread();
if (thread == NULL || thread->GetContext() == NULL)
return false;
HaikuKernelVolume* volume = dynamic_cast<HaikuKernelVolume*>(
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;
}