# HG changeset patch # User Paul Boddie # Date 1631056680 -7200 # Node ID 538b15bffd3e9f99c93d946d6f003a6630d1f191 # Parent 225ff3fe520d97dd1dd8076bf55b790258cb3288 Introduced per-file notification support since the existing support had been brought over from the pipe-related paging support and inadvertently provided a common notification mechanism acting across all files. diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/include/fsserver/file_notification.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/file_notification.h Wed Sep 08 01:18:00 2021 +0200 @@ -0,0 +1,48 @@ +/* + * File-specific notification support. + * + * Copyright (C) 2021 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include + + + +/* Notification support for files. */ + +class FileNotification : public NotificationSupport +{ +protected: + std::mutex _lock; + unsigned int _attached = 0; + +public: + explicit FileNotification(); + + /* Accounting methods. */ + + void attach(); + + unsigned int detach(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/include/fsserver/file_pager.h --- a/libfsserver/include/fsserver/file_pager.h Sat Sep 04 23:23:32 2021 +0200 +++ b/libfsserver/include/fsserver/file_pager.h Wed Sep 08 01:18:00 2021 +0200 @@ -75,9 +75,9 @@ /* Notification methods. */ - virtual long subscribe(l4_cap_idx_t notifier, notify_flags_t flags); + virtual long subscribe(l4_cap_idx_t endpoint, notify_flags_t flags); - virtual long unsubscribe(l4_cap_idx_t notifier); + virtual long unsubscribe(l4_cap_idx_t endpoint); }; // vim: tabstop=4 expandtab shiftwidth=4 diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/include/fsserver/file_paging.h --- a/libfsserver/include/fsserver/file_paging.h Sat Sep 04 23:23:32 2021 +0200 +++ b/libfsserver/include/fsserver/file_paging.h Wed Sep 08 01:18:00 2021 +0200 @@ -24,8 +24,8 @@ #include #include +#include #include -#include #include #include #include @@ -37,15 +37,21 @@ typedef std::map FileMapping; typedef std::pair FileMappingEntry; +/* Mapping type from file identifiers to notification managers. */ + +typedef std::map FileNotifiers; +typedef std::map FileNotifierEntry; + /* A registry of mappers for accessors. */ -class FilePaging : public NotificationSupport +class FilePaging { protected: Pages *_pages; FileMapping _mappers; + FileNotifiers _notifiers; std::mutex _lock; /* Mapper registry access. */ @@ -60,18 +66,26 @@ map_flags_t get_flags(flags_t flags); + long get_mapper(FileOpening *opening, const char *path, flags_t flags, fileid_t fileid, PageMapper **mapper); + + /* Notification manager access. */ + + FileNotification *get_notifier(fileid_t fileid); + + void remove(fileid_t fileid, FileNotification *notifier); + public: explicit FilePaging(Pages *pages); /* Pager initialisation methods. */ - long get_mapper(FileOpening *opening, const char *path, flags_t flags, fileid_t fileid, PageMapper **mapper); - long get_pager(FileOpening *opening, const char *path, flags_t flags, fileid_t fileid, Pager **pager); /* Methods for the pager. */ void detach_pager(fileid_t fileid, PageMapper *mapper); + + FileNotification *notifier(fileid_t fileid); }; // vim: tabstop=4 expandtab shiftwidth=4 diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/include/fsserver/notification.h --- a/libfsserver/include/fsserver/notification.h Sat Sep 04 23:23:32 2021 +0200 +++ b/libfsserver/include/fsserver/notification.h Wed Sep 08 01:18:00 2021 +0200 @@ -75,6 +75,8 @@ public: explicit NotificationSupport(unsigned int endpoints=0); + virtual ~NotificationSupport(); + virtual void notify(unsigned int endpoint, notify_flags_t flags); virtual void notify_others(unsigned int endpoint, notify_flags_t flags); diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/lib/Makefile --- a/libfsserver/lib/Makefile Sat Sep 04 23:23:32 2021 +0200 +++ b/libfsserver/lib/Makefile Wed Sep 08 01:18:00 2021 +0200 @@ -48,6 +48,7 @@ files/ext2_file_opener.cc \ files/ext2_file_operations.cc \ files/ext2_filesystem.cc \ + files/file_notification.cc \ files/file_pager.cc \ files/file_paging.cc \ files/filesystem_resource.cc \ diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/lib/files/file_notification.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/file_notification.cc Wed Sep 08 01:18:00 2021 +0200 @@ -0,0 +1,54 @@ +/* + * Notification support for files. + * + * Copyright (C) 2021 Paul Boddie + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "file_notification.h" + + + +FileNotification::FileNotification() +: NotificationSupport() +{ +} + +/* Accounting methods. */ + +/* Attach a user of this object. */ + +void FileNotification::attach() +{ + std::lock_guard guard(_lock); + + _attached += 1; +} + +/* Detach a user of this object. */ + +unsigned int FileNotification::detach() +{ + std::lock_guard guard(_lock); + + if (_attached) + _attached -= 1; + + return _attached; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/lib/files/file_pager.cc --- a/libfsserver/lib/files/file_pager.cc Sat Sep 04 23:23:32 2021 +0200 +++ b/libfsserver/lib/files/file_pager.cc Wed Sep 08 01:18:00 2021 +0200 @@ -54,7 +54,10 @@ /* Notify other users of the file. */ - _paging->notify_others(_endpoint, NOTIFY_PEER_CLOSED); + FileNotification *notifier = _paging->notifier(fileid); + + if (notifier != NULL) + notifier->notify_others(_endpoint, NOTIFY_PEER_CLOSED); } @@ -67,7 +70,11 @@ if (_resized) { - _paging->notify_others(_endpoint, NOTIFY_CONTENT_AVAILABLE); + FileNotification *notifier = _paging->notifier(fileid); + + if (notifier != NULL) + notifier->notify_others(_endpoint, NOTIFY_CONTENT_AVAILABLE); + _resized = false; } @@ -109,18 +116,27 @@ /* Subscribe to notifications. */ -long FilePager::subscribe(l4_cap_idx_t notifier, notify_flags_t flags) +long FilePager::subscribe(l4_cap_idx_t endpoint, notify_flags_t flags) { /* Readers can subscribe to new data (at end), and pipe closed events. Writers can subscribe to new space and pipe closed events. */ - _endpoint = _paging->subscribe(notifier, flags); + FileNotification *notifier = _paging->notifier(fileid); + + if (notifier == NULL) + return -L4_ENOSYS; + + _endpoint = notifier->subscribe(endpoint, flags); return L4_EOK; } -long FilePager::unsubscribe(l4_cap_idx_t notifier) +long FilePager::unsubscribe(l4_cap_idx_t endpoint) { - _paging->unsubscribe(_endpoint, notifier); + FileNotification *notifier = _paging->notifier(fileid); + + if (notifier != NULL) + notifier->unsubscribe(_endpoint, endpoint); + return L4_EOK; } diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/lib/files/file_paging.cc --- a/libfsserver/lib/files/file_paging.cc Sat Sep 04 23:23:32 2021 +0200 +++ b/libfsserver/lib/files/file_paging.cc Wed Sep 08 01:18:00 2021 +0200 @@ -27,7 +27,7 @@ FilePaging::FilePaging(Pages *pages) -: NotificationSupport(), _pages(pages) +: _pages(pages) { } @@ -49,6 +49,14 @@ return mapper; } +/* Remove a notification manager for the given 'fileid'. */ + +void FilePaging::remove(fileid_t fileid, FileNotification *notifier) +{ + _notifiers.erase(fileid); + delete notifier; +} + /* Remove a page mapper and its resources for the given 'fileid'. */ void FilePaging::remove(fileid_t fileid, PageMapper *mapper) @@ -58,14 +66,17 @@ delete mapper; } -/* Register a page 'mapper' for the given 'fileid'. */ +/* Register a page 'mapper' and a notification manager for the given 'fileid'. */ void FilePaging::set(fileid_t fileid, PageMapper *mapper) { FileMapping::iterator entry = _mappers.find(fileid); - if (entry == _mappers.end()) - _mappers[fileid] = mapper; + if (entry != _mappers.end()) + return; + + _mappers[fileid] = mapper; + _notifiers[fileid] = new FileNotification; } @@ -106,6 +117,18 @@ return L4_EOK; } +/* Obtain a file-specific notification manager. */ + +FileNotification *FilePaging::get_notifier(fileid_t file) +{ + FileNotifiers::iterator entry = _notifiers.find(file); + + if (entry != _notifiers.end()) + return _notifiers[file]; + else + return NULL; +} + /* Return a pager initialised with a page mapper. */ @@ -138,6 +161,20 @@ if (!mapper->detach()) remove(fileid, mapper); + + FileNotification *notifier = get_notifier(fileid); + + if ((notifier != NULL) && (!notifier->detach())) + remove(fileid, notifier); +} + +/* Obtain a file-specific notification manager. */ + +FileNotification *FilePaging::notifier(fileid_t file) +{ + std::lock_guard guard(_lock); + + return get_notifier(file); } // vim: tabstop=4 expandtab shiftwidth=4 diff -r 225ff3fe520d -r 538b15bffd3e libfsserver/lib/generic/notification.cc --- a/libfsserver/lib/generic/notification.cc Sat Sep 04 23:23:32 2021 +0200 +++ b/libfsserver/lib/generic/notification.cc Wed Sep 08 01:18:00 2021 +0200 @@ -34,6 +34,10 @@ _endpoints.resize(_min_endpoints); } +NotificationSupport::~NotificationSupport() +{ +} + /* Subscribe to notifications using a notification object, returning the endpoint number. */