Fix regression introduced in r32526: registering the device watcher for node monitoring needs to happen synchronously, otherwise a race condition occurs: unless you're very lucky, the event for creating the raw device would happen before the async thread had a change to add the node monitor, and as such the listener would miss it, and never trigger a filesystem/partition scan. As a result, whether or not adding a USB stick would actually show a volume was essentially russian roulette. Fixes ticket #4345.

+alphabranch


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32820 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Rene Gollent
2009-08-29 21:49:59 +00:00
parent adbf8b25f8
commit 92e143c14a
@@ -60,7 +60,6 @@ struct device_event {
dev_t device;
ino_t directory;
ino_t node;
NotificationListener* listener;
};
@@ -159,7 +158,29 @@ public:
deviceEvent->device = event->GetInt32("device", -1);
deviceEvent->directory = event->GetInt64("directory", -1);
deviceEvent->node = event->GetInt64("node", -1);
deviceEvent->listener = this;
struct stat st;
if (vfs_stat_node_ref(deviceEvent->device,
deviceEvent->node, &st) != 0) {
delete deviceEvent;
break;
}
if (S_ISDIR(st.st_mode)) {
if (opcode == B_ENTRY_CREATED) {
add_node_listener(
deviceEvent->device,
deviceEvent->node,
B_WATCH_DIRECTORY,
*this);
} else {
remove_node_listener(
deviceEvent->device,
deviceEvent->node,
*this);
}
delete deviceEvent;
break;
}
// TODO: a real in-kernel DPC mechanism would be preferred...
thread_id thread = spawn_kernel_thread(_HandleDeviceEvent,
@@ -179,22 +200,8 @@ public:
static status_t _HandleDeviceEvent(void* _event)
{
device_event* event = (device_event*)_event;
struct stat st;
if (vfs_stat_node_ref(event->device, event->node, &st) != 0) {
delete event;
return B_ERROR;
}
if (S_ISDIR(st.st_mode)) {
if (event->opcode == B_ENTRY_CREATED) {
add_node_listener(event->device, event->node, B_WATCH_DIRECTORY,
*event->listener);
} else {
remove_node_listener(event->device, event->node,
*event->listener);
}
} else if (strcmp(event->name, "raw") == 0) {
if (strcmp(event->name, "raw") == 0) {
// a new raw device was added/removed
KPath path(B_PATH_NAME_LENGTH + 1);
if (path.InitCheck() != B_OK
@@ -206,7 +213,6 @@ public:
}
path.UnlockBuffer();
if (event->opcode == B_ENTRY_CREATED)
KDiskDeviceManager::Default()->CreateDevice(path.Path());
else