* 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 "Compatibility.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
#include "IORequestInfo.h"
|
||||||
#include "RequestPort.h"
|
#include "RequestPort.h"
|
||||||
#include "Requests.h"
|
#include "Requests.h"
|
||||||
#include "RequestThread.h"
|
#include "RequestThread.h"
|
||||||
@@ -69,6 +70,12 @@ UserlandRequestHandler::HandleRequest(Request* request)
|
|||||||
case FS_REMOVE_VNODE_REQUEST:
|
case FS_REMOVE_VNODE_REQUEST:
|
||||||
return _HandleRequest((FSRemoveVNodeRequest*)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
|
// nodes
|
||||||
case IOCTL_REQUEST:
|
case IOCTL_REQUEST:
|
||||||
return _HandleRequest((IOCtlRequest*)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
|
// #pragma mark - nodes
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ class GetVNodeNameRequest;
|
|||||||
class ReadVNodeRequest;
|
class ReadVNodeRequest;
|
||||||
class WriteVNodeRequest;
|
class WriteVNodeRequest;
|
||||||
class FSRemoveVNodeRequest;
|
class FSRemoveVNodeRequest;
|
||||||
|
// asynchronous I/O
|
||||||
|
class DoIORequest;
|
||||||
|
class CancelIORequest;
|
||||||
// nodes
|
// nodes
|
||||||
class IOCtlRequest;
|
class IOCtlRequest;
|
||||||
class SetFlagsRequest;
|
class SetFlagsRequest;
|
||||||
@@ -115,6 +118,10 @@ private:
|
|||||||
status_t _HandleRequest(WriteVNodeRequest* request);
|
status_t _HandleRequest(WriteVNodeRequest* request);
|
||||||
status_t _HandleRequest(FSRemoveVNodeRequest* request);
|
status_t _HandleRequest(FSRemoveVNodeRequest* request);
|
||||||
|
|
||||||
|
// asynchronous I/O
|
||||||
|
status_t _HandleRequest(DoIORequest* request);
|
||||||
|
status_t _HandleRequest(CancelIORequest* request);
|
||||||
|
|
||||||
// nodes
|
// nodes
|
||||||
status_t _HandleRequest(IOCtlRequest* request);
|
status_t _HandleRequest(IOCtlRequest* request);
|
||||||
status_t _HandleRequest(SetFlagsRequest* 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
|
// #pragma mark - nodes
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
namespace UserlandFS {
|
namespace UserlandFS {
|
||||||
|
|
||||||
class FileSystem;
|
class FileSystem;
|
||||||
|
class IORequestInfo;
|
||||||
|
|
||||||
using UserlandFSUtil::FSVolumeCapabilities;
|
using UserlandFSUtil::FSVolumeCapabilities;
|
||||||
|
|
||||||
@@ -52,6 +53,12 @@ public:
|
|||||||
virtual status_t WriteVNode(void* node, bool reenter);
|
virtual status_t WriteVNode(void* node, bool reenter);
|
||||||
virtual status_t RemoveVNode(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
|
// nodes
|
||||||
virtual status_t IOCtl(void* node, void* cookie,
|
virtual status_t IOCtl(void* node, void* cookie,
|
||||||
uint32 command, void* buffer, size_t size);
|
uint32 command, void* buffer, size_t size);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "HashMap.h"
|
#include "HashMap.h"
|
||||||
|
|
||||||
|
#include "../IORequestInfo.h"
|
||||||
#include "../kernel_emu.h"
|
#include "../kernel_emu.h"
|
||||||
|
|
||||||
#include "HaikuKernelNode.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
|
// constructor
|
||||||
HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
|
HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
|
||||||
file_system_module_info* fsModule)
|
file_system_module_info* fsModule)
|
||||||
:
|
:
|
||||||
Volume(fileSystem, id),
|
Volume(fileSystem, id),
|
||||||
fFSModule(fsModule),
|
fFSModule(fsModule),
|
||||||
fNodes(NULL)
|
fNodes(NULL),
|
||||||
|
fIORequests(NULL)
|
||||||
{
|
{
|
||||||
fVolume.id = id;
|
fVolume.id = id;
|
||||||
fVolume.partition = -1;
|
fVolume.partition = -1;
|
||||||
@@ -46,6 +70,8 @@ HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
|
|||||||
// destructor
|
// destructor
|
||||||
HaikuKernelVolume::~HaikuKernelVolume()
|
HaikuKernelVolume::~HaikuKernelVolume()
|
||||||
{
|
{
|
||||||
|
delete fNodes;
|
||||||
|
delete fIORequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -56,8 +82,14 @@ HaikuKernelVolume::Init()
|
|||||||
fNodes = new(std::nothrow) NodeMap;
|
fNodes = new(std::nothrow) NodeMap;
|
||||||
if (fNodes == NULL)
|
if (fNodes == NULL)
|
||||||
return B_NO_MEMORY;
|
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 -
|
||||||
// #pragma mark ----- FS -----
|
// #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
|
// #pragma mark - nodes
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public:
|
|||||||
void UndoPublishVNode(HaikuKernelNode* node);
|
void UndoPublishVNode(HaikuKernelNode* node);
|
||||||
|
|
||||||
HaikuKernelNode* NodeWithID(ino_t vnodeID) const;
|
HaikuKernelNode* NodeWithID(ino_t vnodeID) const;
|
||||||
|
IORequestInfo* IORequestInfoWithID(int32 id) const;
|
||||||
|
|
||||||
// FS
|
// FS
|
||||||
virtual status_t Mount(const char* device, uint32 flags,
|
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 WriteVNode(void* node, bool reenter);
|
||||||
virtual status_t RemoveVNode(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
|
// nodes
|
||||||
virtual status_t IOCtl(void* node, void* cookie,
|
virtual status_t IOCtl(void* node, void* cookie,
|
||||||
uint32 command, void* buffer, size_t size);
|
uint32 command, void* buffer, size_t size);
|
||||||
@@ -178,6 +185,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class NodeMap;
|
class NodeMap;
|
||||||
|
class IORequestHashDefinition;
|
||||||
|
class IORequestTable;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _InitCapabilities();
|
void _InitCapabilities();
|
||||||
@@ -186,6 +195,7 @@ private:
|
|||||||
file_system_module_info* fFSModule;
|
file_system_module_info* fFSModule;
|
||||||
FSVolume fVolume;
|
FSVolume fVolume;
|
||||||
NodeMap* fNodes;
|
NodeMap* fNodes;
|
||||||
|
IORequestTable* fIORequests;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
|
|
||||||
#include "../FileSystem.h"
|
#include "../FileSystem.h"
|
||||||
|
#include "../IORequestInfo.h"
|
||||||
#include "../kernel_emu.h"
|
#include "../kernel_emu.h"
|
||||||
|
#include "../RequestThread.h"
|
||||||
|
|
||||||
#include "HaikuKernelNode.h"
|
#include "HaikuKernelNode.h"
|
||||||
#include "HaikuKernelVolume.h"
|
#include "HaikuKernelVolume.h"
|
||||||
@@ -282,8 +284,19 @@ do_iterative_fd_io(int fd, io_request *request, iterative_io_get_vecs getVecs,
|
|||||||
bool
|
bool
|
||||||
io_request_is_write(const io_request* request)
|
io_request_is_write(const io_request* request)
|
||||||
{
|
{
|
||||||
// TODO: Implement!
|
// get the volume
|
||||||
return false;
|
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