Added support for in-kernel node monitoring ({add,remove}_node_listener()).
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34147 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c89002c82c
commit
c77f643a2b
@ -188,6 +188,10 @@ enum {
|
||||
REWIND_QUERY_REQUEST,
|
||||
REWIND_QUERY_REPLY,
|
||||
|
||||
// node monitoring
|
||||
NODE_MONITORING_EVENT_REQUEST,
|
||||
NODE_MONITORING_EVENT_REPLY,
|
||||
|
||||
// userland -> kernel requests
|
||||
// notifications
|
||||
NOTIFY_LISTENER_REQUEST,
|
||||
@ -241,6 +245,12 @@ enum {
|
||||
NOTIFY_IO_REQUEST_REQUEST,
|
||||
NOTIFY_IO_REQUEST_REPLY,
|
||||
|
||||
// node monitoring
|
||||
ADD_NODE_LISTENER_REQUEST,
|
||||
ADD_NODE_LISTENER_REPLY,
|
||||
REMOVE_NODE_LISTENER_REQUEST,
|
||||
REMOVE_NODE_LISTENER_REPLY,
|
||||
|
||||
// general reply
|
||||
RECEIPT_ACK_REPLY,
|
||||
|
||||
@ -1506,6 +1516,27 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark ----- node monitoring -----
|
||||
|
||||
|
||||
// NodeMonitoringEventRequest
|
||||
class NodeMonitoringEventRequest : public KernelRequest {
|
||||
public:
|
||||
NodeMonitoringEventRequest()
|
||||
: KernelRequest(NODE_MONITORING_EVENT_REQUEST) {}
|
||||
status_t GetAddressInfos(AddressInfo* infos, int32* count);
|
||||
|
||||
void* listener;
|
||||
Address event;
|
||||
};
|
||||
|
||||
// NodeMonitoringEventReply
|
||||
class NodeMonitoringEventReply : public ReplyRequest {
|
||||
public:
|
||||
NodeMonitoringEventReply() : ReplyRequest(NODE_MONITORING_EVENT_REPLY) {}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// #pragma mark ----- userland requests -----
|
||||
|
||||
@ -1893,6 +1924,43 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - node monitoring
|
||||
|
||||
|
||||
// AddNodeListenerRequest
|
||||
class AddNodeListenerRequest : public Request {
|
||||
public:
|
||||
AddNodeListenerRequest() : Request(ADD_NODE_LISTENER_REQUEST) {}
|
||||
|
||||
dev_t device;
|
||||
ino_t node;
|
||||
uint32 flags;
|
||||
void* listener;
|
||||
};
|
||||
|
||||
// AddNodeListenerReply
|
||||
class AddNodeListenerReply : public ReplyRequest {
|
||||
public:
|
||||
AddNodeListenerReply() : ReplyRequest(ADD_NODE_LISTENER_REPLY) {}
|
||||
};
|
||||
|
||||
// RemoveNodeListenerRequest
|
||||
class RemoveNodeListenerRequest : public Request {
|
||||
public:
|
||||
RemoveNodeListenerRequest() : Request(REMOVE_NODE_LISTENER_REQUEST) {}
|
||||
|
||||
dev_t device;
|
||||
ino_t node;
|
||||
void* listener;
|
||||
};
|
||||
|
||||
// RemoveNodeListenerReply
|
||||
class RemoveNodeListenerReply : public ReplyRequest {
|
||||
public:
|
||||
RemoveNodeListenerReply() : ReplyRequest(REMOVE_NODE_LISTENER_REPLY) {}
|
||||
};
|
||||
|
||||
|
||||
//////////////////
|
||||
// General Reply
|
||||
|
||||
@ -2209,6 +2277,11 @@ do_for_request(Request* request, Task& task)
|
||||
return task((RewindQueryRequest*)request);
|
||||
case REWIND_QUERY_REPLY:
|
||||
return task((RewindQueryReply*)request);
|
||||
// node monitoring
|
||||
case NODE_MONITORING_EVENT_REQUEST:
|
||||
return task((NodeMonitoringEventRequest*)request);
|
||||
case NODE_MONITORING_EVENT_REPLY:
|
||||
return task((NodeMonitoringEventReply*)request);
|
||||
|
||||
// userland -> kernel requests
|
||||
// notifications
|
||||
@ -2303,6 +2376,15 @@ do_for_request(Request* request, Task& task)
|
||||
return task((NotifyIORequestRequest*)request);
|
||||
case NOTIFY_IO_REQUEST_REPLY:
|
||||
return task((NotifyIORequestReply*)request);
|
||||
// node monitoring
|
||||
case ADD_NODE_LISTENER_REQUEST:
|
||||
return task((AddNodeListenerRequest*)request);
|
||||
case ADD_NODE_LISTENER_REPLY:
|
||||
return task((AddNodeListenerReply*)request);
|
||||
case REMOVE_NODE_LISTENER_REQUEST:
|
||||
return task((RemoveNodeListenerRequest*)request);
|
||||
case REMOVE_NODE_LISTENER_REPLY:
|
||||
return task((RemoveNodeListenerReply*)request);
|
||||
// general reply
|
||||
case RECEIPT_ACK_REPLY:
|
||||
return task((ReceiptAckReply*)request);
|
||||
@ -2482,6 +2564,9 @@ using UserlandFSUtil::ReadQueryRequest;
|
||||
using UserlandFSUtil::ReadQueryReply;
|
||||
using UserlandFSUtil::RewindQueryRequest;
|
||||
using UserlandFSUtil::RewindQueryReply;
|
||||
// node monitoring
|
||||
using UserlandFSUtil::NodeMonitoringEventRequest;
|
||||
using UserlandFSUtil::NodeMonitoringEventReply;
|
||||
|
||||
// userland -> kernel requests
|
||||
// notifications
|
||||
@ -2532,6 +2617,11 @@ using UserlandFSUtil::WriteToIORequestRequest;
|
||||
using UserlandFSUtil::WriteToIORequestReply;
|
||||
using UserlandFSUtil::NotifyIORequestRequest;
|
||||
using UserlandFSUtil::NotifyIORequestReply;
|
||||
// node monitoring
|
||||
using UserlandFSUtil::AddNodeListenerRequest;
|
||||
using UserlandFSUtil::AddNodeListenerReply;
|
||||
using UserlandFSUtil::RemoveNodeListenerRequest;
|
||||
using UserlandFSUtil::RemoveNodeListenerReply;
|
||||
// general reply
|
||||
using UserlandFSUtil::ReceiptAckReply;
|
||||
|
||||
|
@ -3,10 +3,14 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "Volume.h"
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include <fs/node_monitor.h>
|
||||
#include <Notifications.h>
|
||||
|
||||
#include "AutoLocker.h"
|
||||
#include "Compatibility.h"
|
||||
#include "Debug.h"
|
||||
@ -20,16 +24,139 @@
|
||||
#include "Settings.h"
|
||||
#include "SingleReplyRequestHandler.h"
|
||||
|
||||
|
||||
// The time after which the notification thread times out at the port and
|
||||
// restarts the loop. Of interest only when the FS is deleted. It is the
|
||||
// maximal time the destructor has to wait for the thread.
|
||||
static const bigtime_t kNotificationRequestTimeout = 50000; // 50 ms
|
||||
|
||||
// SelectSyncMap
|
||||
|
||||
// #pragma mark - SelectSyncMap
|
||||
|
||||
|
||||
struct FileSystem::SelectSyncMap
|
||||
: public SynchronizedHashMap<HashKey32<selectsync*>, int32*> {
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - NodeListenerKey
|
||||
|
||||
|
||||
struct FileSystem::NodeListenerKey {
|
||||
NodeListenerKey(void* clientListener, dev_t device, ino_t node)
|
||||
:
|
||||
fClientListener(clientListener),
|
||||
fDevice(device),
|
||||
fNode(node)
|
||||
{
|
||||
}
|
||||
|
||||
void* ClientListener() const
|
||||
{
|
||||
return fClientListener;
|
||||
}
|
||||
|
||||
dev_t Device() const
|
||||
{
|
||||
return fDevice;
|
||||
}
|
||||
|
||||
ino_t Node() const
|
||||
{
|
||||
return fNode;
|
||||
}
|
||||
|
||||
uint32 HashValue() const
|
||||
{
|
||||
return (uint32)(addr_t)fClientListener ^ (uint32)fDevice
|
||||
^ (uint32)fNode ^ (uint32)(fNode >> 32);
|
||||
}
|
||||
|
||||
bool operator==(const NodeListenerKey& other) const
|
||||
{
|
||||
return fClientListener == other.fClientListener
|
||||
&& fDevice == other.fDevice && fNode == other.fNode;
|
||||
}
|
||||
|
||||
protected:
|
||||
void* fClientListener;
|
||||
dev_t fDevice;
|
||||
ino_t fNode;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - NodeListenerProxy
|
||||
|
||||
|
||||
struct FileSystem::NodeListenerProxy : NodeListenerKey, NotificationListener {
|
||||
NodeListenerProxy(FileSystem* fileSystem, void* clientListener,
|
||||
dev_t device, ino_t node)
|
||||
:
|
||||
NodeListenerKey(clientListener, device, node),
|
||||
fFileSystem(fileSystem)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void EventOccurred(NotificationService& service,
|
||||
const KMessage* event)
|
||||
{
|
||||
fFileSystem->_NodeListenerEventOccurred(this, event);
|
||||
}
|
||||
|
||||
NodeListenerProxy*& HashTableLink()
|
||||
{
|
||||
return fHashTableLink;
|
||||
}
|
||||
|
||||
status_t StartListening(uint32 flags)
|
||||
{
|
||||
return add_node_listener(fDevice, fNode, flags, *this);
|
||||
}
|
||||
|
||||
status_t StopListening()
|
||||
{
|
||||
return remove_node_listener(fDevice, fNode, *this);
|
||||
}
|
||||
|
||||
private:
|
||||
FileSystem* fFileSystem;
|
||||
NodeListenerProxy* fHashTableLink;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - NodeListenerHashDefinition
|
||||
|
||||
|
||||
struct FileSystem::NodeListenerHashDefinition {
|
||||
typedef NodeListenerKey KeyType;
|
||||
typedef NodeListenerProxy ValueType;
|
||||
|
||||
size_t HashKey(const NodeListenerKey& key) const
|
||||
{
|
||||
return key.HashValue();
|
||||
}
|
||||
|
||||
size_t Hash(const NodeListenerProxy* value) const
|
||||
{
|
||||
return value->HashValue();
|
||||
}
|
||||
|
||||
bool Compare(const NodeListenerKey& key,
|
||||
const NodeListenerProxy* value) const
|
||||
{
|
||||
return key == *value;
|
||||
}
|
||||
|
||||
NodeListenerProxy*& GetLink(NodeListenerProxy* value) const
|
||||
{
|
||||
return value->HashTableLink();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - FileSystem
|
||||
|
||||
|
||||
// constructor
|
||||
FileSystem::FileSystem()
|
||||
:
|
||||
@ -47,6 +174,7 @@ FileSystem::FileSystem()
|
||||
{
|
||||
mutex_init(&fVolumeLock, "userlandfs volumes");
|
||||
mutex_init(&fVNodeOpsLock, "userlandfs vnode ops");
|
||||
mutex_init(&fNodeListenersLock, "userlandfs node listeners");
|
||||
}
|
||||
|
||||
// destructor
|
||||
@ -61,6 +189,17 @@ FileSystem::~FileSystem()
|
||||
}
|
||||
|
||||
// delete our data structures
|
||||
if (fNodeListeners != NULL) {
|
||||
MutexLocker nodeListenersLocker(fNodeListenersLock);
|
||||
NodeListenerProxy* proxy = fNodeListeners->Clear(true);
|
||||
while (proxy != NULL) {
|
||||
NodeListenerProxy* next = proxy->HashTableLink();
|
||||
proxy->StopListening();
|
||||
delete proxy;
|
||||
proxy = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (fSelectSyncs) {
|
||||
for (SelectSyncMap::Iterator it = fSelectSyncs->GetIterator();
|
||||
it.HasNext();) {
|
||||
@ -69,6 +208,7 @@ FileSystem::~FileSystem()
|
||||
}
|
||||
delete fSelectSyncs;
|
||||
}
|
||||
|
||||
delete fSettings;
|
||||
|
||||
// delete vnode ops vectors -- there shouldn't be any left, though
|
||||
@ -82,6 +222,11 @@ FileSystem::~FileSystem()
|
||||
}
|
||||
if (count > 0)
|
||||
WARN(("Deleted %ld vnode ops vectors!\n", count));
|
||||
|
||||
|
||||
mutex_destroy(&fVolumeLock);
|
||||
mutex_destroy(&fVNodeOpsLock);
|
||||
mutex_destroy(&fNodeListenersLock);
|
||||
}
|
||||
|
||||
// Init
|
||||
@ -113,6 +258,11 @@ FileSystem::Init(const char* name, team_id team, Port::Info* infos, int32 count,
|
||||
if (!fSelectSyncs)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// create the node listener proxy map
|
||||
fNodeListeners = new(std::nothrow) NodeListenerMap;
|
||||
if (fNodeListeners == NULL || fNodeListeners->Init() != B_OK)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// create the request ports
|
||||
// the notification port
|
||||
fNotificationPort = new(nothrow) RequestPort(infos);
|
||||
@ -348,6 +498,57 @@ FileSystem::KnowsSelectSyncEntry(selectsync* sync)
|
||||
}
|
||||
|
||||
|
||||
// AddNodeListener
|
||||
status_t
|
||||
FileSystem::AddNodeListener(dev_t device, ino_t node, uint32 flags,
|
||||
void* listener)
|
||||
{
|
||||
MutexLocker nodeListenersLocker(fNodeListenersLock);
|
||||
|
||||
// lookup the proxy
|
||||
NodeListenerProxy* proxy = fNodeListeners->Lookup(
|
||||
NodeListenerKey(listener, device, node));
|
||||
if (proxy != NULL)
|
||||
return proxy->StartListening(flags);
|
||||
|
||||
// it doesn't exist yet -- create it
|
||||
proxy = new(std::nothrow) NodeListenerProxy(this, listener, device, node);
|
||||
if (proxy == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// start listening
|
||||
status_t error = proxy->StartListening(flags);
|
||||
if (error != B_OK) {
|
||||
delete proxy;
|
||||
return error;
|
||||
}
|
||||
|
||||
fNodeListeners->Insert(proxy);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// RemoveNodeListener
|
||||
status_t
|
||||
FileSystem::RemoveNodeListener(dev_t device, ino_t node, void* listener)
|
||||
{
|
||||
MutexLocker nodeListenersLocker(fNodeListenersLock);
|
||||
|
||||
// lookup the proxy
|
||||
NodeListenerProxy* proxy = fNodeListeners->Lookup(
|
||||
NodeListenerKey(listener, device, node));
|
||||
if (proxy == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
status_t error = proxy->StopListening();
|
||||
|
||||
fNodeListeners->Remove(proxy);
|
||||
delete proxy;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// GetVNodeOps
|
||||
VNodeOps*
|
||||
FileSystem::GetVNodeOps(const FSVNodeCapabilities& capabilities)
|
||||
@ -508,6 +709,42 @@ FileSystem::_InitVNodeOpsVector(fs_vnode_ops* ops,
|
||||
}
|
||||
|
||||
|
||||
// _NodeListenerEventOccurred
|
||||
void
|
||||
FileSystem::_NodeListenerEventOccurred(NodeListenerProxy* proxy,
|
||||
const KMessage* event)
|
||||
{
|
||||
// get a free port
|
||||
RequestPort* port = fPortPool.AcquirePort();
|
||||
if (port == NULL)
|
||||
return;
|
||||
PortReleaser _(&fPortPool, port);
|
||||
|
||||
// prepare the request
|
||||
RequestAllocator allocator(port->GetPort());
|
||||
NodeMonitoringEventRequest* request;
|
||||
status_t error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return;
|
||||
|
||||
error = allocator.AllocateData(request->event, event->Buffer(),
|
||||
event->ContentSize(), 1);
|
||||
if (error != B_OK)
|
||||
return;
|
||||
|
||||
struct thread* thread = thread_get_current_thread();
|
||||
request->team = thread->team->id;
|
||||
request->thread = thread->id;
|
||||
request->user = geteuid();
|
||||
request->group = getegid();
|
||||
request->listener = proxy->ClientListener();
|
||||
|
||||
// send the request
|
||||
KernelRequestHandler handler(this, NODE_MONITORING_EVENT_REPLY);
|
||||
port->SendRequest(&allocator, &handler);
|
||||
}
|
||||
|
||||
|
||||
// _NotificationThreadEntry
|
||||
int32
|
||||
FileSystem::_NotificationThreadEntry(void* data)
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef USERLAND_FS_FILE_SYSTEM_H
|
||||
#define USERLAND_FS_FILE_SYSTEM_H
|
||||
|
||||
|
||||
#include <fs_interface.h>
|
||||
|
||||
#include <util/OpenHashTable.h>
|
||||
@ -21,6 +22,7 @@
|
||||
|
||||
|
||||
struct IOCtlInfo;
|
||||
class KMessage;
|
||||
class Settings;
|
||||
class Volume;
|
||||
|
||||
@ -93,25 +95,40 @@ public:
|
||||
void RemoveSelectSyncEntry(selectsync* sync);
|
||||
bool KnowsSelectSyncEntry(selectsync* sync);
|
||||
|
||||
status_t AddNodeListener(dev_t device, ino_t node,
|
||||
uint32 flags, void* listener);
|
||||
status_t RemoveNodeListener(dev_t device, ino_t node,
|
||||
void* listener);
|
||||
|
||||
VNodeOps* GetVNodeOps(
|
||||
const FSVNodeCapabilities& capabilities);
|
||||
void PutVNodeOps(VNodeOps* ops);
|
||||
|
||||
bool IsUserlandServerThread() const;
|
||||
|
||||
private:
|
||||
friend class KernelDebug;
|
||||
struct SelectSyncMap;
|
||||
struct NodeListenerKey;
|
||||
struct NodeListenerProxy;
|
||||
struct NodeListenerHashDefinition;
|
||||
|
||||
typedef BOpenHashTable<VNodeOpsHashDefinition> VNodeOpsMap;
|
||||
typedef BOpenHashTable<NodeListenerHashDefinition> NodeListenerMap;
|
||||
|
||||
|
||||
private:
|
||||
void _InitVNodeOpsVector(fs_vnode_ops* ops,
|
||||
const FSVNodeCapabilities& capabilities);
|
||||
|
||||
void _NodeListenerEventOccurred(
|
||||
NodeListenerProxy* proxy,
|
||||
const KMessage* event);
|
||||
|
||||
static int32 _NotificationThreadEntry(void* data);
|
||||
int32 _NotificationThread();
|
||||
|
||||
private:
|
||||
friend class KernelDebug;
|
||||
struct SelectSyncEntry;
|
||||
struct SelectSyncMap;
|
||||
typedef BOpenHashTable<VNodeOpsHashDefinition> VNodeOpsMap;
|
||||
|
||||
Vector<Volume*> fVolumes;
|
||||
mutex fVolumeLock;
|
||||
VNodeOpsMap fVNodeOps;
|
||||
@ -123,6 +140,8 @@ private:
|
||||
thread_id fNotificationThread;
|
||||
RequestPortPool fPortPool;
|
||||
SelectSyncMap* fSelectSyncs;
|
||||
mutex fNodeListenersLock;
|
||||
NodeListenerMap* fNodeListeners;
|
||||
Settings* fSettings;
|
||||
team_id fUserlandServerTeam;
|
||||
bool fInitialized;
|
||||
|
@ -112,6 +112,11 @@ KernelRequestHandler::HandleRequest(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: %lu\n",
|
||||
request->GetType()));
|
||||
@ -842,6 +847,48 @@ KernelRequestHandler::_HandleRequest(NotifyIORequestRequest* request)
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
|
@ -80,6 +80,10 @@ private:
|
||||
status_t _HandleRequest(
|
||||
WriteToIORequestRequest* request);
|
||||
status_t _HandleRequest(NotifyIORequestRequest* request);
|
||||
// node monitoring
|
||||
status_t _HandleRequest(AddNodeListenerRequest* request);
|
||||
status_t _HandleRequest(
|
||||
RemoveNodeListenerRequest* request);
|
||||
|
||||
status_t _GetVolume(dev_t id, Volume** volume);
|
||||
|
||||
|
@ -280,6 +280,14 @@ ReadQueryReply::GetAddressInfos(AddressInfo* infos, int32* count)
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// NodeMonitoringEventRequest
|
||||
status_t
|
||||
NodeMonitoringEventRequest::GetAddressInfos(AddressInfo* infos, int32* count)
|
||||
{
|
||||
ADD_ADDRESS(event);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// NotifyListenerRequest
|
||||
status_t
|
||||
NotifyListenerRequest::GetAddressInfos(AddressInfo* infos, int32* count)
|
||||
@ -687,6 +695,11 @@ UserlandFSUtil::is_kernel_request(uint32 type)
|
||||
case READ_QUERY_REPLY:
|
||||
case REWIND_QUERY_REPLY:
|
||||
return false;
|
||||
// node monitoring
|
||||
case NODE_MONITORING_EVENT_REQUEST:
|
||||
return true;
|
||||
case NODE_MONITORING_EVENT_REPLY:
|
||||
return false;
|
||||
|
||||
// userland -> kernel requests
|
||||
// notifications
|
||||
@ -745,6 +758,13 @@ UserlandFSUtil::is_kernel_request(uint32 type)
|
||||
case READ_FROM_IO_REQUEST_REPLY:
|
||||
case WRITE_TO_IO_REQUEST_REPLY:
|
||||
return true;
|
||||
// node monitoring
|
||||
case ADD_NODE_LISTENER_REQUEST:
|
||||
case REMOVE_NODE_LISTENER_REQUEST:
|
||||
return false;
|
||||
case ADD_NODE_LISTENER_REPLY:
|
||||
case REMOVE_NODE_LISTENER_REPLY:
|
||||
return true;
|
||||
|
||||
// general reply
|
||||
case RECEIPT_ACK_REPLY:
|
||||
@ -934,6 +954,11 @@ UserlandFSUtil::is_userland_request(uint32 type)
|
||||
case READ_QUERY_REPLY:
|
||||
case REWIND_QUERY_REPLY:
|
||||
return true;
|
||||
// node monitoring
|
||||
case NODE_MONITORING_EVENT_REQUEST:
|
||||
return false;
|
||||
case NODE_MONITORING_EVENT_REPLY:
|
||||
return true;
|
||||
|
||||
// userland -> kernel requests
|
||||
// notifications
|
||||
@ -992,6 +1017,13 @@ UserlandFSUtil::is_userland_request(uint32 type)
|
||||
case READ_FROM_IO_REQUEST_REPLY:
|
||||
case WRITE_TO_IO_REQUEST_REPLY:
|
||||
return false;
|
||||
// node monitoring
|
||||
case ADD_NODE_LISTENER_REQUEST:
|
||||
case REMOVE_NODE_LISTENER_REQUEST:
|
||||
return true;
|
||||
case ADD_NODE_LISTENER_REPLY:
|
||||
case REMOVE_NODE_LISTENER_REPLY:
|
||||
return false;
|
||||
|
||||
// general reply
|
||||
case RECEIPT_ACK_REPLY:
|
||||
|
@ -5,7 +5,8 @@ local userlandFSTop = [ FDirName $(HAIKU_TOP) src add-ons kernel
|
||||
local userlandFSIncludes = [ PrivateHeaders userlandfs ] ;
|
||||
|
||||
SubDirSysHdrs [ FDirName $(userlandFSIncludes) ] ;
|
||||
UsePrivateHeaders kernel libroot shared ;
|
||||
UsePrivateKernelHeaders ;
|
||||
UsePrivateHeaders libroot shared ;
|
||||
SubDirHdrs [ FDirName $(userlandFSIncludes) private ] ;
|
||||
SubDirHdrs [ FDirName $(userlandFSIncludes) shared ] ;
|
||||
|
||||
|
@ -7,6 +7,10 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <util/KMessage.h>
|
||||
|
||||
#include <Notifications.h>
|
||||
|
||||
#include "AutoDeleter.h"
|
||||
#include "Compatibility.h"
|
||||
#include "Debug.h"
|
||||
@ -208,6 +212,10 @@ UserlandRequestHandler::HandleRequest(Request* request)
|
||||
return _HandleRequest((ReadQueryRequest*)request);
|
||||
case REWIND_QUERY_REQUEST:
|
||||
return _HandleRequest((RewindQueryRequest*)request);
|
||||
|
||||
// node monitoring
|
||||
case NODE_MONITORING_EVENT_REQUEST:
|
||||
return _HandleRequest((NodeMonitoringEventRequest*)request);
|
||||
}
|
||||
PRINT(("UserlandRequestHandler::HandleRequest(): unexpected request: %lu\n",
|
||||
request->GetType()));
|
||||
@ -2431,6 +2439,33 @@ UserlandRequestHandler::_HandleRequest(RewindQueryRequest* request)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - node monitoring
|
||||
|
||||
|
||||
// _HandleRequest
|
||||
status_t
|
||||
UserlandRequestHandler::_HandleRequest(NodeMonitoringEventRequest* request)
|
||||
{
|
||||
// check and execute the request
|
||||
KMessage event;
|
||||
event.SetTo(request->event.GetData(), request->event.GetSize());
|
||||
((NotificationListener*)request->listener)->EventOccurred(
|
||||
*(NotificationService*)NULL, &event);
|
||||
|
||||
// prepare the reply
|
||||
RequestAllocator allocator(fPort->GetPort());
|
||||
NodeMonitoringEventReply* reply;
|
||||
status_t error = AllocateRequest(allocator, &reply);
|
||||
if (error != B_OK)
|
||||
RETURN_ERROR(error);
|
||||
|
||||
reply->error = B_OK;
|
||||
|
||||
// send the reply
|
||||
return _SendReply(allocator, false);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - other
|
||||
|
||||
|
||||
|
@ -87,6 +87,8 @@ class CloseQueryRequest;
|
||||
class FreeQueryCookieRequest;
|
||||
class ReadQueryRequest;
|
||||
class RewindQueryRequest;
|
||||
// node monitoring
|
||||
class NodeMonitoringEventRequest;
|
||||
|
||||
class RequestAllocator;
|
||||
|
||||
@ -200,6 +202,10 @@ private:
|
||||
status_t _HandleRequest(ReadQueryRequest* request);
|
||||
status_t _HandleRequest(RewindQueryRequest* request);
|
||||
|
||||
// node monitoring
|
||||
status_t _HandleRequest(
|
||||
NodeMonitoringEventRequest* request);
|
||||
|
||||
status_t _SendReply(RequestAllocator& allocator,
|
||||
bool expectsReceipt);
|
||||
|
||||
|
@ -37,6 +37,7 @@ SharedLibrary libuserlandfs_haiku_kernel.so
|
||||
block_cache.cpp
|
||||
file_map.cpp
|
||||
khash.c
|
||||
Notifications.cpp
|
||||
Referenceable.cpp
|
||||
|
||||
# emulation
|
||||
@ -55,6 +56,11 @@ SharedLibrary libuserlandfs_haiku_kernel.so
|
||||
$(TARGET_LIBSUPC++)
|
||||
;
|
||||
|
||||
|
||||
SEARCH on [ FGristFiles
|
||||
Notifications.cpp
|
||||
] = [ FDirName $(HAIKU_TOP) src system kernel ] ;
|
||||
|
||||
SEARCH on [ FGristFiles
|
||||
block_cache.cpp
|
||||
file_map.cpp
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <KernelExport.h>
|
||||
#include <NodeMonitor.h>
|
||||
|
||||
#include <fs/node_monitor.h>
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
#include "../FileSystem.h"
|
||||
@ -366,6 +368,25 @@ notify_io_request(io_request* _request, status_t status)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - node monitoring
|
||||
|
||||
|
||||
status_t
|
||||
add_node_listener(dev_t device, ino_t node, uint32 flags,
|
||||
NotificationListener& listener)
|
||||
{
|
||||
return UserlandFS::KernelEmu::add_node_listener(device, node, flags,
|
||||
&listener);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
remove_node_listener(dev_t device, ino_t node, NotificationListener& listener)
|
||||
{
|
||||
return UserlandFS::KernelEmu::remove_node_listener(device, node, &listener);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Disk Device Manager
|
||||
|
||||
|
||||
|
@ -1009,6 +1009,80 @@ UserlandFS::KernelEmu::notify_io_request(dev_t volumeID, int32 requestID,
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - node monitoring
|
||||
|
||||
|
||||
status_t
|
||||
UserlandFS::KernelEmu::add_node_listener(dev_t device, ino_t node, uint32 flags,
|
||||
void* listener)
|
||||
{
|
||||
// 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());
|
||||
AddNodeListenerRequest* request;
|
||||
error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
request->device = device;
|
||||
request->node = node;
|
||||
request->flags = flags;
|
||||
request->listener = listener;
|
||||
|
||||
// send the request
|
||||
UserlandRequestHandler handler(fileSystem, ADD_NODE_LISTENER_REPLY);
|
||||
AddNodeListenerReply* reply;
|
||||
error = port->SendRequest(&allocator, &handler, (Request**)&reply);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
RequestReleaser requestReleaser(port, reply);
|
||||
|
||||
// process the reply
|
||||
return reply->error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
UserlandFS::KernelEmu::remove_node_listener(dev_t device, ino_t node,
|
||||
void* listener)
|
||||
{
|
||||
// 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());
|
||||
RemoveNodeListenerRequest* request;
|
||||
error = AllocateRequest(allocator, &request);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
request->device = device;
|
||||
request->node = node;
|
||||
request->listener = listener;
|
||||
|
||||
// send the request
|
||||
UserlandRequestHandler handler(fileSystem, REMOVE_NODE_LISTENER_REPLY);
|
||||
RemoveNodeListenerReply* reply;
|
||||
error = port->SendRequest(&allocator, &handler, (Request**)&reply);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
RequestReleaser requestReleaser(port, reply);
|
||||
|
||||
// process the reply
|
||||
return reply->error;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
|
@ -56,6 +56,10 @@ status_t write_to_io_request(dev_t volumeID, int32 requestID, const void* buffer
|
||||
size_t size);
|
||||
status_t notify_io_request(dev_t volumeID, int32 requestID, status_t status);
|
||||
|
||||
status_t add_node_listener(dev_t device, ino_t node, uint32 flags,
|
||||
void* listener);
|
||||
status_t remove_node_listener(dev_t device, ino_t node, void* listener);
|
||||
|
||||
void kernel_debugger(const char *message);
|
||||
void vpanic(const char *format, va_list args);
|
||||
void panic(const char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
|
||||
|
Loading…
Reference in New Issue
Block a user