* 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

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
@ -33,3 +33,9 @@ void
BaseDevice::UninitDevice()
{
}
void
BaseDevice::Removed()
{
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
#ifndef BASE_DEVICE_H
@ -22,6 +22,8 @@ public:
virtual status_t InitDevice();
virtual void UninitDevice();
virtual void Removed();
device_module_info* Module() const { return fDeviceModule; }
void* Data() const { return fDeviceData; }

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2008, 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.
*
* 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);
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
// not free the device info as it was inherited from the raw
// device and is still in use there

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2008-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*/
@ -84,8 +84,14 @@ public:
virtual status_t InitDevice();
virtual void UninitDevice();
virtual void Removed();
void SetRemovedFromParent(bool removed)
{ fRemovedFromParent = removed; }
private:
const char* fModuleName;
bool fRemovedFromParent;
};
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)
:
fRemovedFromParent(false)
{
fNode = node;
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
@ -1201,8 +1221,8 @@ device_node::~device_node()
// Delete devices
while (Device* device = fDevices.RemoveHead()) {
device->SetRemovedFromParent(true);
devfs_unpublish_device(device, true);
delete device;
}
// Delete attributes

View File

@ -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.
*/
@ -54,6 +54,8 @@ public:
virtual status_t InitDevice();
virtual void UninitDevice();
virtual void Removed();
void SetHooks(device_hooks* hooks);
legacy_driver* Driver() const { return fDriver; }
@ -67,11 +69,16 @@ public:
bool Republished() const { return fRepublished; }
void SetRepublished(bool republished)
{ fRepublished = republished; }
void SetRemovedFromParent(bool removed)
{ fRemovedFromParent = removed; }
private:
legacy_driver* fDriver;
const char* fPath;
device_hooks* fHooks;
bool fRepublished;
bool fRemovedFromParent;
};
typedef DoublyLinkedList<LegacyDevice> DeviceList;
@ -284,9 +291,9 @@ republish_driver(legacy_driver* driver)
TRACE(("devfs: unpublishing no more present \"%s\"\n", device->Path()));
iterator.Remove();
device->SetRemovedFromParent(true);
devfs_unpublish_device(device, true);
delete device;
}
if (exported == 0) {
@ -430,8 +437,8 @@ static void
unpublish_driver(legacy_driver *driver)
{
while (LegacyDevice* device = driver->devices.RemoveHead()) {
if (devfs_unpublish_device(device, true) == B_OK)
delete device;
device->SetRemovedFromParent(true);
devfs_unpublish_device(device, true);
}
}
@ -1109,7 +1116,8 @@ LegacyDevice::LegacyDevice(legacy_driver* driver, const char* path,
device_hooks* hooks)
:
fDriver(driver),
fRepublished(true)
fRepublished(true),
fRemovedFromParent(false)
{
fDeviceModule = (device_module_info*)malloc(sizeof(device_module_info));
if (fDeviceModule != NULL)
@ -1171,6 +1179,18 @@ LegacyDevice::UninitDevice()
}
void
LegacyDevice::Removed()
{
RecursiveLocker _(sLock);
if (!fRemovedFromParent)
fDriver->devices.Remove(this);
delete this;
}
void
LegacyDevice::SetHooks(device_hooks* hooks)
{