* The nature of asynchronous I/O is to be asynchronous. So we can't store
an on-stack structure for the request in a hash table when forwarding the
io() hook. Create a new object (HaikuKernelIORequest) instead and store it
in a hash table in HaikuKernelFileSystem.
* Some work on the userland side of do_iterative_fd_io().
* Added some missing requests in UserlandFSUtil::is_{kernel,userland}_request().
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29505 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -227,6 +227,10 @@ enum {
|
||||
FILE_CACHE_WRITE_REQUEST,
|
||||
FILE_CACHE_WRITE_REPLY,
|
||||
|
||||
// I/O
|
||||
DO_ITERATIVE_FD_IO_REQUEST,
|
||||
DO_ITERATIVE_FD_IO_REPLY,
|
||||
|
||||
// general reply
|
||||
RECEIPT_ACK_REPLY,
|
||||
|
||||
@@ -543,7 +547,7 @@ class DoIORequest : public FileRequest {
|
||||
public:
|
||||
DoIORequest() : FileRequest(DO_IO_REQUEST) {}
|
||||
|
||||
int32 ioRequest;
|
||||
int32 request;
|
||||
bool isWrite;
|
||||
};
|
||||
|
||||
@@ -558,7 +562,7 @@ class CancelIORequest : public FileRequest {
|
||||
public:
|
||||
CancelIORequest() : FileRequest(CANCEL_IO_REQUEST) {}
|
||||
|
||||
int32 ioRequest;
|
||||
int32 request;
|
||||
};
|
||||
|
||||
// CancelIOReply
|
||||
@@ -1740,6 +1744,29 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - I/O
|
||||
|
||||
|
||||
// DoIterativeFDIORequest
|
||||
class DoIterativeFDIORequest : public Request {
|
||||
public:
|
||||
DoIterativeFDIORequest() : Request(DO_ITERATIVE_FD_IO_REQUEST) {}
|
||||
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
||||
|
||||
int fd;
|
||||
int32 request;
|
||||
void* cookie;
|
||||
Address vecs;
|
||||
uint32 vecCount;
|
||||
};
|
||||
|
||||
// DoIterativeFDIOReply
|
||||
class DoIterativeFDIOReply : public ReplyRequest {
|
||||
public:
|
||||
DoIterativeFDIOReply() : ReplyRequest(DO_ITERATIVE_FD_IO_REPLY) {}
|
||||
};
|
||||
|
||||
|
||||
//////////////////
|
||||
// General Reply
|
||||
|
||||
@@ -2125,6 +2152,11 @@ do_for_request(Request* request, Task& task)
|
||||
return task((FileCacheWriteRequest*)request);
|
||||
case FILE_CACHE_WRITE_REPLY:
|
||||
return task((FileCacheWriteReply*)request);
|
||||
// I/O
|
||||
case DO_ITERATIVE_FD_IO_REQUEST:
|
||||
return task((DoIterativeFDIORequest*)request);
|
||||
case DO_ITERATIVE_FD_IO_REPLY:
|
||||
return task((DoIterativeFDIOReply*)request);
|
||||
// general reply
|
||||
case RECEIPT_ACK_REPLY:
|
||||
return task((ReceiptAckReply*)request);
|
||||
@@ -2340,6 +2372,9 @@ using UserlandFSUtil::FileCacheReadRequest;
|
||||
using UserlandFSUtil::FileCacheReadReply;
|
||||
using UserlandFSUtil::FileCacheWriteRequest;
|
||||
using UserlandFSUtil::FileCacheWriteReply;
|
||||
// I/O
|
||||
using UserlandFSUtil::DoIterativeFDIORequest;
|
||||
using UserlandFSUtil::DoIterativeFDIOReply;
|
||||
// general reply
|
||||
using UserlandFSUtil::ReceiptAckReply;
|
||||
|
||||
|
||||
@@ -313,6 +313,14 @@ 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 -
|
||||
|
||||
@@ -531,6 +539,13 @@ UserlandFSUtil::is_kernel_request(uint32 type)
|
||||
case WRITE_VNODE_REPLY:
|
||||
case FS_REMOVE_VNODE_REPLY:
|
||||
return false;
|
||||
// asynchronous I/O
|
||||
case DO_IO_REQUEST:
|
||||
case CANCEL_IO_REQUEST:
|
||||
return true;
|
||||
case DO_IO_REPLY:
|
||||
case CANCEL_IO_REPLY:
|
||||
return false;
|
||||
// nodes
|
||||
case IOCTL_REQUEST:
|
||||
case SET_FLAGS_REQUEST:
|
||||
@@ -674,6 +689,7 @@ UserlandFSUtil::is_kernel_request(uint32 type)
|
||||
// vnodes
|
||||
case GET_VNODE_REQUEST:
|
||||
case PUT_VNODE_REQUEST:
|
||||
case ACQUIRE_VNODE_REQUEST:
|
||||
case NEW_VNODE_REQUEST:
|
||||
case PUBLISH_VNODE_REQUEST:
|
||||
case REMOVE_VNODE_REQUEST:
|
||||
@@ -682,12 +698,35 @@ UserlandFSUtil::is_kernel_request(uint32 type)
|
||||
return false;
|
||||
case GET_VNODE_REPLY:
|
||||
case PUT_VNODE_REPLY:
|
||||
case ACQUIRE_VNODE_REPLY:
|
||||
case NEW_VNODE_REPLY:
|
||||
case PUBLISH_VNODE_REPLY:
|
||||
case REMOVE_VNODE_REPLY:
|
||||
case UNREMOVE_VNODE_REPLY:
|
||||
case GET_VNODE_REMOVED_REPLY:
|
||||
return true;
|
||||
// file cache
|
||||
case FILE_CACHE_CREATE_REQUEST:
|
||||
case FILE_CACHE_DELETE_REQUEST:
|
||||
case FILE_CACHE_SET_ENABLED_REQUEST:
|
||||
case FILE_CACHE_SET_SIZE_REQUEST:
|
||||
case FILE_CACHE_SYNC_REQUEST:
|
||||
case FILE_CACHE_READ_REQUEST:
|
||||
case FILE_CACHE_WRITE_REQUEST:
|
||||
return false;
|
||||
case FILE_CACHE_CREATE_REPLY:
|
||||
case FILE_CACHE_DELETE_REPLY:
|
||||
case FILE_CACHE_SET_ENABLED_REPLY:
|
||||
case FILE_CACHE_SET_SIZE_REPLY:
|
||||
case FILE_CACHE_SYNC_REPLY:
|
||||
case FILE_CACHE_READ_REPLY:
|
||||
case FILE_CACHE_WRITE_REPLY:
|
||||
return true;
|
||||
// I/O
|
||||
case DO_ITERATIVE_FD_IO_REQUEST:
|
||||
return false;
|
||||
case DO_ITERATIVE_FD_IO_REPLY:
|
||||
return true;
|
||||
|
||||
// general reply
|
||||
case RECEIPT_ACK_REPLY:
|
||||
@@ -737,6 +776,13 @@ UserlandFSUtil::is_userland_request(uint32 type)
|
||||
case WRITE_VNODE_REPLY:
|
||||
case FS_REMOVE_VNODE_REPLY:
|
||||
return true;
|
||||
// asynchronous I/O
|
||||
case DO_IO_REQUEST:
|
||||
case CANCEL_IO_REQUEST:
|
||||
return false;
|
||||
case DO_IO_REPLY:
|
||||
case CANCEL_IO_REPLY:
|
||||
return true;
|
||||
// nodes
|
||||
case IOCTL_REQUEST:
|
||||
case SET_FLAGS_REQUEST:
|
||||
@@ -880,6 +926,7 @@ UserlandFSUtil::is_userland_request(uint32 type)
|
||||
// vnodes
|
||||
case GET_VNODE_REQUEST:
|
||||
case PUT_VNODE_REQUEST:
|
||||
case ACQUIRE_VNODE_REQUEST:
|
||||
case NEW_VNODE_REQUEST:
|
||||
case PUBLISH_VNODE_REQUEST:
|
||||
case REMOVE_VNODE_REQUEST:
|
||||
@@ -888,12 +935,35 @@ UserlandFSUtil::is_userland_request(uint32 type)
|
||||
return true;
|
||||
case GET_VNODE_REPLY:
|
||||
case PUT_VNODE_REPLY:
|
||||
case ACQUIRE_VNODE_REPLY:
|
||||
case NEW_VNODE_REPLY:
|
||||
case PUBLISH_VNODE_REPLY:
|
||||
case REMOVE_VNODE_REPLY:
|
||||
case UNREMOVE_VNODE_REPLY:
|
||||
case GET_VNODE_REMOVED_REPLY:
|
||||
return false;
|
||||
// file cache
|
||||
case FILE_CACHE_CREATE_REQUEST:
|
||||
case FILE_CACHE_DELETE_REQUEST:
|
||||
case FILE_CACHE_SET_ENABLED_REQUEST:
|
||||
case FILE_CACHE_SET_SIZE_REQUEST:
|
||||
case FILE_CACHE_SYNC_REQUEST:
|
||||
case FILE_CACHE_READ_REQUEST:
|
||||
case FILE_CACHE_WRITE_REQUEST:
|
||||
return true;
|
||||
case FILE_CACHE_CREATE_REPLY:
|
||||
case FILE_CACHE_DELETE_REPLY:
|
||||
case FILE_CACHE_SET_ENABLED_REPLY:
|
||||
case FILE_CACHE_SET_SIZE_REPLY:
|
||||
case FILE_CACHE_SYNC_REPLY:
|
||||
case FILE_CACHE_READ_REPLY:
|
||||
case FILE_CACHE_WRITE_REPLY:
|
||||
return false;
|
||||
// I/O
|
||||
case DO_ITERATIVE_FD_IO_REQUEST:
|
||||
return false;
|
||||
case DO_ITERATIVE_FD_IO_REPLY:
|
||||
return true;
|
||||
|
||||
// general reply
|
||||
case RECEIPT_ACK_REPLY:
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#ifndef USERLAND_FS_IO_REQUEST_INFO_H
|
||||
#define USERLAND_FS_IO_REQUEST_INFO_H
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
namespace UserlandFS {
|
||||
|
||||
struct IORequestInfo : HashTableLink<IORequestInfo> {
|
||||
struct IORequestInfo {
|
||||
int32 id;
|
||||
bool isWrite;
|
||||
|
||||
@@ -20,6 +20,13 @@ struct IORequestInfo : HashTableLink<IORequestInfo> {
|
||||
isWrite(isWrite)
|
||||
{
|
||||
}
|
||||
|
||||
IORequestInfo(const IORequestInfo& other)
|
||||
:
|
||||
id(other.id),
|
||||
isWrite(other.isWrite)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace UserlandFS
|
||||
|
||||
@@ -552,8 +552,8 @@ UserlandRequestHandler::_HandleRequest(DoIORequest* request)
|
||||
|
||||
if (result == B_OK) {
|
||||
RequestThreadContext context(volume);
|
||||
IORequestInfo requestInfo(request->ioRequest, request->isWrite);
|
||||
result = volume->DoIO(request->node, request->fileCookie, &requestInfo);
|
||||
IORequestInfo requestInfo(request->request, request->isWrite);
|
||||
result = volume->DoIO(request->node, request->fileCookie, requestInfo);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
@@ -582,7 +582,7 @@ UserlandRequestHandler::_HandleRequest(CancelIORequest* request)
|
||||
if (result == B_OK) {
|
||||
RequestThreadContext context(volume);
|
||||
result = volume->CancelIO(request->node, request->fileCookie,
|
||||
request->ioRequest);
|
||||
request->request);
|
||||
}
|
||||
|
||||
// prepare the reply
|
||||
|
||||
@@ -193,7 +193,7 @@ Volume::RemoveVNode(void* node, bool reenter)
|
||||
|
||||
|
||||
status_t
|
||||
Volume::DoIO(void* node, void* cookie, IORequestInfo* requestInfo)
|
||||
Volume::DoIO(void* node, void* cookie, const IORequestInfo& requestInfo)
|
||||
{
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
|
||||
// asynchronous I/O
|
||||
virtual status_t DoIO(void* node, void* cookie,
|
||||
IORequestInfo* requestInfo);
|
||||
const IORequestInfo& requestInfo);
|
||||
virtual status_t CancelIO(void* node, void* cookie,
|
||||
int32 ioRequestID);
|
||||
|
||||
|
||||
@@ -8,20 +8,50 @@
|
||||
|
||||
#include <fs_interface.h>
|
||||
|
||||
#include <AutoLocker.h>
|
||||
|
||||
#include <block_cache.h>
|
||||
#include <condition_variable.h>
|
||||
|
||||
#include "HaikuKernelIORequest.h"
|
||||
#include "HaikuKernelVolume.h"
|
||||
|
||||
|
||||
// IORequestHashDefinition
|
||||
struct HaikuKernelFileSystem::IORequestHashDefinition {
|
||||
typedef int32 KeyType;
|
||||
typedef HaikuKernelIORequest ValueType;
|
||||
|
||||
size_t HashKey(int32 key) const
|
||||
{ return key; }
|
||||
size_t Hash(const HaikuKernelIORequest* value) const
|
||||
{ return value->id; }
|
||||
bool Compare(int32 key, const HaikuKernelIORequest* value) const
|
||||
{ return value->id == key; }
|
||||
HashTableLink<HaikuKernelIORequest>*
|
||||
GetLink(HaikuKernelIORequest* value) const
|
||||
{ return value; }
|
||||
};
|
||||
|
||||
|
||||
// IORequestTable
|
||||
struct HaikuKernelFileSystem::IORequestTable
|
||||
: public OpenHashTable<IORequestHashDefinition> {
|
||||
};
|
||||
|
||||
|
||||
// constructor
|
||||
HaikuKernelFileSystem::HaikuKernelFileSystem(file_system_module_info* fsModule)
|
||||
: FileSystem(),
|
||||
fFSModule(fsModule)
|
||||
:
|
||||
FileSystem(),
|
||||
fFSModule(fsModule),
|
||||
fIORequests(NULL),
|
||||
fLock("HaikuKernelFileSystem")
|
||||
{
|
||||
_InitCapabilities();
|
||||
}
|
||||
|
||||
|
||||
// destructor
|
||||
HaikuKernelFileSystem::~HaikuKernelFileSystem()
|
||||
{
|
||||
@@ -29,19 +59,35 @@ HaikuKernelFileSystem::~HaikuKernelFileSystem()
|
||||
if (fFSModule->info.std_ops)
|
||||
fFSModule->info.std_ops(B_MODULE_UNINIT);
|
||||
|
||||
delete fIORequests;
|
||||
|
||||
// TODO: Call the cleanup methods (condition vars, block cache)!
|
||||
}
|
||||
|
||||
|
||||
// Init
|
||||
status_t
|
||||
HaikuKernelFileSystem::Init()
|
||||
{
|
||||
status_t error = fLock.InitCheck();
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
// init condition variables
|
||||
condition_variable_init();
|
||||
// TODO: Call the cleanup methods, if something goes wrong!
|
||||
|
||||
// init block cache
|
||||
status_t error = block_cache_init();
|
||||
error = block_cache_init();
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
// create I/O request map
|
||||
fIORequests = new(std::nothrow) IORequestTable;
|
||||
if (fIORequests == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
error = fIORequests->Init();
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
@@ -56,6 +102,7 @@ HaikuKernelFileSystem::Init()
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// CreateVolume
|
||||
status_t
|
||||
HaikuKernelFileSystem::CreateVolume(Volume** _volume, dev_t id)
|
||||
@@ -79,6 +126,7 @@ HaikuKernelFileSystem::CreateVolume(Volume** _volume, dev_t id)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// DeleteVolume
|
||||
status_t
|
||||
HaikuKernelFileSystem::DeleteVolume(Volume* volume)
|
||||
@@ -89,6 +137,51 @@ HaikuKernelFileSystem::DeleteVolume(Volume* volume)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// AddIORequest
|
||||
status_t
|
||||
HaikuKernelFileSystem::AddIORequest(HaikuKernelIORequest* request)
|
||||
{
|
||||
AutoLocker<Locker> _(fLock);
|
||||
|
||||
// check, if a request with that ID is already in the map
|
||||
if (fIORequests->Lookup(request->id) != NULL)
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
|
||||
fIORequests->Insert(request);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// GetIORequest
|
||||
HaikuKernelIORequest*
|
||||
HaikuKernelFileSystem::GetIORequest(int32 requestID)
|
||||
{
|
||||
AutoLocker<Locker> _(fLock);
|
||||
|
||||
HaikuKernelIORequest* request = fIORequests->Lookup(requestID);
|
||||
if (request != NULL)
|
||||
request->refCount++;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
// PutIORequest
|
||||
void
|
||||
HaikuKernelFileSystem::PutIORequest(HaikuKernelIORequest* request,
|
||||
int32 refCount)
|
||||
{
|
||||
AutoLocker<Locker> locker(fLock);
|
||||
|
||||
if ((request->refCount -= refCount) <= 0) {
|
||||
fIORequests->Remove(request);
|
||||
locker.Unlock();
|
||||
delete request;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// _InitCapabilities
|
||||
void
|
||||
HaikuKernelFileSystem::_InitCapabilities()
|
||||
|
||||
@@ -3,12 +3,16 @@
|
||||
#ifndef USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H
|
||||
#define USERLAND_FS_HAIKU_KERNEL_FILE_SYSTEM_H
|
||||
|
||||
#include "Locker.h"
|
||||
|
||||
#include "../FileSystem.h"
|
||||
|
||||
struct file_system_module_info;
|
||||
|
||||
namespace UserlandFS {
|
||||
|
||||
struct HaikuKernelIORequest;
|
||||
|
||||
class HaikuKernelFileSystem : public FileSystem {
|
||||
public:
|
||||
HaikuKernelFileSystem(
|
||||
@@ -20,11 +24,22 @@ public:
|
||||
virtual status_t CreateVolume(Volume** volume, dev_t id);
|
||||
virtual status_t DeleteVolume(Volume* volume);
|
||||
|
||||
status_t AddIORequest(HaikuKernelIORequest* request);
|
||||
HaikuKernelIORequest* GetIORequest(int32 requestID);
|
||||
void PutIORequest(HaikuKernelIORequest* request,
|
||||
int32 refCount = 1);
|
||||
|
||||
private:
|
||||
class IORequestHashDefinition;
|
||||
class IORequestTable;
|
||||
|
||||
private:
|
||||
void _InitCapabilities();
|
||||
|
||||
private:
|
||||
file_system_module_info* fFSModule;
|
||||
IORequestTable* fIORequests;
|
||||
Locker fLock;
|
||||
};
|
||||
|
||||
} // namespace UserlandFS
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "../IORequestInfo.h"
|
||||
#include "../kernel_emu.h"
|
||||
|
||||
#include "HaikuKernelFileSystem.h"
|
||||
#include "HaikuKernelIORequest.h"
|
||||
#include "HaikuKernelNode.h"
|
||||
|
||||
|
||||
@@ -24,26 +26,12 @@ 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> {
|
||||
};
|
||||
// _FileSystem
|
||||
inline HaikuKernelFileSystem*
|
||||
HaikuKernelVolume::_FileSystem() const
|
||||
{
|
||||
return static_cast<HaikuKernelFileSystem*>(fFileSystem);
|
||||
}
|
||||
|
||||
|
||||
// constructor
|
||||
@@ -52,8 +40,7 @@ HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
|
||||
:
|
||||
Volume(fileSystem, id),
|
||||
fFSModule(fsModule),
|
||||
fNodes(NULL),
|
||||
fIORequests(NULL)
|
||||
fNodes(NULL)
|
||||
{
|
||||
fVolume.id = id;
|
||||
fVolume.partition = -1;
|
||||
@@ -71,7 +58,6 @@ HaikuKernelVolume::HaikuKernelVolume(FileSystem* fileSystem, dev_t id,
|
||||
HaikuKernelVolume::~HaikuKernelVolume()
|
||||
{
|
||||
delete fNodes;
|
||||
delete fIORequests;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,14 +68,7 @@ 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;
|
||||
|
||||
fIORequests = new(std::nothrow) IORequestTable;
|
||||
if (fIORequests == NULL)
|
||||
return B_NO_MEMORY;
|
||||
return fIORequests->Init();
|
||||
return fNodes->InitCheck();
|
||||
}
|
||||
|
||||
|
||||
@@ -184,14 +163,6 @@ 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 -----
|
||||
|
||||
@@ -374,30 +345,39 @@ HaikuKernelVolume::RemoveVNode(void* _node, bool reenter)
|
||||
|
||||
|
||||
status_t
|
||||
HaikuKernelVolume::DoIO(void* _node, void* cookie, IORequestInfo* requestInfo)
|
||||
HaikuKernelVolume::DoIO(void* _node, void* cookie,
|
||||
const 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);
|
||||
// create a request object
|
||||
HaikuKernelIORequest* request
|
||||
= new(std::nothrow) HaikuKernelIORequest(requestInfo);
|
||||
if (request == NULL)
|
||||
RETURN_ERROR(B_NO_MEMORY);
|
||||
|
||||
fIORequests->Insert(requestInfo);
|
||||
locker.Unlock();
|
||||
status_t error = _FileSystem()->AddIORequest(request);
|
||||
if (error != B_OK) {
|
||||
delete request;
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
// call the hook
|
||||
status_t error = node->ops->io(&fVolume, node, cookie,
|
||||
(io_request*)(addr_t)requestInfo->id);
|
||||
error = node->ops->io(&fVolume, node, cookie, (io_request*)request);
|
||||
|
||||
// remove the info from the table
|
||||
locker.Lock();
|
||||
fIORequests->Remove(requestInfo);
|
||||
// directly put our reference to the request, if the call failed
|
||||
if (error != B_OK) {
|
||||
_FileSystem()->PutIORequest(request);
|
||||
RETURN_ERROR(error);
|
||||
}
|
||||
|
||||
return error;
|
||||
// TODO: ATM we don't release our reference when the request is finished
|
||||
// normally!
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -409,8 +389,20 @@ HaikuKernelVolume::CancelIO(void* _node, void* cookie, int32 ioRequestID)
|
||||
if (!node->ops->cancel_io)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
return node->ops->cancel_io(&fVolume, node, cookie,
|
||||
(io_request*)(addr_t)ioRequestID);
|
||||
// get the request
|
||||
HaikuKernelIORequest* request = _FileSystem()->GetIORequest(ioRequestID);
|
||||
if (request == NULL)
|
||||
RETURN_ERROR(B_BAD_VALUE);
|
||||
|
||||
// call the hook
|
||||
status_t error = node->ops->cancel_io(&fVolume, node, cookie,
|
||||
(io_request*)request);
|
||||
|
||||
// put the request -- once for the reference we got above, once for the
|
||||
// reference we've got in DoIO()
|
||||
_FileSystem()->PutIORequest(request, 2);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace UserlandFS {
|
||||
|
||||
class HaikuKernelFileSystem;
|
||||
class HaikuKernelNode;
|
||||
|
||||
|
||||
@@ -34,7 +35,6 @@ 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,
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
// asynchronous I/O
|
||||
virtual status_t DoIO(void* node, void* cookie,
|
||||
IORequestInfo* requestInfo);
|
||||
const IORequestInfo& requestInfo);
|
||||
virtual status_t CancelIO(void* node, void* cookie,
|
||||
int32 ioRequestID);
|
||||
|
||||
@@ -185,17 +185,15 @@ private:
|
||||
};
|
||||
|
||||
class NodeMap;
|
||||
class IORequestHashDefinition;
|
||||
class IORequestTable;
|
||||
|
||||
private:
|
||||
void _InitCapabilities();
|
||||
inline HaikuKernelFileSystem* _FileSystem() const;
|
||||
|
||||
private:
|
||||
file_system_module_info* fFSModule;
|
||||
FSVolume fVolume;
|
||||
NodeMap* fNodes;
|
||||
IORequestTable* fIORequests;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "../kernel_emu.h"
|
||||
#include "../RequestThread.h"
|
||||
|
||||
#include "HaikuKernelIORequest.h"
|
||||
#include "HaikuKernelNode.h"
|
||||
#include "HaikuKernelVolume.h"
|
||||
#include "vfs.h"
|
||||
@@ -270,11 +271,39 @@ do_fd_io(int fd, io_request *request)
|
||||
|
||||
// do_iterative_fd_io
|
||||
status_t
|
||||
do_iterative_fd_io(int fd, io_request *request, iterative_io_get_vecs getVecs,
|
||||
iterative_io_finished finished, void *cookie)
|
||||
do_iterative_fd_io(int fd, io_request *_request, iterative_io_get_vecs getVecs,
|
||||
iterative_io_finished finished, void *_cookie)
|
||||
{
|
||||
// TODO: Implement!
|
||||
return B_UNSUPPORTED;
|
||||
#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;
|
||||
|
||||
// create a cookie
|
||||
HaikuKernelIterativeFDIOCookie* cookie
|
||||
= new(std::nothrow) HaikuKernelIterativeFDIOCookie(fd, request, getVecs,
|
||||
finished, _cookie);
|
||||
if (cookie == NULL) {
|
||||
finished(_cookie, _request, B_NO_MEMORY, false, 0);
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
// send the request
|
||||
status_t error = UserlandFS::KernelEmu::do_iterative_fd_io(fd, request->id,
|
||||
cookie, NULL, 0);
|
||||
if (error != B_OK) {
|
||||
delete cookie;
|
||||
return error;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -284,19 +313,7 @@ do_iterative_fd_io(int fd, io_request *request, iterative_io_get_vecs getVecs,
|
||||
bool
|
||||
io_request_is_write(const io_request* request)
|
||||
{
|
||||
// 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;
|
||||
return ((HaikuKernelIORequest*)request)->isWrite;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -837,6 +837,53 @@ UserlandFS::KernelEmu::file_cache_write(dev_t mountID, ino_t vnodeID,
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - I/O
|
||||
|
||||
|
||||
status_t
|
||||
UserlandFS::KernelEmu::do_iterative_fd_io(int fd, int32 requestID, void* cookie,
|
||||
const file_io_vec* vecs, uint32 vecCount)
|
||||
{
|
||||
// get the request port and the file system
|
||||
RequestPort* port;
|
||||
FileSystem* fileSystem;
|
||||
status_t error = get_port_and_fs(&port, &fileSystem);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
DoIterativeFDIORequest* request;
|
||||
error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// send the request
|
||||
UserlandRequestHandler handler(fileSystem, DO_ITERATIVE_FD_IO_REPLY);
|
||||
DoIterativeFDIOReply* reply;
|
||||
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!
|
||||
RequestReleaser requestReleaser(port, reply);
|
||||
|
||||
// process the reply
|
||||
return reply->error;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <OS.h>
|
||||
|
||||
struct selectsync;
|
||||
struct file_io_vec;
|
||||
|
||||
namespace UserlandFS {
|
||||
namespace KernelEmu {
|
||||
@@ -31,18 +32,20 @@ status_t remove_vnode(dev_t nsid, ino_t vnid);
|
||||
status_t unremove_vnode(dev_t nsid, ino_t vnid);
|
||||
status_t get_vnode_removed(dev_t nsid, ino_t vnid, bool* removed);
|
||||
|
||||
extern status_t file_cache_create(dev_t mountID, ino_t vnodeID, off_t size);
|
||||
extern status_t file_cache_delete(dev_t mountID, ino_t vnodeID);
|
||||
extern status_t file_cache_set_enabled(dev_t mountID, ino_t vnodeID,
|
||||
bool enabled);
|
||||
extern status_t file_cache_set_size(dev_t mountID, ino_t vnodeID, off_t size);
|
||||
extern status_t file_cache_sync(dev_t mountID, ino_t vnodeID);
|
||||
status_t file_cache_create(dev_t mountID, ino_t vnodeID, off_t size);
|
||||
status_t file_cache_delete(dev_t mountID, ino_t vnodeID);
|
||||
status_t file_cache_set_enabled(dev_t mountID, ino_t vnodeID, bool enabled);
|
||||
status_t file_cache_set_size(dev_t mountID, ino_t vnodeID, off_t size);
|
||||
status_t file_cache_sync(dev_t mountID, ino_t vnodeID);
|
||||
|
||||
extern status_t file_cache_read(dev_t mountID, ino_t vnodeID, void *cookie,
|
||||
status_t file_cache_read(dev_t mountID, ino_t vnodeID, void *cookie,
|
||||
off_t offset, void *bufferBase, size_t *_size);
|
||||
extern status_t file_cache_write(dev_t mountID, ino_t vnodeID, void *cookie,
|
||||
status_t file_cache_write(dev_t mountID, ino_t vnodeID, void *cookie,
|
||||
off_t offset, const void *buffer, size_t *_size);
|
||||
|
||||
status_t do_iterative_fd_io(int fd, int32 requestID, void* cookie,
|
||||
const file_io_vec* vecs, uint32 vecCount);
|
||||
|
||||
void kernel_debugger(const char *message);
|
||||
void vpanic(const char *format, va_list args);
|
||||
void panic(const char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
|
||||
|
||||
Reference in New Issue
Block a user