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:
@@ -60,7 +60,6 @@ struct device_event {
|
|||||||
dev_t device;
|
dev_t device;
|
||||||
ino_t directory;
|
ino_t directory;
|
||||||
ino_t node;
|
ino_t node;
|
||||||
NotificationListener* listener;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -159,7 +158,29 @@ public:
|
|||||||
deviceEvent->device = event->GetInt32("device", -1);
|
deviceEvent->device = event->GetInt32("device", -1);
|
||||||
deviceEvent->directory = event->GetInt64("directory", -1);
|
deviceEvent->directory = event->GetInt64("directory", -1);
|
||||||
deviceEvent->node = event->GetInt64("node", -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...
|
// TODO: a real in-kernel DPC mechanism would be preferred...
|
||||||
thread_id thread = spawn_kernel_thread(_HandleDeviceEvent,
|
thread_id thread = spawn_kernel_thread(_HandleDeviceEvent,
|
||||||
@@ -180,21 +201,7 @@ public:
|
|||||||
{
|
{
|
||||||
device_event* event = (device_event*)_event;
|
device_event* event = (device_event*)_event;
|
||||||
|
|
||||||
struct stat st;
|
if (strcmp(event->name, "raw") == 0) {
|
||||||
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) {
|
|
||||||
// a new raw device was added/removed
|
// a new raw device was added/removed
|
||||||
KPath path(B_PATH_NAME_LENGTH + 1);
|
KPath path(B_PATH_NAME_LENGTH + 1);
|
||||||
if (path.InitCheck() != B_OK
|
if (path.InitCheck() != B_OK
|
||||||
@@ -206,7 +213,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
path.UnlockBuffer();
|
path.UnlockBuffer();
|
||||||
|
|
||||||
if (event->opcode == B_ENTRY_CREATED)
|
if (event->opcode == B_ENTRY_CREATED)
|
||||||
KDiskDeviceManager::Default()->CreateDevice(path.Path());
|
KDiskDeviceManager::Default()->CreateDevice(path.Path());
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in New Issue
Block a user