* 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
This commit is contained in:
@@ -108,6 +108,8 @@ struct path_entry : DoublyLinkedListLinkImpl<path_entry> {
|
|||||||
char path[B_PATH_NAME_LENGTH];
|
char path[B_PATH_NAME_LENGTH];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef DoublyLinkedList<path_entry> EntryList;
|
||||||
|
|
||||||
struct driver_entry : public DoublyLinkedListLinkImpl<driver_entry> {
|
struct driver_entry : public DoublyLinkedListLinkImpl<driver_entry> {
|
||||||
char* path;
|
char* path;
|
||||||
dev_t device;
|
dev_t device;
|
||||||
@@ -191,8 +193,8 @@ static status_t load_driver(legacy_driver *driver);
|
|||||||
static hash_table* sDriverHash;
|
static hash_table* sDriverHash;
|
||||||
static DriverWatcher sDriverWatcher;
|
static DriverWatcher sDriverWatcher;
|
||||||
static int32 sDriverEvents;
|
static int32 sDriverEvents;
|
||||||
static DoublyLinkedList<path_entry> sDriversToAdd;
|
static EntryList sDriversToAdd;
|
||||||
static DoublyLinkedList<path_entry> sDriversToRemove;
|
static EntryList sDriversToRemove;
|
||||||
static mutex sDriversListLock = MUTEX_INITIALIZER("driversList");
|
static mutex sDriversListLock = MUTEX_INITIALIZER("driversList");
|
||||||
static DirectoryWatcher sDirectoryWatcher;
|
static DirectoryWatcher sDirectoryWatcher;
|
||||||
static DirectoryNodeHash sDirectoryNodeHash;
|
static DirectoryNodeHash sDirectoryNodeHash;
|
||||||
@@ -581,7 +583,7 @@ add_driver(const char *path, image_id image)
|
|||||||
|
|
||||||
hash_insert(sDriverHash, driver);
|
hash_insert(sDriverHash, driver);
|
||||||
if (stat.st_dev > 0) {
|
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);
|
sDriverWatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,8 +614,19 @@ reload_driver(legacy_driver *driver)
|
|||||||
|
|
||||||
unload_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);
|
status_t status = load_driver(driver);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
unpublish_driver(driver);
|
unpublish_driver(driver);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -691,8 +704,10 @@ void
|
|||||||
DriverWatcher::EventOccured(NotificationService& service,
|
DriverWatcher::EventOccured(NotificationService& service,
|
||||||
const KMessage* event)
|
const KMessage* event)
|
||||||
{
|
{
|
||||||
if (event->GetInt32("opcode", -1) != B_STAT_CHANGED
|
int32 opcode = event->GetInt32("opcode", -1);
|
||||||
|| (event->GetInt32("fields", 0) & B_STAT_MODIFICATION_TIME) == 0)
|
if ((opcode == B_STAT_CHANGED
|
||||||
|
&& (event->GetInt32("fields", 0) & B_STAT_MODIFICATION_TIME) == 0)
|
||||||
|
|| opcode != B_ENTRY_REMOVED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RecursiveLocker locker(sLock);
|
RecursiveLocker locker(sLock);
|
||||||
|
|||||||
Reference in New Issue
Block a user