* Added new devfs_unpublish_device() that gets a BaseDevice instead of a path.

* Added inode ID member to BaseDevice to make this possible.
* Removed unused and unmaintained legacy_driver::devices_published field.
* Implemented legacy driver's unpublish_driver().
* Reenabled legacy driver reloading on changes.
* Renamed devfs_driver_{added|removed}() to driver_{added|removed}(), and
  made them private.
* Simplified deletion of device_node lists (no need to use an iterator here),
  added device unpublishing.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27033 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-08-18 11:07:47 +00:00
parent aac7507616
commit c35ab0c38d
5 changed files with 86 additions and 110 deletions
@@ -14,6 +14,9 @@ public:
BaseDevice(); BaseDevice();
virtual ~BaseDevice(); virtual ~BaseDevice();
void SetID(ino_t id) { fID = id; }
ino_t ID() const { return fID; }
device_node* Node() const { return fNode; } device_node* Node() const { return fNode; }
virtual status_t InitDevice(); virtual status_t InitDevice();
@@ -50,6 +53,7 @@ public:
status_t Free(void* cookie); status_t Free(void* cookie);
protected: protected:
ino_t fID;
device_node* fNode; device_node* fNode;
int32 fInitialized; int32 fInitialized;
device_module_info* fDeviceModule; device_module_info* fDeviceModule;
+22 -7
View File
@@ -483,13 +483,6 @@ unpublish_node(struct devfs *fs, devfs_vnode *node, mode_t type)
status = remove_vnode(fs->volume, node->id); status = remove_vnode(fs->volume, node->id);
#if 0
if (status == B_OK && S_ISCHR(node->stream.type)
&& node->stream.u.dev.driver != NULL) {
node->stream.u.dev.driver->devices_published--;
}
#endif
out: out:
recursive_lock_unlock(&fs->lock); recursive_lock_unlock(&fs->lock);
return status; return status;
@@ -2082,6 +2075,9 @@ devfs_unpublish_device(const char* path, bool disconnect)
} }
// #pragma mark - device_manager private API
status_t status_t
devfs_publish_device(const char* path, BaseDevice* device) devfs_publish_device(const char* path, BaseDevice* device)
{ {
@@ -2089,6 +2085,25 @@ devfs_publish_device(const char* path, BaseDevice* device)
} }
status_t
devfs_unpublish_device(BaseDevice* device, bool disconnect)
{
devfs_vnode* node;
status_t status = get_vnode(sDeviceFileSystem->volume, device->ID(),
(void**)&node);
if (status != B_OK)
return status;
status = unpublish_node(sDeviceFileSystem, node, S_IFCHR);
if (status == B_OK && disconnect)
vfs_disconnect_vnode(sDeviceFileSystem->id, node->id);
put_vnode(sDeviceFileSystem->volume, node->id);
return status;
}
// #pragma mark - support API for legacy drivers // #pragma mark - support API for legacy drivers
@@ -12,6 +12,7 @@
class BaseDevice; class BaseDevice;
status_t devfs_publish_device(const char* path, BaseDevice* device); status_t devfs_publish_device(const char* path, BaseDevice* device);
status_t devfs_unpublish_device(BaseDevice* device, bool disconnect);
status_t devfs_get_device(dev_t device, ino_t node, BaseDevice** _device); status_t devfs_get_device(dev_t device, ino_t node, BaseDevice** _device);
#endif /* DEVFS_PRIVATE_H */ #endif /* DEVFS_PRIVATE_H */
@@ -1156,35 +1156,23 @@ device_node::~device_node()
} }
// Delete children // Delete children
NodeList::Iterator nodeIterator = fChildren.GetIterator(); while (device_node* child = fChildren.RemoveHead()) {
while (nodeIterator.HasNext()) {
device_node* child = nodeIterator.Next();
nodeIterator.Remove();
delete child; delete child;
} }
// Delete devices // Delete devices
DeviceList::Iterator deviceIterator = fDevices.GetIterator(); while (Device* device = fDevices.RemoveHead()) {
while (deviceIterator.HasNext()) { devfs_unpublish_device(device, true);
Device* device = deviceIterator.Next();
deviceIterator.Remove();
// TODO: unpublish!
delete device; delete device;
} }
// Delete attributes // Delete attributes
AttributeList::Iterator attrIterator = fAttributes.GetIterator(); while (device_attr_private* attr = fAttributes.RemoveHead()) {
while (attrIterator.HasNext()) {
device_attr_private* attr = attrIterator.Next();
attrIterator.Remove();
delete attr; delete attr;
} }
// Delete resources // Delete resources
ResourceList::Iterator resourceIterator = fResources.GetIterator(); while (io_resource_private* resource = fResources.RemoveHead()) {
while (resourceIterator.HasNext()) {
io_resource_private* resource = resourceIterator.Next();
resourceIterator.Remove();
delete resource; delete resource;
} }
@@ -80,7 +80,6 @@ struct legacy_driver {
ino_t node; ino_t node;
time_t last_modified; time_t last_modified;
image_id image; image_id image;
uint32 devices_published;
uint32 devices_used; uint32 devices_used;
bool binary_updated; bool binary_updated;
int32 priority; int32 priority;
@@ -454,42 +453,14 @@ unload_driver(legacy_driver *driver)
} }
/*! Collects all devices belonging to the \a driver and unpublishs them. /*! Unpublishes all devices belonging to the \a driver. */
*/
static void static void
unpublish_driver(legacy_driver *driver) unpublish_driver(legacy_driver *driver)
{ {
// Iterate through all nodes until all devices of this driver have while (LegacyDevice* device = driver->devices.RemoveHead()) {
// been unpublished devfs_unpublish_device(device, true);
delete device;
dprintf("IMPLEMENT unpublish_driver()!\n");
#if 0
while (driver->devices_published > 0) {
struct hash_iterator i;
hash_open(sDeviceFileSystem->vnode_hash, &i);
while (true) {
devfs_vnode *vnode = (devfs_vnode *)hash_next(
sDeviceFileSystem->vnode_hash, &i);
if (vnode == NULL)
break;
if (S_ISCHR(vnode->stream.type)
&& vnode->stream.u.dev.driver == driver) {
void *dummy;
get_vnode(sDeviceFileSystem->volume, vnode->id, &dummy);
// We need to get/put the node, so that it is
// actually removed
unpublish_node(sDeviceFileSystem, vnode, S_IFCHR);
put_vnode(sDeviceFileSystem->volume, vnode->id);
break;
}
}
hash_close(sDeviceFileSystem->vnode_hash, &i, false);
} }
#endif
} }
@@ -618,7 +589,6 @@ add_driver(const char *path, image_id image)
driver->node = stat.st_ino; driver->node = stat.st_ino;
driver->image = image; driver->image = image;
driver->last_modified = stat.st_mtime; driver->last_modified = stat.st_mtime;
driver->devices_published = 0;
driver->devices_used = 0; driver->devices_used = 0;
driver->binary_updated = false; driver->binary_updated = false;
driver->priority = priority; driver->priority = priority;
@@ -708,6 +678,51 @@ handle_driver_events(void */*_fs*/, int /*iteration*/)
} }
static void
driver_added(const char *path)
{
int32 priority = get_priority(path);
RecursiveLocker locker(sLock);
legacy_driver *driver = (legacy_driver *)hash_lookup(sDriverHash,
get_leaf(path));
if (driver == NULL) {
// Add the driver to our list
path_entry *entry = new(std::nothrow) path_entry;
if (entry == NULL)
return;
strlcpy(entry->path, path, sizeof(entry->path));
sDriversToAdd.Add(entry);
} else {
// Update the driver if it is affected by the new entry
if (priority < driver->priority)
return;
driver->binary_updated = true;
}
atomic_add(&sDriverEvents, 1);
}
static void
driver_removed(const char* path)
{
int32 priority = get_priority(path);
RecursiveLocker locker(sLock);
legacy_driver* driver = (legacy_driver*)hash_lookup(sDriverHash,
get_leaf(path));
if (driver == NULL || priority < driver->priority)
return;
driver->binary_updated = true;
atomic_add(&sDriverEvents, 1);
}
// #pragma mark - DriverWatcher // #pragma mark - DriverWatcher
@@ -737,7 +752,7 @@ DriverWatcher::EventOccured(NotificationService& service,
return; return;
driver->binary_updated = true; driver->binary_updated = true;
//dprintf("%s: devices published %ld, used %ld\n", driver->name, driver->devices_published, driver->devices_used);
if (driver->devices_used == 0) { if (driver->devices_used == 0) {
// trigger a reload of the driver // trigger a reload of the driver
atomic_add(&sDriverEvents, 1); atomic_add(&sDriverEvents, 1);
@@ -764,7 +779,7 @@ dump_driver(int argc, char** argv)
kprintf("%p %5ld %3ld %5ld %c %3ld %s\n", driver, kprintf("%p %5ld %3ld %5ld %c %3ld %s\n", driver,
driver->image < 0 ? -1 : driver->image, driver->image < 0 ? -1 : driver->image,
driver->devices_used, driver->devices_published, driver->devices_used, driver->devices.Size(),
driver->binary_updated ? 'U' : ' ', driver->priority, driver->binary_updated ? 'U' : ' ', driver->priority,
driver->name); driver->name);
} }
@@ -792,7 +807,7 @@ dump_driver(int argc, char** argv)
kprintf(" node: %Ld\n", driver->node); kprintf(" node: %Ld\n", driver->node);
kprintf(" last modified: %ld\n", driver->last_modified); kprintf(" last modified: %ld\n", driver->last_modified);
kprintf(" devs used: %ld\n", driver->devices_used); kprintf(" devs used: %ld\n", driver->devices_used);
kprintf(" devs published: %ld\n", driver->devices_published); kprintf(" devs published: %ld\n", driver->devices.Size());
kprintf(" binary updated: %d\n", driver->binary_updated); kprintf(" binary updated: %d\n", driver->binary_updated);
kprintf(" priority: %ld\n", driver->priority); kprintf(" priority: %ld\n", driver->priority);
kprintf(" api version: %ld\n", driver->api_version); kprintf(" api version: %ld\n", driver->api_version);
@@ -988,16 +1003,14 @@ DirectoryWatcher::EventOccured(NotificationService& service,
dprintf("driver \"%s\" %s\n", path.Leaf(), dprintf("driver \"%s\" %s\n", path.Leaf(),
opcode == B_ENTRY_CREATED ? "added" : "removed"); opcode == B_ENTRY_CREATED ? "added" : "removed");
#if 0
switch (opcode) { switch (opcode) {
case B_ENTRY_CREATED: case B_ENTRY_CREATED:
devfs_driver_added(path.Path()); driver_added(path.Path());
break; break;
case B_ENTRY_REMOVED: case B_ENTRY_REMOVED:
devfs_driver_removed(path.Path()); driver_removed(path.Path());
break; break;
} }
#endif
} }
@@ -1306,51 +1319,6 @@ legacy_driver_add(const char* path)
} }
extern "C" void
devfs_driver_added(const char *path)
{
int32 priority = get_priority(path);
RecursiveLocker locker(sLock);
legacy_driver *driver = (legacy_driver *)hash_lookup(sDriverHash,
get_leaf(path));
if (driver == NULL) {
// Add the driver to our list
path_entry *entry = new(std::nothrow) path_entry;
if (entry == NULL)
return;
strlcpy(entry->path, path, sizeof(entry->path));
sDriversToAdd.Add(entry);
} else {
// Update the driver if it is affected by the new entry
if (priority < driver->priority)
return;
driver->binary_updated = true;
}
atomic_add(&sDriverEvents, 1);
}
extern "C" void
devfs_driver_removed(const char* path)
{
int32 priority = get_priority(path);
RecursiveLocker locker(sLock);
legacy_driver* driver = (legacy_driver*)hash_lookup(sDriverHash,
get_leaf(path));
if (driver == NULL || priority < driver->priority)
return;
driver->binary_updated = true;
atomic_add(&sDriverEvents, 1);
}
extern "C" status_t extern "C" status_t
legacy_driver_publish(const char *path, device_hooks *hooks) legacy_driver_publish(const char *path, device_hooks *hooks)
{ {