From e0965f2727623547ce67f3f51725ce370481e456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 27 Jun 2009 14:24:55 +0000 Subject: [PATCH] * reload_driver() now also checks if the binary node changed, and will update the node listener, to make sure it won't lose track. * The DriverWatcher now also listens for B_ENTRY_REMOVED. This causes drivers to be unpublished even if they are only symlinked. * However, to detect new drivers in a symlinked location, we'd need special support for those, and also need to watch the parent directory of the symlink target - this is close to overkill, so I stayed away from implementing that for now :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@31267 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/device_manager/legacy_drivers.cpp | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/system/kernel/device_manager/legacy_drivers.cpp b/src/system/kernel/device_manager/legacy_drivers.cpp index bf473bfd61..c1e6769d80 100644 --- a/src/system/kernel/device_manager/legacy_drivers.cpp +++ b/src/system/kernel/device_manager/legacy_drivers.cpp @@ -108,6 +108,8 @@ struct path_entry : DoublyLinkedListLinkImpl { char path[B_PATH_NAME_LENGTH]; }; +typedef DoublyLinkedList EntryList; + struct driver_entry : public DoublyLinkedListLinkImpl { char* path; dev_t device; @@ -191,8 +193,8 @@ static status_t load_driver(legacy_driver *driver); static hash_table* sDriverHash; static DriverWatcher sDriverWatcher; static int32 sDriverEvents; -static DoublyLinkedList sDriversToAdd; -static DoublyLinkedList sDriversToRemove; +static EntryList sDriversToAdd; +static EntryList sDriversToRemove; static mutex sDriversListLock = MUTEX_INITIALIZER("driversList"); static DirectoryWatcher sDirectoryWatcher; static DirectoryNodeHash sDirectoryNodeHash; @@ -581,7 +583,7 @@ add_driver(const char *path, image_id image) hash_insert(sDriverHash, driver); if (stat.st_dev > 0) { - add_node_listener(stat.st_dev, stat.st_ino, B_WATCH_STAT, + add_node_listener(stat.st_dev, stat.st_ino, B_WATCH_STAT | B_WATCH_NAME, sDriverWatcher); } @@ -612,8 +614,19 @@ reload_driver(legacy_driver *driver) unload_driver(driver); + struct stat stat; + if (::stat(driver->path, &stat) == 0 + && (stat.st_dev != driver->device || stat.st_ino != driver->node)) { + // The driver file has been changed, so we need to update its listener + if (driver->device != -1) + remove_node_listener(driver->device, driver->node, sDriverWatcher); + + add_node_listener(driver->device, driver->node, + B_WATCH_STAT | B_WATCH_NAME, sDriverWatcher); + } + status_t status = load_driver(driver); - if (status < B_OK) + if (status != B_OK) unpublish_driver(driver); return status; @@ -691,8 +704,10 @@ void DriverWatcher::EventOccured(NotificationService& service, const KMessage* event) { - if (event->GetInt32("opcode", -1) != B_STAT_CHANGED - || (event->GetInt32("fields", 0) & B_STAT_MODIFICATION_TIME) == 0) + int32 opcode = event->GetInt32("opcode", -1); + if ((opcode == B_STAT_CHANGED + && (event->GetInt32("fields", 0) & B_STAT_MODIFICATION_TIME) == 0) + || opcode != B_ENTRY_REMOVED) return; RecursiveLocker locker(sLock);