* Add dev_ops_remove_override() as the counterpart to dev_ops_add_override().
* Do not complain if ops->head.refs is non-zero when deleting ops,
as the ops structure might be used with other unit numbers.
* Fix a bad assertion that was leading to incorrect panics when selectively
removing dev_ops.
ndev = LIST_FIRST(&dev_hash[i]);
while ((dev = ndev) != NULL) {
ndev = LIST_NEXT(dev, si_hash);
- KKASSERT(dev->si_flags & SI_ADHOC);
if (dev->si_ops == ops &&
((u_int)dev->si_uminor & mask) == match
) {
+ KKASSERT(dev->si_flags & SI_ADHOC);
reference_dev(dev);
destroy_dev(dev);
}
return(ops);
}
+void
+dev_ops_remove_override(struct dev_ops *ops, u_int mask, u_int match)
+{
+ dev_ops_remove(ops, mask, match);
+ if (ops->head.refs) {
+ kprintf("dev_ops_remove_override: %s still has %d refs!\n",
+ ops->head.name, ops->head.refs);
+ } else {
+ bzero(ops, sizeof(*ops));
+ kfree(ops, M_DEVBUF);
+ }
+}
+
/*
* Remove all matching dev_ops entries from the dev_ops_array[] major
* array so no new user opens can be performed, and destroy all devices
kfree(rbmaj, M_DEVBUF);
}
+#if 0
+ /*
+ * The same ops might be used with multiple devices, so don't
+ * complain if the ref count is non-zero.
+ */
if (ops->head.refs != 0) {
kprintf("%s(%d)[%08x/%08x]: Warning: dev_ops_remove() called "
"while %d device refs still exist!\n",
if (bootverbose)
kprintf("%s: ops removed\n", ops->head.name);
}
+#endif
return 0;
}
void
disk_destroy(struct disk *disk)
{
+ u_int match;
+
if (disk->d_dev_ops) {
- dev_ops_remove(disk->d_dev_ops, dkunitmask(),
- dkmakeunit(dkunit(disk->d_cdev)));
+ match = dkmakeunit(dkunit(disk->d_cdev));
+ dev_ops_remove_override(disk->d_dev_ops, dkunitmask(), match);
LIST_REMOVE(disk, d_list);
}
if (disk->d_raw_ops) {
- destroy_all_devs(disk->d_raw_ops, dkunitmask(),
- dkmakeunit(dkunit(disk->d_rawdev)));
+ match = dkmakeunit(dkunit(disk->d_rawdev));
+ destroy_all_devs(disk->d_raw_ops, dkunitmask(), match);
}
bzero(disk, sizeof(*disk));
}
int dev_ops_remove(struct dev_ops *, u_int mask, u_int match);
void dev_ops_release(struct dev_ops *);
struct dev_ops *dev_ops_add_override(cdev_t, struct dev_ops *, u_int, u_int);
+void dev_ops_remove_override(struct dev_ops *ops, u_int mask, u_int match);
struct dev_ops *dev_ops_intercept(cdev_t, struct dev_ops *);
void dev_ops_restore(cdev_t, struct dev_ops *);