* Simplified devfs_rescan_driver() since the driver hash is now based on the

name of the drivers.
* Allow driver::publish_devices() to return NULL to hint that it has no devices
  to publish anymore (ie. existing devices will be unpublished in this case).
* republish_driver() now also calls load_driver() in case the driver is not
  loaded.
* publish_device() and unpublish_node() now maintain the new
  driver_entry::devices_published field, so we always know how many devices
  a driver has now.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24016 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-02-19 14:59:30 +00:00
parent 644c84564a
commit 350e0b20a5

View File

@ -130,6 +130,7 @@ struct driver_entry {
ino_t node;
time_t last_modified;
image_id image;
uint32 devices_published;
// driver image information
int32 *api_version;
@ -781,6 +782,11 @@ unpublish_node(struct devfs *fs, devfs_vnode *node, mode_t type)
status = remove_vnode(fs->id, node->id);
if (status == B_OK && S_ISCHR(node->stream.type)
&& node->stream.u.dev.driver != NULL) {
node->stream.u.dev.driver->devices_published--;
}
out:
recursive_lock_unlock(&fs->lock);
return status;
@ -1007,6 +1013,9 @@ publish_device(struct devfs *fs, const char *path, device_node_info *deviceNode,
node->stream.u.dev.driver = driver;
node->stream.u.dev.ops = ops;
if (driver != NULL)
driver->devices_published++;
// every raw disk gets an I/O scheduler object attached
// ToDo: the driver should ask for a scheduler (ie. using its devfs node attributes)
if (isDisk && !strcmp(node->name, "raw")) {
@ -1015,41 +1024,49 @@ publish_device(struct devfs *fs, const char *path, device_node_info *deviceNode,
return B_NO_MEMORY;
}
return status;
return B_OK;
}
/*! Collects all published devices of a driver, compares them to what the
driver would publish now, and then publishes/unpublishes the devices
as needed.
If the driver does not publish any devices anymore, it is unloaded.
*/
static status_t
republish_driver(driver_entry *driver)
{
if (driver->image < 0)
return B_NO_INIT;
if (driver->image < 0) {
// The driver is not yet loaded - go through the normal load procedure
return load_driver(driver);
}
RecursiveLocker locker(&sDeviceFileSystem->lock);
// build the list of currently present devices by iterating through all
// present nodes
// build the list of currently present devices of this driver
// by iterating through all present nodes
struct hash_iterator i;
hash_open(sDeviceFileSystem->vnode_hash, &i);
devfs_vnode *vnode = (devfs_vnode *)hash_next(
sDeviceFileSystem->vnode_hash, &i);
DoublyLinkedList<node_path_entry> currentNodes;
while (vnode) {
if (S_ISCHR(vnode->stream.type)) {
if (vnode->stream.u.dev.driver == driver) {
node_path_entry *path = new(std::nothrow) node_path_entry;
if (!path) {
while ((path = currentNodes.RemoveHead()))
delete path;
hash_close(sDeviceFileSystem->vnode_hash, &i, false);
return B_NO_MEMORY;
}
while (true) {
devfs_vnode *vnode = (devfs_vnode *)hash_next(
sDeviceFileSystem->vnode_hash, &i);
if (vnode == NULL)
break;
get_device_name(vnode, path->path, sizeof(path->path));
currentNodes.Add(path);
if (S_ISCHR(vnode->stream.type)
&& vnode->stream.u.dev.driver == driver) {
node_path_entry *path = new(std::nothrow) node_path_entry;
if (!path) {
while ((path = currentNodes.RemoveHead()))
delete path;
hash_close(sDeviceFileSystem->vnode_hash, &i, false);
return B_NO_MEMORY;
}
get_device_name(vnode, path->path, sizeof(path->path));
currentNodes.Add(path);
}
vnode = (devfs_vnode *)hash_next(sDeviceFileSystem->vnode_hash, &i);
@ -1058,15 +1075,9 @@ republish_driver(driver_entry *driver)
// now ask the driver for it's currently published devices
const char **devicePaths = driver->publish_devices();
if (devicePaths == NULL) {
node_path_entry *entry = NULL;
while ((entry = currentNodes.RemoveHead()))
delete entry;
return B_ERROR;
}
int32 exported = 0;
for (; devicePaths[0]; devicePaths++) {
for (; devicePaths != NULL && devicePaths[0]; devicePaths++) {
bool present = false;
node_path_entry *entry = currentNodes.Head();
while (entry) {
@ -2620,33 +2631,11 @@ devfs_rescan_driver(const char *driverName)
RecursiveLocker locker(&sDeviceFileSystem->lock);
// iterate over the drivers and search a matching driverName
struct hash_iterator i;
hash_open(sDeviceFileSystem->driver_hash, &i);
driver_entry *driver = (driver_entry *)hash_lookup(
sDeviceFileSystem->driver_hash, driverName);
if (driver == NULL)
return B_ENTRY_NOT_FOUND;
driver_entry *driver = (driver_entry *)hash_next(
sDeviceFileSystem->driver_hash, &i);
while (driver) {
const char *name = strrchr(driver->path, '/');
if (name == NULL)
name = driver->path;
else
name++;
if (!strcmp(name, driverName)) {
hash_close(sDeviceFileSystem->driver_hash, &i, false);
if (driver->image < 0) {
// The driver is not yet loaded
return load_driver(driver);
} else {
// The driver is loaded, just republish its entries
return republish_driver(driver);
}
}
driver = (driver_entry *)hash_next(sDeviceFileSystem->driver_hash, &i);
}
hash_close(sDeviceFileSystem->driver_hash, &i, false);
return B_ENTRY_NOT_FOUND;
// Republish the driver's entries
return republish_driver(driver);
}