/*
* Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "Compatibility.h"
#include "Debug.h"
#include "FileSystem.h"
#include "KernelRequestHandler.h"
#include "RequestPort.h"
#include "Requests.h"
#include "SingleReplyRequestHandler.h"
#include "Volume.h"
#include <NodeMonitor.h>
#include <AutoDeleter.h>
// VolumePutter
class VolumePutter {
public:
VolumePutter(Volume* volume) : fVolume(volume) {}
~VolumePutter()
{
if (fVolume)
fVolume->ReleaseReference();
}
private:
Volume *fVolume;
};
// constructor
KernelRequestHandler::KernelRequestHandler(Volume* volume, uint32 expectedReply)
: RequestHandler(),
fFileSystem(volume->GetFileSystem()),
fVolume(volume),
fExpectedReply(expectedReply)
{
}
// constructor
KernelRequestHandler::KernelRequestHandler(FileSystem* fileSystem,
uint32 expectedReply)
: RequestHandler(),
fFileSystem(fileSystem),
fVolume(NULL),
fExpectedReply(expectedReply)
{
}
// destructor
KernelRequestHandler::~KernelRequestHandler()
{
}
// HandleRequest
status_t
KernelRequestHandler::HandleRequest(Request* request)
{
if (request->GetType() == fExpectedReply) {
fDone = true;
return B_OK;
}
switch (request->GetType()) {
// notifications
case NOTIFY_LISTENER_REQUEST:
return _HandleRequest((NotifyListenerRequest*)request);
case NOTIFY_SELECT_EVENT_REQUEST:
return _HandleRequest((NotifySelectEventRequest*)request);
case NOTIFY_QUERY_REQUEST:
return _HandleRequest((NotifyQueryRequest*)request);
// vnodes
case GET_VNODE_REQUEST:
return _HandleRequest((GetVNodeRequest*)request);
case PUT_VNODE_REQUEST:
return _HandleRequest((PutVNodeRequest*)request);
case ACQUIRE_VNODE_REQUEST:
return _HandleRequest((AcquireVNodeRequest*)request);
case NEW_VNODE_REQUEST:
return _HandleRequest((NewVNodeRequest*)request);
case PUBLISH_VNODE_REQUEST:
return _HandleRequest((PublishVNodeRequest*)request);
case REMOVE_VNODE_REQUEST:
return _HandleRequest((RemoveVNodeRequest*)request);
case UNREMOVE_VNODE_REQUEST:
return _HandleRequest((UnremoveVNodeRequest*)request);
case GET_VNODE_REMOVED_REQUEST:
return _HandleRequest((GetVNodeRemovedRequest*)request);
// file cache
case FILE_CACHE_CREATE_REQUEST:
return _HandleRequest((FileCacheCreateRequest*)request);
case FILE_CACHE_DELETE_REQUEST:
return _HandleRequest((FileCacheDeleteRequest*)request);
case FILE_CACHE_SET_ENABLED_REQUEST:
return _HandleRequest((FileCacheSetEnabledRequest*)request);
case FILE_CACHE_SET_SIZE_REQUEST:
return _HandleRequest((FileCacheSetSizeRequest*)request);
case FILE_CACHE_SYNC_REQUEST:
return _HandleRequest((FileCacheSyncRequest*)request);
case FILE_CACHE_READ_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);
case READ_FROM_IO_REQUEST_REQUEST:
return _HandleRequest((ReadFromIORequestRequest*)request);
case WRITE_TO_IO_REQUEST_REQUEST:
return _HandleRequest((WriteToIORequestRequest*)request);
case NOTIFY_IO_REQUEST_REQUEST:
return _HandleRequest((NotifyIORequestRequest*)request);
// node monitoring
case ADD_NODE_LISTENER_REQUEST:
return _HandleRequest((AddNodeListenerRequest*)request);
case REMOVE_NODE_LISTENER_REQUEST:
return _HandleRequest((RemoveNodeListenerRequest*)request);
}
PRINT(("KernelRequestHandler::HandleRequest(): unexpected request: %"
B_PRIu32 "\n", request->GetType()));
return B_BAD_DATA;
}
// #pragma mark -
// #pragma mark ----- notifications -----
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(NotifyListenerRequest* request)
{
// check and execute the request
status_t result = B_OK;
if (fVolume && request->device != fVolume->GetID())
result = B_BAD_VALUE;
// get the names
// name
char* name = (char*)request->name.GetData();
int32 nameLen = request->name.GetSize();
if (name && (nameLen <= 0))
name = NULL;
else if (name)
name[nameLen - 1] = '\0'; // NULL-terminate to be safe
// old name
char* oldName = (char*)request->oldName.GetData();
int32 oldNameLen = request->oldName.GetSize();
if (oldName && (oldNameLen <= 0))
oldName = NULL;
else if (oldName)
oldName[oldNameLen - 1] = '\0'; // NULL-terminate to be safe
// check the names
if (result == B_OK) {
switch (request->operation) {
case B_ENTRY_MOVED:
if (!oldName) {
ERROR(("NotifyListenerRequest: NULL oldName for "
"B_ENTRY_MOVED\n"));
result = B_BAD_VALUE;
break;
}
// fall through...
case B_ENTRY_CREATED:
case B_ENTRY_REMOVED:
case B_ATTR_CHANGED:
if (!name) {
ERROR(("NotifyListenerRequest: NULL name for opcode: %"
B_PRId32 "\n", request->operation));
result = B_BAD_VALUE;
}
break;
case B_STAT_CHANGED:
break;
}
}
// execute the request
if (result == B_OK) {
switch (request->operation) {
case B_ENTRY_CREATED:
PRINT(("notify_entry_created(%" B_PRId32 ", %" B_PRId64 ", "
"\"%s\", %" B_PRId64 ")\n", request->device,
request->directory, name, request->node));
result = notify_entry_created(request->device,
request->directory, name, request->node);
break;
case B_ENTRY_REMOVED:
PRINT(("notify_entry_removed(%" B_PRId32 ", %" B_PRId64 ", "
"\"%s\", %" B_PRId64 ")\n", request->device,
request->directory, name, request->node));
result = notify_entry_removed(request->device,
request->directory, name, request->node);
break;
case B_ENTRY_MOVED:
PRINT(("notify_entry_moved(%" B_PRId32 ", %" B_PRId64 ", "
"\"%s\", %" B_PRId64 ", \"%s\", %" B_PRId64 ")\n",
request->device, request->oldDirectory, oldName,
request->directory, name, request->node));
result = notify_entry_moved(request->device,
request->oldDirectory, oldName, request->directory, name,
request->node);
break;
case B_STAT_CHANGED:
PRINT(("notify_stat_changed(%" B_PRId32 ", %" B_PRId64 ", "
"0x%" B_PRIx32 ")\n", request->device, request->node,
request->details));
result = notify_stat_changed(request->device,
request->directory, request->node, request->details);
break;
case B_ATTR_CHANGED:
PRINT(("notify_attribute_changed(%" B_PRId32 ", %" B_PRId64 ", "
"\"%s\", 0x%" B_PRIx32 ")\n", request->device,
request->node, name, (int32)request->details));
result = notify_attribute_changed(request->device,
request->directory, request->node, name,
(int32)request->details);
break;
default:
ERROR(("NotifyQueryRequest: unsupported operation: %" B_PRId32
"\n", request->operation));
result = B_BAD_VALUE;
break;
}
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
NotifyListenerReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(NotifySelectEventRequest* request)
{
// check and execute the request
status_t result = B_OK;
if (fFileSystem->KnowsSelectSyncEntry(request->sync)) {
if (request->unspecifiedEvent) {
// old style add-ons can't provide an event argument; we shoot
// all events
notify_select_event(request->sync, B_SELECT_READ);
notify_select_event(request->sync, B_SELECT_WRITE);
notify_select_event(request->sync, B_SELECT_ERROR);
} else {
PRINT(("notify_select_event(%p, %d)\n", request->sync,
(int)request->event));
notify_select_event(request->sync, request->event);
}
} else
result = B_BAD_VALUE;
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
NotifySelectEventReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(NotifyQueryRequest* request)
{
// check and execute the request
status_t result = B_OK;
if (fVolume && request->device != fVolume->GetID())
result = B_BAD_VALUE;
// check the name
char* name = (char*)request->name.GetData();
int32 nameLen = request->name.GetSize();
if (!name || nameLen <= 0) {
ERROR(("NotifyQueryRequest: NULL name!\n"));
result = B_BAD_VALUE;
} else
name[nameLen - 1] = '\0'; // NULL-terminate to be safe
// execute the request
if (result == B_OK) {
switch (request->operation) {
case B_ENTRY_CREATED:
PRINT(("notify_query_entry_created(%" B_PRId32 ", %" B_PRId32
", %" B_PRId32 ", %" B_PRId64 ", \"%s\", %" B_PRId64 ")\n",
request->port, request->token, request->device,
request->directory, name, request->node));
result = notify_query_entry_created(request->port,
request->token, request->device, request->directory, name,
request->node);
break;
case B_ENTRY_REMOVED:
PRINT(("notify_query_entry_removed(%" B_PRId32 ", %" B_PRId32
", %" B_PRId32 ", %" B_PRId64 ", \"%s\", %" B_PRId64 ")\n",
request->port, request->token, request->device,
request->directory, name, request->node));
result = notify_query_entry_removed(request->port,
request->token, request->device, request->directory, name,
request->node);
break;
case B_ENTRY_MOVED:
default:
ERROR(("NotifyQueryRequest: unsupported operation: %" B_PRId32
"\n", request->operation));
result = B_BAD_VALUE;
break;
}
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
NotifyQueryReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// #pragma mark -
// #pragma mark ----- vnodes -----
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(GetVNodeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
void* node;
if (result == B_OK)
result = volume->GetVNode(request->vnid, &node);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
GetVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
reply->node = node;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(PutVNodeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->PutVNode(request->vnid);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
PutVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(AcquireVNodeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->AcquireVNode(request->vnid);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
AcquireVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(NewVNodeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK) {
result = volume->NewVNode(request->vnid, request->node,
request->capabilities);
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
NewVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(PublishVNodeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK) {
result = volume->PublishVNode(request->vnid, request->node,
request->type, request->flags, request->capabilities);
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
PublishVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(RemoveVNodeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->RemoveVNode(request->vnid);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
RemoveVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(UnremoveVNodeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->UnremoveVNode(request->vnid);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
UnremoveVNodeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(GetVNodeRemovedRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
bool removed = false;
if (result == B_OK)
result = volume->GetVNodeRemoved(request->vnid, &removed);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
GetVNodeRemovedReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
reply->removed = removed;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(FileCacheCreateRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->CreateFileCache(request->vnid, request->size);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
FileCacheCreateReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(FileCacheDeleteRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->DeleteFileCache(request->vnid);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
FileCacheDeleteReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(FileCacheSetEnabledRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->SetFileCacheEnabled(request->vnid, request->enabled);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
FileCacheSetEnabledReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(FileCacheSetSizeRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->SetFileCacheSize(request->vnid, request->size);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
FileCacheSetSizeReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(FileCacheSyncRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->SyncFileCache(request->vnid);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
FileCacheSyncReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(FileCacheReadRequest* request)
{
// check the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
size_t size = request->size;
// allocate the reply
RequestAllocator allocator(fPort->GetPort());
FileCacheReadReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
RETURN_ERROR(error);
void* buffer;
if (result == B_OK) {
result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
true);
}
// execute the request
if (result == B_OK) {
result = volume->ReadFileCache(request->vnid, request->cookie,
request->pos, buffer, &size);
}
// prepare the reply
reply->error = result;
reply->bytesRead = size;
// send the reply
if (reply->error == B_OK && reply->bytesRead > 0) {
SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
return fPort->SendRequest(&allocator, &handler);
}
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(FileCacheWriteRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
size_t size = 0;
if (result == B_OK) {
const void* data = request->buffer.GetData();
size = request->size;
if (data != NULL) {
if (size != (size_t)request->buffer.GetSize())
result = B_BAD_DATA;
}
if (result == B_OK) {
result = volume->WriteFileCache(request->vnid, request->cookie,
request->pos, data, &size);
}
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
FileCacheWriteReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
reply->bytesWritten = size;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(DoIterativeFDIORequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
uint32 vecCount = request->vecCount;
if (result == B_OK && vecCount > DoIterativeFDIORequest::MAX_VECS)
result = B_BAD_VALUE;
if (result == B_OK) {
result = volume->DoIterativeFDIO(request->fd, request->request,
request->cookie, request->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);
}
status_t
KernelRequestHandler::_HandleRequest(ReadFromIORequestRequest* request)
{
// check the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
size_t size = request->size;
// allocate the reply
RequestAllocator allocator(fPort->GetPort());
ReadFromIORequestReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
RETURN_ERROR(error);
void* buffer;
if (result == B_OK) {
result = allocator.AllocateAddress(reply->buffer, size, 1, &buffer,
true);
}
// execute the request
if (result == B_OK)
result = volume->ReadFromIORequest(request->request, buffer, size);
// prepare the reply
reply->error = result;
// send the reply
if (reply->error == B_OK && size > 0) {
SingleReplyRequestHandler handler(RECEIPT_ACK_REPLY);
return fPort->SendRequest(&allocator, &handler);
}
return fPort->SendRequest(&allocator);
}
status_t
KernelRequestHandler::_HandleRequest(WriteToIORequestRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK) {
result = volume->WriteToIORequest(request->request,
request->buffer.GetData(), request->buffer.GetSize());
}
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
WriteToIORequestReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
// _HandleRequest
status_t
KernelRequestHandler::_HandleRequest(NotifyIORequestRequest* request)
{
// check and execute the request
Volume* volume = NULL;
status_t result = _GetVolume(request->nsid, &volume);
VolumePutter _(volume);
if (result == B_OK)
result = volume->NotifyIORequest(request->request, request->status);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
NotifyIORequestReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
status_t
KernelRequestHandler::_HandleRequest(AddNodeListenerRequest* request)
{
// check and execute the request
status_t result = fFileSystem->AddNodeListener(request->device,
request->node, request->flags, request->listener);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
AddNodeListenerReply* reply;
status_t error = AllocateRequest(allocator, &reply);
if (error != B_OK)
return error;
reply->error = result;
// send the reply
return fPort->SendRequest(&allocator);
}
status_t
KernelRequestHandler::_HandleRequest(RemoveNodeListenerRequest* request)
{
// check and execute the request
status_t result = fFileSystem->RemoveNodeListener(request->device,
request->node, request->listener);
// prepare the reply
RequestAllocator allocator(fPort->GetPort());
RemoveNodeListenerReply* 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)
{
if (fVolume) {
if (fVolume->GetID() != id) {
*volume = NULL;
return B_BAD_VALUE;
}
fVolume->AcquireReference();
*volume = fVolume;
return B_OK;
}
*volume = fFileSystem->GetVolume(id);
return (*volume ? B_OK : B_BAD_VALUE);
}
↑ V614 Potentially uninitialized pointer 'node' used.