* Instead of deleting the device directly, we now only remove it from its

parent.
* Additionally, when a vnode is deleted, the new BaseDevice::Removed() method is
  called that will remove the device from its parent if needed, and delete it
  then.
* This should fix #3856.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30726 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-05-12 20:03:58 +00:00
parent 3aa9a86343
commit 6015793f57
5 changed files with 61 additions and 10 deletions
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2008-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -33,3 +33,9 @@ void
BaseDevice::UninitDevice() BaseDevice::UninitDevice()
{ {
} }
void
BaseDevice::Removed()
{
}
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2008-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef BASE_DEVICE_H #ifndef BASE_DEVICE_H
@@ -22,6 +22,8 @@ public:
virtual status_t InitDevice(); virtual status_t InitDevice();
virtual void UninitDevice(); virtual void UninitDevice();
virtual void Removed();
device_module_info* Module() const { return fDeviceModule; } device_module_info* Module() const { return fDeviceModule; }
void* Data() const { return fDeviceData; } void* Data() const { return fDeviceData; }
+4 -1
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2002-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
@@ -252,6 +252,9 @@ devfs_delete_vnode(struct devfs* fs, struct devfs_vnode* vnode,
hash_remove(fs->vnode_hash, vnode); hash_remove(fs->vnode_hash, vnode);
if (S_ISCHR(vnode->stream.type)) { if (S_ISCHR(vnode->stream.type)) {
// pass the call through to the underlying device
vnode->stream.u.dev.device->Removed();
// for partitions, we have to release the raw device but must // for partitions, we have to release the raw device but must
// not free the device info as it was inherited from the raw // not free the device info as it was inherited from the raw
// device and is still in use there // device and is still in use there
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008, Axel Dörfler, [email protected]. All rights reserved. * Copyright 2008-2009, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -84,8 +84,14 @@ public:
virtual status_t InitDevice(); virtual status_t InitDevice();
virtual void UninitDevice(); virtual void UninitDevice();
virtual void Removed();
void SetRemovedFromParent(bool removed)
{ fRemovedFromParent = removed; }
private: private:
const char* fModuleName; const char* fModuleName;
bool fRemovedFromParent;
}; };
typedef DoublyLinkedList<Device> DeviceList; typedef DoublyLinkedList<Device> DeviceList;
@@ -1057,6 +1063,8 @@ device_attr_private::Compare(const device_attr* attrA, const device_attr *attrB)
Device::Device(device_node* node, const char* moduleName) Device::Device(device_node* node, const char* moduleName)
:
fRemovedFromParent(false)
{ {
fNode = node; fNode = node;
fModuleName = strdup(moduleName); fModuleName = strdup(moduleName);
@@ -1144,6 +1152,18 @@ Device::UninitDevice()
} }
void
Device::Removed()
{
RecursiveLocker _(sLock);
if (!fRemovedFromParent)
fNode->RemoveDevice(this);
delete this;
}
// #pragma mark - device_node // #pragma mark - device_node
@@ -1201,8 +1221,8 @@ device_node::~device_node()
// Delete devices // Delete devices
while (Device* device = fDevices.RemoveHead()) { while (Device* device = fDevices.RemoveHead()) {
device->SetRemovedFromParent(true);
devfs_unpublish_device(device, true); devfs_unpublish_device(device, true);
delete device;
} }
// Delete attributes // Delete attributes
@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
@@ -54,6 +54,8 @@ public:
virtual status_t InitDevice(); virtual status_t InitDevice();
virtual void UninitDevice(); virtual void UninitDevice();
virtual void Removed();
void SetHooks(device_hooks* hooks); void SetHooks(device_hooks* hooks);
legacy_driver* Driver() const { return fDriver; } legacy_driver* Driver() const { return fDriver; }
@@ -67,11 +69,16 @@ public:
bool Republished() const { return fRepublished; } bool Republished() const { return fRepublished; }
void SetRepublished(bool republished) void SetRepublished(bool republished)
{ fRepublished = republished; } { fRepublished = republished; }
void SetRemovedFromParent(bool removed)
{ fRemovedFromParent = removed; }
private: private:
legacy_driver* fDriver; legacy_driver* fDriver;
const char* fPath; const char* fPath;
device_hooks* fHooks; device_hooks* fHooks;
bool fRepublished; bool fRepublished;
bool fRemovedFromParent;
}; };
typedef DoublyLinkedList<LegacyDevice> DeviceList; typedef DoublyLinkedList<LegacyDevice> DeviceList;
@@ -284,9 +291,9 @@ republish_driver(legacy_driver* driver)
TRACE(("devfs: unpublishing no more present \"%s\"\n", device->Path())); TRACE(("devfs: unpublishing no more present \"%s\"\n", device->Path()));
iterator.Remove(); iterator.Remove();
device->SetRemovedFromParent(true);
devfs_unpublish_device(device, true); devfs_unpublish_device(device, true);
delete device;
} }
if (exported == 0) { if (exported == 0) {
@@ -430,8 +437,8 @@ static void
unpublish_driver(legacy_driver *driver) unpublish_driver(legacy_driver *driver)
{ {
while (LegacyDevice* device = driver->devices.RemoveHead()) { while (LegacyDevice* device = driver->devices.RemoveHead()) {
if (devfs_unpublish_device(device, true) == B_OK) device->SetRemovedFromParent(true);
delete device; devfs_unpublish_device(device, true);
} }
} }
@@ -1109,7 +1116,8 @@ LegacyDevice::LegacyDevice(legacy_driver* driver, const char* path,
device_hooks* hooks) device_hooks* hooks)
: :
fDriver(driver), fDriver(driver),
fRepublished(true) fRepublished(true),
fRemovedFromParent(false)
{ {
fDeviceModule = (device_module_info*)malloc(sizeof(device_module_info)); fDeviceModule = (device_module_info*)malloc(sizeof(device_module_info));
if (fDeviceModule != NULL) if (fDeviceModule != NULL)
@@ -1171,6 +1179,18 @@ LegacyDevice::UninitDevice()
} }
void
LegacyDevice::Removed()
{
RecursiveLocker _(sLock);
if (!fRemovedFromParent)
fDriver->devices.Remove(this);
delete this;
}
void void
LegacyDevice::SetHooks(device_hooks* hooks) LegacyDevice::SetHooks(device_hooks* hooks)
{ {