* Forward the io() and cancel_io() hooks. Implemented the missing kernel
part. * Implemented a good part of the kernel part for the support of do_iterative_fd_io(). The forwarding of the callbacks are missing yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29540 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1753,6 +1753,7 @@ public:
|
|||||||
DoIterativeFDIORequest() : Request(DO_ITERATIVE_FD_IO_REQUEST) {}
|
DoIterativeFDIORequest() : Request(DO_ITERATIVE_FD_IO_REQUEST) {}
|
||||||
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
||||||
|
|
||||||
|
dev_t nsid;
|
||||||
int fd;
|
int fd;
|
||||||
int32 request;
|
int32 request;
|
||||||
void* cookie;
|
void* cookie;
|
||||||
|
|||||||
@@ -100,6 +100,9 @@ KernelRequestHandler::HandleRequest(Request* request)
|
|||||||
return _HandleRequest((FileCacheReadRequest*)request);
|
return _HandleRequest((FileCacheReadRequest*)request);
|
||||||
case FILE_CACHE_WRITE_REQUEST:
|
case FILE_CACHE_WRITE_REQUEST:
|
||||||
return _HandleRequest((FileCacheWriteRequest*)request);
|
return _HandleRequest((FileCacheWriteRequest*)request);
|
||||||
|
// I/O
|
||||||
|
case DO_ITERATIVE_FD_IO_REQUEST:
|
||||||
|
return _HandleRequest((DoIterativeFDIORequest*)request);
|
||||||
}
|
}
|
||||||
PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %lu\n",
|
PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %lu\n",
|
||||||
request->GetType()));
|
request->GetType()));
|
||||||
@@ -704,6 +707,40 @@ KernelRequestHandler::_HandleRequest(FileCacheWriteRequest* request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _HandleRequest
|
||||||
|
status_t
|
||||||
|
KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request)
|
||||||
|
{
|
||||||
|
// check and execute the request
|
||||||
|
Volume* volume = NULL;
|
||||||
|
status_t result = _GetVolume(request->nsid, &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;
|
||||||
|
|
||||||
|
if (result == B_OK && vecsSize / sizeof(file_io_vec) < vecCount)
|
||||||
|
result = B_BAD_VALUE;
|
||||||
|
|
||||||
|
if (result == B_OK) {
|
||||||
|
result = volume->DoIterativeFDIO(request->fd, request->request,
|
||||||
|
request->cookie, vecs, vecCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the reply
|
||||||
|
RequestAllocator allocator(fPort->GetPort());
|
||||||
|
DoIterativeFDIOReply* reply;
|
||||||
|
status_t error = AllocateRequest(allocator, &reply);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
reply->error = result;
|
||||||
|
|
||||||
|
// send the reply
|
||||||
|
return fPort->SendRequest(&allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// _GetVolume
|
// _GetVolume
|
||||||
status_t
|
status_t
|
||||||
KernelRequestHandler::_GetVolume(dev_t id, Volume** volume)
|
KernelRequestHandler::_GetVolume(dev_t id, Volume** volume)
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ private:
|
|||||||
status_t _HandleRequest(FileCacheSyncRequest* request);
|
status_t _HandleRequest(FileCacheSyncRequest* request);
|
||||||
status_t _HandleRequest(FileCacheReadRequest* request);
|
status_t _HandleRequest(FileCacheReadRequest* request);
|
||||||
status_t _HandleRequest(FileCacheWriteRequest* request);
|
status_t _HandleRequest(FileCacheWriteRequest* request);
|
||||||
|
// I/O
|
||||||
|
status_t _HandleRequest(DoIterativeFDIORequest* request);
|
||||||
|
|
||||||
status_t _GetVolume(dev_t id, Volume** volume);
|
status_t _GetVolume(dev_t id, Volume** volume);
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#include <util/AutoLock.h>
|
#include <util/AutoLock.h>
|
||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
#include <fs/fd.h> // kernel private
|
||||||
|
|
||||||
#include "Compatibility.h"
|
#include "Compatibility.h"
|
||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
@@ -75,7 +77,7 @@ struct Volume::VNodeHashDefinition {
|
|||||||
{ return (uint32)key ^ (uint32)(key >> 32); }
|
{ return (uint32)key ^ (uint32)(key >> 32); }
|
||||||
size_t Hash(const VNode* value) const
|
size_t Hash(const VNode* value) const
|
||||||
{ return HashKey(value->id); }
|
{ return HashKey(value->id); }
|
||||||
bool Compare(ino_t key, VNode* value) const
|
bool Compare(ino_t key, const VNode* value) const
|
||||||
{ return value->id == key; }
|
{ return value->id == key; }
|
||||||
HashTableLink<VNode>* GetLink(VNode* value) const
|
HashTableLink<VNode>* GetLink(VNode* value) const
|
||||||
{ return value; }
|
{ return value; }
|
||||||
@@ -88,6 +90,90 @@ struct Volume::VNodeMap
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IORequestInfo
|
||||||
|
struct Volume::IORequestInfo {
|
||||||
|
io_request* request;
|
||||||
|
int32 id;
|
||||||
|
|
||||||
|
HashTableLink<IORequestInfo> idLink;
|
||||||
|
HashTableLink<IORequestInfo> structLink;
|
||||||
|
|
||||||
|
IORequestInfo(io_request* request, int32 id)
|
||||||
|
:
|
||||||
|
request(request),
|
||||||
|
id(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IORequestIDHashDefinition
|
||||||
|
struct Volume::IORequestIDHashDefinition {
|
||||||
|
typedef int32 KeyType;
|
||||||
|
typedef IORequestInfo ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(int32 key) const
|
||||||
|
{ return key; }
|
||||||
|
size_t Hash(const IORequestInfo* value) const
|
||||||
|
{ return HashKey(value->id); }
|
||||||
|
bool Compare(int32 key, const IORequestInfo* value) const
|
||||||
|
{ return value->id == key; }
|
||||||
|
HashTableLink<IORequestInfo>* GetLink(IORequestInfo* value) const
|
||||||
|
{ return &value->idLink; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IORequestStructHashDefinition
|
||||||
|
struct Volume::IORequestStructHashDefinition {
|
||||||
|
typedef io_request* KeyType;
|
||||||
|
typedef IORequestInfo ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(io_request* key) const
|
||||||
|
{ return (size_t)(addr_t)key; }
|
||||||
|
size_t Hash(const IORequestInfo* value) const
|
||||||
|
{ return HashKey(value->request); }
|
||||||
|
bool Compare(io_request* key, const IORequestInfo* value) const
|
||||||
|
{ return value->request == key; }
|
||||||
|
HashTableLink<IORequestInfo>* GetLink(IORequestInfo* value) const
|
||||||
|
{ return &value->structLink; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IORequestIDMap
|
||||||
|
struct Volume::IORequestIDMap
|
||||||
|
: public OpenHashTable<IORequestIDHashDefinition> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IORequestStructMap
|
||||||
|
struct Volume::IORequestStructMap
|
||||||
|
: public OpenHashTable<IORequestStructHashDefinition> {
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IterativeFDIOCookie
|
||||||
|
struct Volume::IterativeFDIOCookie : public Referenceable {
|
||||||
|
Volume* volume;
|
||||||
|
int fd;
|
||||||
|
int32 requestID;
|
||||||
|
void* clientCookie;
|
||||||
|
const file_io_vec* vecs;
|
||||||
|
uint32 vecCount;
|
||||||
|
|
||||||
|
IterativeFDIOCookie(Volume* volume, int fd, int32 requestID,
|
||||||
|
void* clientCookie, const file_io_vec* vecs, uint32 vecCount)
|
||||||
|
:
|
||||||
|
volume(volume),
|
||||||
|
fd(fd),
|
||||||
|
requestID(requestID),
|
||||||
|
clientCookie(clientCookie),
|
||||||
|
vecs(vecs),
|
||||||
|
vecCount(vecCount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// AutoIncrementer
|
// AutoIncrementer
|
||||||
class Volume::AutoIncrementer {
|
class Volume::AutoIncrementer {
|
||||||
public:
|
public:
|
||||||
@@ -113,9 +199,38 @@ private:
|
|||||||
vint32* fVariable;
|
vint32* fVariable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// IORequestRemover
|
||||||
|
class Volume::IORequestRemover {
|
||||||
|
public:
|
||||||
|
IORequestRemover(Volume* volume, int32 requestID)
|
||||||
|
:
|
||||||
|
fVolume(volume),
|
||||||
|
fRequestID(requestID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~IORequestRemover()
|
||||||
|
{
|
||||||
|
if (fVolume != NULL)
|
||||||
|
fVolume->_UnregisterIORequest(fRequestID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Detach()
|
||||||
|
{
|
||||||
|
fVolume = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Volume* fVolume;
|
||||||
|
int32 fRequestID;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
Volume::Volume(FileSystem* fileSystem, fs_volume* fsVolume)
|
Volume::Volume(FileSystem* fileSystem, fs_volume* fsVolume)
|
||||||
: Referenceable(true),
|
:
|
||||||
|
Referenceable(true),
|
||||||
fFileSystem(fileSystem),
|
fFileSystem(fileSystem),
|
||||||
fFSVolume(fsVolume),
|
fFSVolume(fsVolume),
|
||||||
fUserlandVolume(NULL),
|
fUserlandVolume(NULL),
|
||||||
@@ -128,19 +243,26 @@ Volume::Volume(FileSystem* fileSystem, fs_volume* fsVolume)
|
|||||||
fOpenIndexDirectories(0),
|
fOpenIndexDirectories(0),
|
||||||
fOpenQueries(0),
|
fOpenQueries(0),
|
||||||
fVNodes(NULL),
|
fVNodes(NULL),
|
||||||
|
fIORequestInfosByID(NULL),
|
||||||
|
fIORequestInfosByStruct(NULL),
|
||||||
|
fLastIORequestID(0),
|
||||||
fVNodeCountingEnabled(false)
|
fVNodeCountingEnabled(false)
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, "userlandfs volume");
|
mutex_init(&fLock, "userlandfs volume");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// destructor
|
// destructor
|
||||||
Volume::~Volume()
|
Volume::~Volume()
|
||||||
{
|
{
|
||||||
mutex_destroy(&fLock);
|
mutex_destroy(&fLock);
|
||||||
|
|
||||||
|
delete fIORequestInfosByID;
|
||||||
|
delete fIORequestInfosByStruct;
|
||||||
delete fVNodes;
|
delete fVNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GetFileSystem
|
// GetFileSystem
|
||||||
FileSystem*
|
FileSystem*
|
||||||
Volume::GetFileSystem() const
|
Volume::GetFileSystem() const
|
||||||
@@ -481,6 +603,48 @@ Volume::WriteFileCache(ino_t vnodeID, void* cookie,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// DoIterativeFDIO
|
||||||
|
status_t
|
||||||
|
Volume::DoIterativeFDIO(int fd, int32 requestID, void* clientCookie,
|
||||||
|
const file_io_vec* vecs, uint32 vecCount)
|
||||||
|
{
|
||||||
|
// get the request
|
||||||
|
io_request* request;
|
||||||
|
status_t error = _FindIORequest(requestID, &request);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
|
||||||
|
// copy the FD into the kernel
|
||||||
|
fd = dup_foreign_fd(fFileSystem->GetTeam(), fd, true);
|
||||||
|
if (fd < 0)
|
||||||
|
RETURN_ERROR(fd);
|
||||||
|
|
||||||
|
// create a cookie
|
||||||
|
IterativeFDIOCookie* cookie = new(std::nothrow) IterativeFDIOCookie(
|
||||||
|
this, fd, requestID, clientCookie, vecs, vecCount);
|
||||||
|
if (cookie == NULL) {
|
||||||
|
close(fd);
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need another reference, so we can still access the cookie below
|
||||||
|
cookie->AddReference();
|
||||||
|
|
||||||
|
// call the kernel function
|
||||||
|
error = do_iterative_fd_io(fd, request, &_IterativeFDIOGetVecs,
|
||||||
|
&_IterativeFDIOFinished, cookie);
|
||||||
|
|
||||||
|
// unset the vecs -- they are on the stack an will become invalid when we
|
||||||
|
// return
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
cookie->vecs = NULL;
|
||||||
|
cookie->vecCount = 0;
|
||||||
|
cookie->RemoveReference();
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - FS
|
// #pragma mark - FS
|
||||||
|
|
||||||
|
|
||||||
@@ -488,20 +652,27 @@ Volume::WriteFileCache(ino_t vnodeID, void* cookie,
|
|||||||
status_t
|
status_t
|
||||||
Volume::Mount(const char* device, uint32 flags, const char* parameters)
|
Volume::Mount(const char* device, uint32 flags, const char* parameters)
|
||||||
{
|
{
|
||||||
// create the vnode map
|
// create the maps
|
||||||
fVNodes = new(std::nothrow) VNodeMap;
|
fVNodes = new(std::nothrow) VNodeMap;
|
||||||
if (fVNodes == NULL)
|
fIORequestInfosByID = new(std::nothrow) IORequestIDMap;
|
||||||
return B_NO_MEMORY;
|
fIORequestInfosByStruct = new(std::nothrow) IORequestStructMap;
|
||||||
|
|
||||||
status_t error = fVNodes->Init();
|
if (fVNodes == NULL || fIORequestInfosByID == NULL
|
||||||
if (error != B_OK)
|
|| fIORequestInfosByStruct == NULL
|
||||||
return error;
|
|| fVNodes->Init() != B_OK
|
||||||
|
|| fIORequestInfosByID->Init() != B_OK
|
||||||
|
|| fIORequestInfosByStruct->Init() != B_OK) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
// enable vnode counting
|
// enable vnode counting
|
||||||
fVNodeCountingEnabled = true;
|
fVNodeCountingEnabled = true;
|
||||||
|
|
||||||
|
// init IORequest ID's
|
||||||
|
fLastIORequestID = 0;
|
||||||
|
|
||||||
// mount
|
// mount
|
||||||
error = _Mount(device, flags, parameters);
|
status_t error = _Mount(device, flags, parameters);
|
||||||
|
|
||||||
if (error == B_OK) {
|
if (error == B_OK) {
|
||||||
MutexLocker locker(fLock);
|
MutexLocker locker(fLock);
|
||||||
@@ -533,10 +704,12 @@ Volume::Unmount()
|
|||||||
{
|
{
|
||||||
status_t error = _Unmount();
|
status_t error = _Unmount();
|
||||||
|
|
||||||
// free the memory associated with the vnode map
|
// free the memory associated with the maps
|
||||||
if (fVNodes != NULL) {
|
{
|
||||||
|
// vnodes
|
||||||
MutexLocker _(fLock);
|
MutexLocker _(fLock);
|
||||||
VNode* node = fVNodes->Clear();
|
if (fVNodes != NULL) {
|
||||||
|
VNode* node = fVNodes->Clear(true);
|
||||||
while (node != NULL) {
|
while (node != NULL) {
|
||||||
VNode* nextNode = node->fNext;
|
VNode* nextNode = node->fNext;
|
||||||
delete node;
|
delete node;
|
||||||
@@ -546,6 +719,25 @@ Volume::Unmount()
|
|||||||
fVNodes = NULL;
|
fVNodes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// io request infos
|
||||||
|
if (fIORequestInfosByID != NULL) {
|
||||||
|
fIORequestInfosByID->Clear();
|
||||||
|
delete fIORequestInfosByID;
|
||||||
|
fIORequestInfosByID = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fIORequestInfosByStruct != NULL) {
|
||||||
|
IORequestInfo* info = fIORequestInfosByStruct->Clear(true);
|
||||||
|
while (info != NULL) {
|
||||||
|
IORequestInfo* nextInfo = info->structLink.fNext;
|
||||||
|
delete info;
|
||||||
|
info = nextInfo;
|
||||||
|
}
|
||||||
|
delete fIORequestInfosByStruct;
|
||||||
|
fIORequestInfosByStruct = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fFileSystem->VolumeUnmounted(this);
|
fFileSystem->VolumeUnmounted(this);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@@ -837,6 +1029,119 @@ Volume::RemoveVNode(void* _node, bool reenter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - asynchronous I/O
|
||||||
|
|
||||||
|
|
||||||
|
// DoIO
|
||||||
|
status_t
|
||||||
|
Volume::DoIO(void* _node, void* cookie, io_request* ioRequest)
|
||||||
|
{
|
||||||
|
VNode* vnode = (VNode*)_node;
|
||||||
|
|
||||||
|
// check capability
|
||||||
|
if (!HasVNodeCapability(vnode, FS_VNODE_CAPABILITY_IO))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// register the IO request
|
||||||
|
int32 requestID;
|
||||||
|
status_t error = _RegisterIORequest(ioRequest, &requestID);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
IORequestRemover requestRemover(this, requestID);
|
||||||
|
|
||||||
|
// get a free port
|
||||||
|
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||||
|
if (!port)
|
||||||
|
return B_ERROR;
|
||||||
|
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||||
|
|
||||||
|
// prepare the request
|
||||||
|
RequestAllocator allocator(port->GetPort());
|
||||||
|
DoIORequest* request;
|
||||||
|
error = AllocateRequest(allocator, &request);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
request->volume = fUserlandVolume;
|
||||||
|
request->node = vnode->clientNode;
|
||||||
|
request->fileCookie = cookie;
|
||||||
|
request->request = requestID;
|
||||||
|
|
||||||
|
// send the request
|
||||||
|
KernelRequestHandler handler(this, DO_IO_REPLY);
|
||||||
|
DoIOReply* reply;
|
||||||
|
error = _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;
|
||||||
|
|
||||||
|
requestRemover.Detach();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// CancelIO
|
||||||
|
status_t
|
||||||
|
Volume::CancelIO(void* _node, void* cookie, io_request* ioRequest)
|
||||||
|
{
|
||||||
|
VNode* vnode = (VNode*)_node;
|
||||||
|
|
||||||
|
// check capability
|
||||||
|
if (!HasVNodeCapability(vnode, FS_VNODE_CAPABILITY_CANCEL_IO))
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// find the request
|
||||||
|
int32 requestID;
|
||||||
|
status_t error = _FindIORequest(ioRequest, &requestID);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
IORequestRemover requestRemover(this, requestID);
|
||||||
|
|
||||||
|
// get a free port
|
||||||
|
RequestPort* port = fFileSystem->GetPortPool()->AcquirePort();
|
||||||
|
if (!port)
|
||||||
|
return B_ERROR;
|
||||||
|
PortReleaser _(fFileSystem->GetPortPool(), port);
|
||||||
|
|
||||||
|
// prepare the request
|
||||||
|
RequestAllocator allocator(port->GetPort());
|
||||||
|
CancelIORequest* request;
|
||||||
|
error = AllocateRequest(allocator, &request);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
request->volume = fUserlandVolume;
|
||||||
|
request->node = vnode->clientNode;
|
||||||
|
request->fileCookie = cookie;
|
||||||
|
request->request = requestID;
|
||||||
|
|
||||||
|
// send the request
|
||||||
|
KernelRequestHandler handler(this, CANCEL_IO_REPLY);
|
||||||
|
CancelIOReply* reply;
|
||||||
|
error = _SendRequest(port, &allocator, &handler, (Request**)&reply);
|
||||||
|
if (error != B_OK) {
|
||||||
|
_UnregisterIORequest(requestID);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
RequestReleaser requestReleaser(port, reply);
|
||||||
|
|
||||||
|
// process the reply
|
||||||
|
if (reply->error != B_OK) {
|
||||||
|
_UnregisterIORequest(requestID);
|
||||||
|
return reply->error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - nodes
|
// #pragma mark - nodes
|
||||||
|
|
||||||
|
|
||||||
@@ -4026,3 +4331,93 @@ PRINT(("Volume::_PutAllPendingVNodes()\n"));
|
|||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _RegisterIORequest
|
||||||
|
status_t
|
||||||
|
Volume::_RegisterIORequest(io_request* request, int32* requestID)
|
||||||
|
{
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
// get the next free ID
|
||||||
|
while (fIORequestInfosByID->Lookup(++fLastIORequestID) != NULL) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate the info
|
||||||
|
IORequestInfo* info = new(std::nothrow) IORequestInfo(request,
|
||||||
|
++fLastIORequestID);
|
||||||
|
if (info == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
// add the info to the maps
|
||||||
|
fIORequestInfosByID->Insert(info);
|
||||||
|
fIORequestInfosByStruct->Insert(info);
|
||||||
|
|
||||||
|
*requestID = info->id;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _UnregisterIORequest
|
||||||
|
status_t
|
||||||
|
Volume::_UnregisterIORequest(int32 requestID)
|
||||||
|
{
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
if (IORequestInfo* info = fIORequestInfosByID->Lookup(requestID)) {
|
||||||
|
fIORequestInfosByID->Remove(info);
|
||||||
|
fIORequestInfosByStruct->Remove(info);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _FindIORequest
|
||||||
|
status_t
|
||||||
|
Volume::_FindIORequest(int32 requestID, io_request** request)
|
||||||
|
{
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
if (IORequestInfo* info = fIORequestInfosByID->Lookup(requestID)) {
|
||||||
|
*request = info->request;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// _FindIORequest
|
||||||
|
status_t
|
||||||
|
Volume::_FindIORequest(io_request* request, int32* requestID)
|
||||||
|
{
|
||||||
|
MutexLocker _(fLock);
|
||||||
|
|
||||||
|
if (IORequestInfo* info = fIORequestInfosByStruct->Lookup(request)) {
|
||||||
|
*requestID = info->id;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
Volume::_IterativeFDIOGetVecs(void* cookie, io_request* request, off_t offset,
|
||||||
|
size_t size, struct file_io_vec* vecs, size_t* _count)
|
||||||
|
{
|
||||||
|
// TODO: Implement!
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
Volume::_IterativeFDIOFinished(void* cookie, io_request* request,
|
||||||
|
status_t status, bool partialTransfer, size_t bytesTransferred)
|
||||||
|
{
|
||||||
|
// TODO: Implement!
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ public:
|
|||||||
off_t offset, const void* buffer,
|
off_t offset, const void* buffer,
|
||||||
size_t* _size);
|
size_t* _size);
|
||||||
|
|
||||||
|
status_t DoIterativeFDIO(int fd, int32 requestID,
|
||||||
|
void* cookie, const file_io_vec* vecs,
|
||||||
|
uint32 vecCount);
|
||||||
|
|
||||||
// FS
|
// FS
|
||||||
status_t Mount(const char* device, uint32 flags,
|
status_t Mount(const char* device, uint32 flags,
|
||||||
const char* parameters);
|
const char* parameters);
|
||||||
@@ -88,6 +92,12 @@ public:
|
|||||||
status_t WriteVNode(void* node, bool reenter);
|
status_t WriteVNode(void* node, bool reenter);
|
||||||
status_t RemoveVNode(void* node, bool reenter);
|
status_t RemoveVNode(void* node, bool reenter);
|
||||||
|
|
||||||
|
// asynchronous I/O
|
||||||
|
status_t DoIO(void* node, void* cookie,
|
||||||
|
io_request* ioRequest);
|
||||||
|
status_t CancelIO(void* node, void* cookie,
|
||||||
|
io_request* ioRequest);
|
||||||
|
|
||||||
// nodes
|
// nodes
|
||||||
status_t IOCtl(void* node, void* cookie,
|
status_t IOCtl(void* node, void* cookie,
|
||||||
uint32 command, void *buffer, size_t size);
|
uint32 command, void *buffer, size_t size);
|
||||||
@@ -205,8 +215,16 @@ private:
|
|||||||
struct VNode;
|
struct VNode;
|
||||||
struct VNodeHashDefinition;
|
struct VNodeHashDefinition;
|
||||||
struct VNodeMap;
|
struct VNodeMap;
|
||||||
|
struct IORequestInfo;
|
||||||
|
struct IORequestIDHashDefinition;
|
||||||
|
struct IORequestStructHashDefinition;
|
||||||
|
struct IORequestIDMap;
|
||||||
|
struct IORequestStructMap;
|
||||||
|
struct IterativeFDIOCookie;
|
||||||
|
|
||||||
class AutoIncrementer;
|
class AutoIncrementer;
|
||||||
|
class IORequestRemover;
|
||||||
|
friend class IORequestRemover;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _Mount(const char* device, uint32 flags,
|
status_t _Mount(const char* device, uint32 flags,
|
||||||
@@ -245,6 +263,23 @@ private:
|
|||||||
|
|
||||||
status_t _PutAllPendingVNodes();
|
status_t _PutAllPendingVNodes();
|
||||||
|
|
||||||
|
status_t _RegisterIORequest(io_request* request,
|
||||||
|
int32* requestID);
|
||||||
|
status_t _UnregisterIORequest(int32 requestID);
|
||||||
|
status_t _FindIORequest(io_request* request,
|
||||||
|
int32* requestID);
|
||||||
|
status_t _FindIORequest(int32 requestID,
|
||||||
|
io_request** request);
|
||||||
|
|
||||||
|
static status_t _IterativeFDIOGetVecs(void* cookie,
|
||||||
|
io_request* request, off_t offset,
|
||||||
|
size_t size, struct file_io_vec* vecs,
|
||||||
|
size_t* _count);
|
||||||
|
static status_t _IterativeFDIOFinished(void* cookie,
|
||||||
|
io_request* request, status_t status,
|
||||||
|
bool partialTransfer,
|
||||||
|
size_t bytesTransferred);
|
||||||
|
|
||||||
inline bool HasVNodeCapability(VNode* vnode,
|
inline bool HasVNodeCapability(VNode* vnode,
|
||||||
int capability) const;
|
int capability) const;
|
||||||
|
|
||||||
@@ -263,6 +298,9 @@ private:
|
|||||||
vint32 fOpenIndexDirectories;
|
vint32 fOpenIndexDirectories;
|
||||||
vint32 fOpenQueries;
|
vint32 fOpenQueries;
|
||||||
VNodeMap* fVNodes;
|
VNodeMap* fVNodes;
|
||||||
|
IORequestIDMap* fIORequestInfosByID;
|
||||||
|
IORequestStructMap* fIORequestInfosByStruct;
|
||||||
|
int32 fLastIORequestID;
|
||||||
volatile bool fVNodeCountingEnabled;
|
volatile bool fVNodeCountingEnabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -248,25 +248,35 @@ userlandfs_remove_vnode(fs_volume* fsVolume, fs_vnode* fsNode, bool reenter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - VM file access
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: userlandfs_can_page()
|
|
||||||
// TODO: userlandfs_read_pages()
|
|
||||||
// TODO: userlandfs_write_pages()
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - asynchronous I/O
|
// #pragma mark - asynchronous I/O
|
||||||
|
|
||||||
|
|
||||||
// TODO: userlandfs_io()
|
// userlandfs_io
|
||||||
// TODO: userlandfs_cancel_io()
|
status_t
|
||||||
|
userlandfs_io(fs_volume* fsVolume, fs_vnode* fsNode, void* cookie,
|
||||||
|
io_request* request)
|
||||||
|
{
|
||||||
|
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||||
|
PRINT(("userlandfs_io(%p, %p, %p, %p)\n", volume, fsNode->private_node,
|
||||||
|
cookie, request));
|
||||||
|
status_t error = volume->DoIO(fsNode->private_node, cookie, request);
|
||||||
|
PRINT(("userlandfs_io() done: (%lx)\n", error));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - cache file access
|
// userlandfs_cancel_io
|
||||||
|
status_t
|
||||||
|
userlandfs_cancel_io(fs_volume* fsVolume, fs_vnode* fsNode, void *cookie,
|
||||||
// TODO: userlandfs_get_file_map()
|
io_request *request)
|
||||||
|
{
|
||||||
|
Volume* volume = (Volume*)fsVolume->private_volume;
|
||||||
|
PRINT(("userlandfs_cancel_io(%p, %p, %p, %p)\n", volume,
|
||||||
|
fsNode->private_node, cookie, request));
|
||||||
|
status_t error = volume->CancelIO(fsNode->private_node, cookie, request);
|
||||||
|
PRINT(("userlandfs_cancel_io() done: (%lx)\n", error));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - common
|
// #pragma mark - common
|
||||||
@@ -1169,16 +1179,16 @@ fs_vnode_ops gUserlandFSVnodeOps = {
|
|||||||
&userlandfs_remove_vnode,
|
&userlandfs_remove_vnode,
|
||||||
|
|
||||||
// VM file access
|
// VM file access
|
||||||
NULL, // &userlandfs_can_page,
|
NULL, // can_page() -- obsolete
|
||||||
NULL, // &userlandfs_read_pages,
|
NULL, // read_pages() -- obsolete
|
||||||
NULL, // &userlandfs_write_pages,
|
NULL, // write_pages() -- obsolete
|
||||||
|
|
||||||
// asynchronous I/O
|
// asynchronous I/O
|
||||||
NULL, // &userlandfs_io
|
&userlandfs_io,
|
||||||
NULL, // &userlandfs_cancel_io
|
&userlandfs_cancel_io,
|
||||||
|
|
||||||
// cache file access
|
// cache file access
|
||||||
NULL, // &userlandfs_get_file_map
|
NULL, // get_file_map() -- not needed
|
||||||
|
|
||||||
// common operations
|
// common operations
|
||||||
&userlandfs_ioctl,
|
&userlandfs_ioctl,
|
||||||
|
|||||||
@@ -14,14 +14,18 @@
|
|||||||
|
|
||||||
namespace UserlandFS {
|
namespace UserlandFS {
|
||||||
|
|
||||||
|
class HaikuKernelVolume;
|
||||||
|
|
||||||
struct HaikuKernelIORequest : HashTableLink<HaikuKernelIORequest>,
|
struct HaikuKernelIORequest : HashTableLink<HaikuKernelIORequest>,
|
||||||
IORequestInfo {
|
IORequestInfo {
|
||||||
|
|
||||||
|
HaikuKernelVolume* volume;
|
||||||
int32 refCount;
|
int32 refCount;
|
||||||
|
|
||||||
HaikuKernelIORequest(const IORequestInfo& info)
|
HaikuKernelIORequest(HaikuKernelVolume* volume, const IORequestInfo& info)
|
||||||
:
|
:
|
||||||
IORequestInfo(info),
|
IORequestInfo(info),
|
||||||
|
volume(volume),
|
||||||
refCount(1)
|
refCount(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ HaikuKernelVolume::DoIO(void* _node, void* cookie,
|
|||||||
|
|
||||||
// create a request object
|
// create a request object
|
||||||
HaikuKernelIORequest* request
|
HaikuKernelIORequest* request
|
||||||
= new(std::nothrow) HaikuKernelIORequest(requestInfo);
|
= new(std::nothrow) HaikuKernelIORequest(this, requestInfo);
|
||||||
if (request == NULL)
|
if (request == NULL)
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
|||||||
@@ -296,8 +296,8 @@ 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(fd, request->id,
|
status_t error = UserlandFS::KernelEmu::do_iterative_fd_io(
|
||||||
cookie, NULL, 0);
|
request->volume->GetID(), fd, request->id, cookie, NULL, 0);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
delete cookie;
|
delete cookie;
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
@@ -841,8 +841,8 @@ UserlandFS::KernelEmu::file_cache_write(dev_t mountID, ino_t vnodeID,
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
UserlandFS::KernelEmu::do_iterative_fd_io(int fd, int32 requestID, void* cookie,
|
UserlandFS::KernelEmu::do_iterative_fd_io(dev_t volumeID, int fd,
|
||||||
const file_io_vec* vecs, uint32 vecCount)
|
int32 requestID, void* cookie, const file_io_vec* vecs, uint32 vecCount)
|
||||||
{
|
{
|
||||||
// get the request port and the file system
|
// get the request port and the file system
|
||||||
RequestPort* port;
|
RequestPort* port;
|
||||||
@@ -858,6 +858,7 @@ UserlandFS::KernelEmu::do_iterative_fd_io(int fd, int32 requestID, void* cookie,
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
request->nsid = volumeID;
|
||||||
request->fd = fd;
|
request->fd = fd;
|
||||||
request->request = requestID;
|
request->request = requestID;
|
||||||
request->cookie = cookie;
|
request->cookie = cookie;
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ status_t file_cache_read(dev_t mountID, ino_t vnodeID, void *cookie,
|
|||||||
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);
|
off_t offset, const void *buffer, size_t *_size);
|
||||||
|
|
||||||
status_t do_iterative_fd_io(int fd, int32 requestID, void* cookie,
|
status_t do_iterative_fd_io(dev_t volumeID, int fd, int32 requestID,
|
||||||
const file_io_vec* vecs, uint32 vecCount);
|
void* cookie, const file_io_vec* vecs, uint32 vecCount);
|
||||||
|
|
||||||
void kernel_debugger(const char *message);
|
void kernel_debugger(const char *message);
|
||||||
void vpanic(const char *format, va_list args);
|
void vpanic(const char *format, va_list args);
|
||||||
|
|||||||
Reference in New Issue
Block a user