From c77f643a2b3f3990e6f355d6c333537b9cbfd88f Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 20 Nov 2009 07:59:09 +0000 Subject: [PATCH] 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 --- headers/private/userlandfs/private/Requests.h | 90 +++++++ .../userlandfs/kernel_add_on/FileSystem.cpp | 239 +++++++++++++++++- .../userlandfs/kernel_add_on/FileSystem.h | 29 ++- .../kernel_add_on/KernelRequestHandler.cpp | 47 ++++ .../kernel_add_on/KernelRequestHandler.h | 4 + .../userlandfs/private/Requests.cpp | 32 +++ .../file_systems/userlandfs/server/Jamfile | 3 +- .../server/UserlandRequestHandler.cpp | 35 +++ .../server/UserlandRequestHandler.h | 6 + .../userlandfs/server/haiku/Jamfile | 6 + .../server/haiku/haiku_kernel_emu.cpp | 21 ++ .../userlandfs/server/kernel_emu.cpp | 74 ++++++ .../userlandfs/server/kernel_emu.h | 4 + 13 files changed, 583 insertions(+), 7 deletions(-) diff --git a/headers/private/userlandfs/private/Requests.h b/headers/private/userlandfs/private/Requests.h index abd896f03a..00785ab0bf 100644 --- a/headers/private/userlandfs/private/Requests.h +++ b/headers/private/userlandfs/private/Requests.h @@ -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; diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp index ac8fb615cf..3bf68bc8ce 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.cpp @@ -3,10 +3,14 @@ * Distributed under the terms of the MIT License. */ + #include "Volume.h" #include +#include +#include + #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, 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) diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h index 7527208119..de50f83b91 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/FileSystem.h @@ -5,6 +5,7 @@ #ifndef USERLAND_FS_FILE_SYSTEM_H #define USERLAND_FS_FILE_SYSTEM_H + #include #include @@ -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 VNodeOpsMap; + typedef BOpenHashTable 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 VNodeOpsMap; - Vector 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; diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp index 48ab78d3de..f3b6aef346 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.cpp @@ -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) diff --git a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.h b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.h index cb1e4a7f5e..e523e2d43d 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.h +++ b/src/add-ons/kernel/file_systems/userlandfs/kernel_add_on/KernelRequestHandler.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp b/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp index 023fcc2288..ccdc7a906b 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/private/Requests.cpp @@ -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: diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/Jamfile b/src/add-ons/kernel/file_systems/userlandfs/server/Jamfile index 91198c6275..b2357ec236 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/Jamfile +++ b/src/add-ons/kernel/file_systems/userlandfs/server/Jamfile @@ -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 ] ; diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp index 0fd086a56b..b853aa4207 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.cpp @@ -7,6 +7,10 @@ #include +#include + +#include + #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 diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h index a2fc3b884b..35855b8870 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/UserlandRequestHandler.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile index 669d3dfb90..34d23413e6 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/Jamfile @@ -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 diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp index ba8f6a7d35..182d2111be 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/haiku/haiku_kernel_emu.cpp @@ -14,6 +14,8 @@ #include #include +#include + #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 diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp index 187ba7fc6c..b7d6ad53e6 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.cpp @@ -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 - diff --git a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h index a759c9437e..be93c3b25f 100644 --- a/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h +++ b/src/add-ons/kernel/file_systems/userlandfs/server/kernel_emu.h @@ -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)));