* 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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user