* 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) {}
|
||||
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
||||
|
||||
dev_t nsid;
|
||||
int fd;
|
||||
int32 request;
|
||||
void* cookie;
|
||||
|
||||
@@ -100,6 +100,9 @@ KernelRequestHandler::HandleRequest(Request* request)
|
||||
return _HandleRequest((FileCacheReadRequest*)request);
|
||||
case FILE_CACHE_WRITE_REQUEST:
|
||||
return _HandleRequest((FileCacheWriteRequest*)request);
|
||||
// I/O
|
||||
case DO_ITERATIVE_FD_IO_REQUEST:
|
||||
return _HandleRequest((DoIterativeFDIORequest*)request);
|
||||
}
|
||||
PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %lu\n",
|
||||
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
|
||||
status_t
|
||||
KernelRequestHandler::_GetVolume(dev_t id, Volume** volume)
|
||||
|
||||
@@ -73,6 +73,8 @@ private:
|
||||
status_t _HandleRequest(FileCacheSyncRequest* request);
|
||||
status_t _HandleRequest(FileCacheReadRequest* request);
|
||||
status_t _HandleRequest(FileCacheWriteRequest* request);
|
||||
// I/O
|
||||
status_t _HandleRequest(DoIterativeFDIORequest* request);
|
||||
|
||||
status_t _GetVolume(dev_t id, Volume** volume);
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <util/AutoLock.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
|
||||
#include <fs/fd.h> // kernel private
|
||||
|
||||
#include "Compatibility.h"
|
||||
#include "Debug.h"
|
||||
#include "FileSystem.h"
|
||||
@@ -75,7 +77,7 @@ struct Volume::VNodeHashDefinition {
|
||||
{ return (uint32)key ^ (uint32)(key >> 32); }
|
||||
size_t Hash(const VNode* value) const
|
||||
{ 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; }
|
||||
HashTableLink<VNode>* GetLink(VNode* value) const
|
||||
{ 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
|
||||
class Volume::AutoIncrementer {
|
||||
public:
|
||||
@@ -113,34 +199,70 @@ private:
|
||||
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
|
||||
Volume::Volume(FileSystem* fileSystem, fs_volume* fsVolume)
|
||||
: Referenceable(true),
|
||||
fFileSystem(fileSystem),
|
||||
fFSVolume(fsVolume),
|
||||
fUserlandVolume(NULL),
|
||||
fRootID(0),
|
||||
fRootNode(NULL),
|
||||
fOpenFiles(0),
|
||||
fOpenDirectories(0),
|
||||
fOpenAttributeDirectories(0),
|
||||
fOpenAttributes(0),
|
||||
fOpenIndexDirectories(0),
|
||||
fOpenQueries(0),
|
||||
fVNodes(NULL),
|
||||
fVNodeCountingEnabled(false)
|
||||
:
|
||||
Referenceable(true),
|
||||
fFileSystem(fileSystem),
|
||||
fFSVolume(fsVolume),
|
||||
fUserlandVolume(NULL),
|
||||
fRootID(0),
|
||||
fRootNode(NULL),
|
||||
fOpenFiles(0),
|
||||
fOpenDirectories(0),
|
||||
fOpenAttributeDirectories(0),
|
||||
fOpenAttributes(0),
|
||||
fOpenIndexDirectories(0),
|
||||
fOpenQueries(0),
|
||||
fVNodes(NULL),
|
||||
fIORequestInfosByID(NULL),
|
||||
fIORequestInfosByStruct(NULL),
|
||||
fLastIORequestID(0),
|
||||
fVNodeCountingEnabled(false)
|
||||
{
|
||||
mutex_init(&fLock, "userlandfs volume");
|
||||
}
|
||||
|
||||
|
||||
// destructor
|
||||
Volume::~Volume()
|
||||
{
|
||||
mutex_destroy(&fLock);
|
||||
|
||||
delete fIORequestInfosByID;
|
||||
delete fIORequestInfosByStruct;
|
||||
delete fVNodes;
|
||||
}
|
||||
|
||||
|
||||
// GetFileSystem
|
||||
FileSystem*
|
||||
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
|
||||
|
||||
|
||||
@@ -488,20 +652,27 @@ Volume::WriteFileCache(ino_t vnodeID, void* cookie,
|
||||
status_t
|
||||
Volume::Mount(const char* device, uint32 flags, const char* parameters)
|
||||
{
|
||||
// create the vnode map
|
||||
// create the maps
|
||||
fVNodes = new(std::nothrow) VNodeMap;
|
||||
if (fVNodes == NULL)
|
||||
return B_NO_MEMORY;
|
||||
fIORequestInfosByID = new(std::nothrow) IORequestIDMap;
|
||||
fIORequestInfosByStruct = new(std::nothrow) IORequestStructMap;
|
||||
|
||||
status_t error = fVNodes->Init();
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
if (fVNodes == NULL || fIORequestInfosByID == NULL
|
||||
|| fIORequestInfosByStruct == NULL
|
||||
|| fVNodes->Init() != B_OK
|
||||
|| fIORequestInfosByID->Init() != B_OK
|
||||
|| fIORequestInfosByStruct->Init() != B_OK) {
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
// enable vnode counting
|
||||
fVNodeCountingEnabled = true;
|
||||
|
||||
// init IORequest ID's
|
||||
fLastIORequestID = 0;
|
||||
|
||||
// mount
|
||||
error = _Mount(device, flags, parameters);
|
||||
status_t error = _Mount(device, flags, parameters);
|
||||
|
||||
if (error == B_OK) {
|
||||
MutexLocker locker(fLock);
|
||||
@@ -533,17 +704,38 @@ Volume::Unmount()
|
||||
{
|
||||
status_t error = _Unmount();
|
||||
|
||||
// free the memory associated with the vnode map
|
||||
if (fVNodes != NULL) {
|
||||
// free the memory associated with the maps
|
||||
{
|
||||
// vnodes
|
||||
MutexLocker _(fLock);
|
||||
VNode* node = fVNodes->Clear();
|
||||
while (node != NULL) {
|
||||
VNode* nextNode = node->fNext;
|
||||
delete node;
|
||||
node = nextNode;
|
||||
if (fVNodes != NULL) {
|
||||
VNode* node = fVNodes->Clear(true);
|
||||
while (node != NULL) {
|
||||
VNode* nextNode = node->fNext;
|
||||
delete node;
|
||||
node = nextNode;
|
||||
}
|
||||
delete fVNodes;
|
||||
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;
|
||||
}
|
||||
delete fVNodes;
|
||||
fVNodes = NULL;
|
||||
}
|
||||
|
||||
fFileSystem->VolumeUnmounted(this);
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -4026,3 +4331,93 @@ PRINT(("Volume::_PutAllPendingVNodes()\n"));
|
||||
|
||||
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,
|
||||
size_t* _size);
|
||||
|
||||
status_t DoIterativeFDIO(int fd, int32 requestID,
|
||||
void* cookie, const file_io_vec* vecs,
|
||||
uint32 vecCount);
|
||||
|
||||
// FS
|
||||
status_t Mount(const char* device, uint32 flags,
|
||||
const char* parameters);
|
||||
@@ -88,6 +92,12 @@ public:
|
||||
status_t WriteVNode(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
|
||||
status_t IOCtl(void* node, void* cookie,
|
||||
uint32 command, void *buffer, size_t size);
|
||||
@@ -205,8 +215,16 @@ private:
|
||||
struct VNode;
|
||||
struct VNodeHashDefinition;
|
||||
struct VNodeMap;
|
||||
struct IORequestInfo;
|
||||
struct IORequestIDHashDefinition;
|
||||
struct IORequestStructHashDefinition;
|
||||
struct IORequestIDMap;
|
||||
struct IORequestStructMap;
|
||||
struct IterativeFDIOCookie;
|
||||
|
||||
class AutoIncrementer;
|
||||
class IORequestRemover;
|
||||
friend class IORequestRemover;
|
||||
|
||||
private:
|
||||
status_t _Mount(const char* device, uint32 flags,
|
||||
@@ -245,6 +263,23 @@ private:
|
||||
|
||||
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,
|
||||
int capability) const;
|
||||
|
||||
@@ -263,6 +298,9 @@ private:
|
||||
vint32 fOpenIndexDirectories;
|
||||
vint32 fOpenQueries;
|
||||
VNodeMap* fVNodes;
|
||||
IORequestIDMap* fIORequestInfosByID;
|
||||
IORequestStructMap* fIORequestInfosByStruct;
|
||||
int32 fLastIORequestID;
|
||||
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
|
||||
|
||||
|
||||
// TODO: userlandfs_io()
|
||||
// TODO: userlandfs_cancel_io()
|
||||
// userlandfs_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
|
||||
|
||||
|
||||
// TODO: userlandfs_get_file_map()
|
||||
// userlandfs_cancel_io
|
||||
status_t
|
||||
userlandfs_cancel_io(fs_volume* fsVolume, fs_vnode* fsNode, void *cookie,
|
||||
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
|
||||
@@ -1169,16 +1179,16 @@ fs_vnode_ops gUserlandFSVnodeOps = {
|
||||
&userlandfs_remove_vnode,
|
||||
|
||||
// VM file access
|
||||
NULL, // &userlandfs_can_page,
|
||||
NULL, // &userlandfs_read_pages,
|
||||
NULL, // &userlandfs_write_pages,
|
||||
NULL, // can_page() -- obsolete
|
||||
NULL, // read_pages() -- obsolete
|
||||
NULL, // write_pages() -- obsolete
|
||||
|
||||
// asynchronous I/O
|
||||
NULL, // &userlandfs_io
|
||||
NULL, // &userlandfs_cancel_io
|
||||
&userlandfs_io,
|
||||
&userlandfs_cancel_io,
|
||||
|
||||
// cache file access
|
||||
NULL, // &userlandfs_get_file_map
|
||||
NULL, // get_file_map() -- not needed
|
||||
|
||||
// common operations
|
||||
&userlandfs_ioctl,
|
||||
|
||||
@@ -14,14 +14,18 @@
|
||||
|
||||
namespace UserlandFS {
|
||||
|
||||
class HaikuKernelVolume;
|
||||
|
||||
struct HaikuKernelIORequest : HashTableLink<HaikuKernelIORequest>,
|
||||
IORequestInfo {
|
||||
|
||||
int32 refCount;
|
||||
HaikuKernelVolume* volume;
|
||||
int32 refCount;
|
||||
|
||||
HaikuKernelIORequest(const IORequestInfo& info)
|
||||
HaikuKernelIORequest(HaikuKernelVolume* volume, const IORequestInfo& info)
|
||||
:
|
||||
IORequestInfo(info),
|
||||
volume(volume),
|
||||
refCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ HaikuKernelVolume::DoIO(void* _node, void* cookie,
|
||||
|
||||
// create a request object
|
||||
HaikuKernelIORequest* request
|
||||
= new(std::nothrow) HaikuKernelIORequest(requestInfo);
|
||||
= new(std::nothrow) HaikuKernelIORequest(this, requestInfo);
|
||||
if (request == NULL)
|
||||
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
|
||||
status_t error = UserlandFS::KernelEmu::do_iterative_fd_io(fd, request->id,
|
||||
cookie, NULL, 0);
|
||||
status_t error = UserlandFS::KernelEmu::do_iterative_fd_io(
|
||||
request->volume->GetID(), fd, request->id, cookie, NULL, 0);
|
||||
if (error != B_OK) {
|
||||
delete cookie;
|
||||
return error;
|
||||
|
||||
@@ -841,8 +841,8 @@ UserlandFS::KernelEmu::file_cache_write(dev_t mountID, ino_t vnodeID,
|
||||
|
||||
|
||||
status_t
|
||||
UserlandFS::KernelEmu::do_iterative_fd_io(int fd, int32 requestID, void* cookie,
|
||||
const file_io_vec* vecs, uint32 vecCount)
|
||||
UserlandFS::KernelEmu::do_iterative_fd_io(dev_t volumeID, int fd,
|
||||
int32 requestID, void* cookie, const file_io_vec* vecs, uint32 vecCount)
|
||||
{
|
||||
// get the request port and the file system
|
||||
RequestPort* port;
|
||||
@@ -858,6 +858,7 @@ UserlandFS::KernelEmu::do_iterative_fd_io(int fd, int32 requestID, void* cookie,
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
request->nsid = volumeID;
|
||||
request->fd = fd;
|
||||
request->request = requestID;
|
||||
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,
|
||||
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);
|
||||
status_t do_iterative_fd_io(dev_t volumeID, 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);
|
||||
|
||||
Reference in New Issue
Block a user