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:
Ingo Weinhold 2009-11-20 07:59:09 +00:00
parent c89002c82c
commit c77f643a2b
13 changed files with 583 additions and 7 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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:

View File

@ -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 ] ;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 -

View File

@ -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)));