diff --git a/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h b/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h index cf4a62d964..d604828007 100644 --- a/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h +++ b/headers/private/kernel/disk_device_manager/KDiskDeviceManager.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007, Haiku, Inc. All rights reserved. + * Copyright 2004-2009, Haiku, Inc. All rights reserved. * Copyright 2003-2004, Ingo Weinhold, bonefish@cs.tu-berlin.de. All rights reserved. * * Distributed under the terms of the MIT License. @@ -10,6 +10,7 @@ #include #include +#include namespace BPrivate { @@ -40,6 +41,9 @@ public: // Disk Device / Partition Management + DefaultUserNotificationService& Notifications(); + void Notify(const KMessage& event, uint32 eventMask); + // manager must be locked KDiskDevice *FindDevice(const char *path); KDiskDevice *FindDevice(partition_id id, bool deviceOnly = true); @@ -104,6 +108,7 @@ private: struct PartitionSet; class DiskSystemWatcher; class DeviceWatcher; + class DiskNotifications; static status_t _CheckMediaStatusDaemon(void* self); status_t _CheckMediaStatus(); @@ -126,6 +131,8 @@ private: status_t _AddRemoveMonitoring(const char *path, bool add); + void _NotifyDeviceEvent(KDiskDevice* device, int32 event, uint32 mask); + BLocker fLock; DeviceMap *fDevices; PartitionMap *fPartitions; @@ -135,6 +142,7 @@ private: volatile bool fTerminating; DiskSystemWatcher *fDiskSystemWatcher; DeviceWatcher *fDeviceWatcher; + DiskNotifications* fNotifications; static KDiskDeviceManager *sDefaultManager; }; diff --git a/headers/private/kernel/disk_device_manager/ddm_userland_interface.h b/headers/private/kernel/disk_device_manager/ddm_userland_interface.h index 93233e3b23..197ac53a65 100644 --- a/headers/private/kernel/disk_device_manager/ddm_userland_interface.h +++ b/headers/private/kernel/disk_device_manager/ddm_userland_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008, Haiku Inc. + * Copyright 2003-2009, Haiku Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -90,6 +90,10 @@ status_t _user_delete_child_partition(partition_id partitionID, int32* changeCounter, partition_id childID, int32 childChangeCounter); +// change notification +status_t _user_start_watching_disks(uint32 eventMask, port_id port, int32 token); +status_t _user_stop_watching_disks(port_id port, int32 token); + #ifdef __cplusplus } #endif diff --git a/headers/private/system/syscalls.h b/headers/private/system/syscalls.h index 4944b9eaab..e9f0cddce7 100644 --- a/headers/private/system/syscalls.h +++ b/headers/private/system/syscalls.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Haiku Inc. All rights reserved. + * Copyright 2004-2009, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _SYSTEM_SYSCALLS_H @@ -512,15 +512,10 @@ extern status_t _kern_delete_child_partition(partition_id partitionID, int32* changeCounter, partition_id childID, int32 childChangeCounter); -#if 0 - -// watching -status_t start_disk_device_watching(port_id, int32 token, uint32 flags); -status_t start_disk_device_job_watching(disk_job_id job, port_id, int32 token, - uint32 flags); -status_t stop_disk_device_watching(port_id, int32 token); - -#endif // 0 +// disk change notification +extern status_t _kern_start_watching_disks(uint32 eventMask, port_id port, + int32 token); +extern status_t _kern_stop_watching_disks(port_id port, int32 token); // The end mark for gensyscallinfos. diff --git a/src/kits/storage/disk_device/DiskDeviceRoster.cpp b/src/kits/storage/disk_device/DiskDeviceRoster.cpp index 5fa873bb2c..c7b219fe70 100644 --- a/src/kits/storage/disk_device/DiskDeviceRoster.cpp +++ b/src/kits/storage/disk_device/DiskDeviceRoster.cpp @@ -22,6 +22,8 @@ #include #include +#include + #include #include @@ -511,8 +513,14 @@ BDiskDeviceRoster::GetFileDeviceForPath(const char* filename, status_t BDiskDeviceRoster::StartWatching(BMessenger target, uint32 eventMask) { - // not implemented - return B_ERROR; + if (eventMask == 0) + return B_BAD_VALUE; + + BMessenger::Private messengerPrivate(target); + port_id port = messengerPrivate.Port(); + int32 token = messengerPrivate.Token(); + + return _kern_start_watching_disks(eventMask, port, token); } @@ -525,8 +533,11 @@ BDiskDeviceRoster::StartWatching(BMessenger target, uint32 eventMask) status_t BDiskDeviceRoster::StopWatching(BMessenger target) { - // not implemented - return B_ERROR; + BMessenger::Private messengerPrivate(target); + port_id port = messengerPrivate.Port(); + int32 token = messengerPrivate.Token(); + + return _kern_stop_watching_disks(port, token); } #if 0 diff --git a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp index 10c0ae6504..ed113a0a76 100644 --- a/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp +++ b/src/system/kernel/disk_device_manager/KDiskDeviceManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Haiku, Inc. All rights reserved. + * Copyright 2004-2009, Haiku, Inc. All rights reserved. * Copyright 2003-2004, Ingo Weinhold, bonefish@cs.tu-berlin.de. All rights reserved. * * Distributed under the terms of the MIT License. @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -183,19 +184,42 @@ private: }; +class KDiskDeviceManager::DiskNotifications + : public DefaultUserNotificationService { +public: + DiskNotifications() + : DefaultUserNotificationService("disk devices") + { + } + + virtual ~DiskNotifications() + { + } + +protected: + status_t _ToFlags(const KMessage& eventSpecifier, uint32& flags) + { + flags = eventSpecifier.GetInt32("flags", 0); + return B_OK; + } +}; + + // #pragma mark - KDiskDeviceManager::KDiskDeviceManager() - : fLock("disk device manager"), - fDevices(new(nothrow) DeviceMap), - fPartitions(new(nothrow) PartitionMap), - fDiskSystems(new(nothrow) DiskSystemMap), - fObsoletePartitions(new(nothrow) PartitionSet), - fMediaChecker(-1), - fTerminating(false), - fDiskSystemWatcher(NULL), - fDeviceWatcher(new(nothrow) DeviceWatcher(this)) + : + fLock("disk device manager"), + fDevices(new(nothrow) DeviceMap), + fPartitions(new(nothrow) PartitionMap), + fDiskSystems(new(nothrow) DiskSystemMap), + fObsoletePartitions(new(nothrow) PartitionSet), + fMediaChecker(-1), + fTerminating(false), + fDiskSystemWatcher(NULL), + fDeviceWatcher(new(nothrow) DeviceWatcher(this)), + fNotifications(new(nothrow) DiskNotifications) { if (InitCheck() != B_OK) return; @@ -267,7 +291,8 @@ KDiskDeviceManager::~KDiskDeviceManager() status_t KDiskDeviceManager::InitCheck() const { - if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions) + if (fPartitions == NULL || fDevices == NULL || fDiskSystems == NULL + || fObsoletePartitions == NULL || fNotifications == NULL) return B_NO_MEMORY; return fLock.Sem() >= 0 ? B_OK : fLock.Sem(); @@ -323,6 +348,20 @@ KDiskDeviceManager::Unlock() } +DefaultUserNotificationService& +KDiskDeviceManager::Notifications() +{ + return *fNotifications; +} + + +void +KDiskDeviceManager::Notify(const KMessage& event, uint32 eventMask) +{ + fNotifications->Notify(event, eventMask); +} + + KDiskDevice* KDiskDeviceManager::FindDevice(const char* path) { @@ -637,6 +676,9 @@ KDiskDeviceManager::CreateDevice(const char* path, bool* newlyCreated) _ScanPartition(device, false); device->UnmarkBusy(true); + _NotifyDeviceEvent(device, B_DEVICE_ADDED, + B_DEVICE_REQUEST_DEVICE_LIST); + if (newlyCreated) *newlyCreated = true; @@ -709,6 +751,9 @@ KDiskDeviceManager::CreateFileDevice(const char* filePath, bool* newlyCreated) _ScanPartition(device, false); device->UnmarkBusy(true); + _NotifyDeviceEvent(device, B_DEVICE_ADDED, + B_DEVICE_REQUEST_DEVICE_LIST); + if (newlyCreated) *newlyCreated = true; @@ -765,6 +810,7 @@ KDiskDeviceManager::NextDevice(int32* cookie) { if (!cookie) return NULL; + DeviceMap::Iterator it = fDevices->FindClose(*cookie, false); if (it != fDevices->End()) { KDiskDevice* device = it->Value(); @@ -787,7 +833,7 @@ KDiskDeviceManager::PartitionRemoved(KPartition* partition) { if (partition && partition->PrepareForRemoval() && fPartitions->Remove(partition->ID())) { - // If adding the partition to the obsolete list fails (due to lack + // TODO: If adding the partition to the obsolete list fails (due to lack // of memory), we can't do anything about it. We will leak memory then. fObsoletePartitions->Insert(partition); partition->MarkObsolete(); @@ -1091,8 +1137,14 @@ KDiskDeviceManager::_AddDevice(KDiskDevice* device) bool KDiskDeviceManager::_RemoveDevice(KDiskDevice* device) { - return (device && fDevices->Remove(device->ID()) - && PartitionRemoved(device)); + if (device != NULL && fDevices->Remove(device->ID()) + && PartitionRemoved(device)) { + _NotifyDeviceEvent(device, B_DEVICE_REMOVED, + B_DEVICE_REQUEST_DEVICE_LIST); + return true; + } + + return false; } @@ -1433,6 +1485,8 @@ KDiskDeviceManager::_CheckMediaStatus() dprintf("Media changed from %s\n", device->Path()); device->UpdateGeometry(); _ScanPartition(device, false); + _NotifyDeviceEvent(device, B_DEVICE_MEDIA_CHANGED, + B_DEVICE_REQUEST_DEVICE); } else if (!device->HasMedia() && hadMedia) { dprintf("Media removed from %s\n", device->Path()); } @@ -1452,3 +1506,19 @@ KDiskDeviceManager::_CheckMediaStatusDaemon(void* self) { return ((KDiskDeviceManager*)self)->_CheckMediaStatus(); } + + +void +KDiskDeviceManager::_NotifyDeviceEvent(KDiskDevice* device, int32 event, + uint32 mask) +{ + char messageBuffer[512]; + KMessage message; + message.SetTo(messageBuffer, sizeof(messageBuffer), B_DEVICE_UPDATE); + message.AddInt32("event", event); + message.AddInt32("id", device->ID()); + message.AddString("device", device->Path()); + + fNotifications->Notify(message, mask); +} + diff --git a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp index 965336eb32..60410dea19 100644 --- a/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp +++ b/src/system/kernel/disk_device_manager/ddm_userland_interface.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008, Haiku, Inc. All Rights Reserved. + * Copyright 2003-2009, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -40,7 +40,6 @@ using namespace BPrivate::DiskDevice; // TODO: Add user address checks and check return values of user_memcpy()! -// ddm_strlcpy /*! \brief Wrapper around user_strlcpy() that returns a status_t indicating appropriate success or failure. @@ -61,7 +60,6 @@ ddm_strlcpy(char *to, const char *from, size_t size, } -// copy_from_user_value template static inline status_t copy_from_user_value(Type& value, const Type* userValue) @@ -76,7 +74,6 @@ copy_from_user_value(Type& value, const Type* userValue) } -// copy_to_user_value template static inline status_t copy_to_user_value(Type* userValue, const Type& value) @@ -91,7 +88,6 @@ copy_to_user_value(Type* userValue, const Type& value) } -// UserStringParameter template struct UserStringParameter { char* value; @@ -144,7 +140,6 @@ struct UserStringParameter { }; -// UserMemoryParameter template struct UserMemoryParameter { Type* value; @@ -190,7 +185,6 @@ struct UserMemoryParameter { #if 0 -// move_descendants static void move_descendants(KPartition *partition, off_t moveBy) { @@ -203,7 +197,6 @@ move_descendants(KPartition *partition, off_t moveBy) } -// move_descendants_contents static status_t move_descendants_contents(KPartition *partition) { @@ -228,7 +221,6 @@ move_descendants_contents(KPartition *partition) #endif // 0 -// _user_get_next_disk_device_id partition_id _user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize) { @@ -262,7 +254,6 @@ _user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize) } -// _user_find_disk_device partition_id _user_find_disk_device(const char *_filename, size_t *neededSize) { @@ -293,7 +284,6 @@ _user_find_disk_device(const char *_filename, size_t *neededSize) } -// _user_find_partition partition_id _user_find_partition(const char *_filename, size_t *neededSize) { @@ -362,7 +352,6 @@ _user_find_file_disk_device(const char *_filename, size_t *neededSize) } -// _user_get_disk_device_data /*! \brief Writes data describing the disk device identified by ID and all its partitions into the supplied buffer. @@ -454,7 +443,6 @@ _user_get_disk_device_data(partition_id id, bool deviceOnly, } -// _user_register_file_device partition_id _user_register_file_device(const char *_filename) { @@ -475,7 +463,6 @@ _user_register_file_device(const char *_filename) } -// _user_unregister_file_device status_t _user_unregister_file_device(partition_id deviceID, const char *_filename) { @@ -520,7 +507,6 @@ _user_get_file_disk_device_path(partition_id id, char* buffer, } -// _user_get_disk_system_info status_t _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info) { @@ -539,7 +525,6 @@ _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info) } -// _user_get_next_disk_system_info status_t _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info) { @@ -562,7 +547,6 @@ _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info) } -// _user_find_disk_system status_t _user_find_disk_system(const char *_name, user_disk_system_info *_info) { @@ -585,7 +569,6 @@ _user_find_disk_system(const char *_name, user_disk_system_info *_info) } -// _user_defragment_partition status_t _user_defragment_partition(partition_id partitionID, int32* _changeCounter) { @@ -640,7 +623,6 @@ _user_defragment_partition(partition_id partitionID, int32* _changeCounter) } -// _user_repair_partition status_t _user_repair_partition(partition_id partitionID, int32* _changeCounter, bool checkOnly) @@ -696,7 +678,6 @@ _user_repair_partition(partition_id partitionID, int32* _changeCounter, } -// _user_resize_partition status_t _user_resize_partition(partition_id partitionID, int32* _changeCounter, partition_id childID, int32* _childChangeCounter, off_t size, @@ -792,7 +773,6 @@ _user_resize_partition(partition_id partitionID, int32* _changeCounter, } -// _user_move_partition status_t _user_move_partition(partition_id partitionID, int32* changeCounter, partition_id childID, int32* childChangeCounter, off_t newOffset, @@ -834,7 +814,6 @@ return B_BAD_VALUE; } -// _user_set_partition_name status_t _user_set_partition_name(partition_id partitionID, int32* _changeCounter, partition_id childID, int32* _childChangeCounter, const char* _name) @@ -915,7 +894,6 @@ _user_set_partition_name(partition_id partitionID, int32* _changeCounter, } -// _user_set_partition_content_name status_t _user_set_partition_content_name(partition_id partitionID, int32* _changeCounter, const char* _name) @@ -975,7 +953,6 @@ _user_set_partition_content_name(partition_id partitionID, } -// _user_set_partition_type status_t _user_set_partition_type(partition_id partitionID, int32* _changeCounter, partition_id childID, int32* _childChangeCounter, const char* _type) @@ -1056,7 +1033,6 @@ _user_set_partition_type(partition_id partitionID, int32* _changeCounter, } -// _user_set_partition_parameters status_t _user_set_partition_parameters(partition_id partitionID, int32* _changeCounter, partition_id childID, int32* _childChangeCounter, const char* _parameters, @@ -1139,7 +1115,6 @@ _user_set_partition_parameters(partition_id partitionID, int32* _changeCounter, } -// _user_set_partition_content_parameters status_t _user_set_partition_content_parameters(partition_id partitionID, int32* _changeCounter, const char* _parameters, size_t parametersSize) @@ -1201,7 +1176,6 @@ _user_set_partition_content_parameters(partition_id partitionID, } -// _user_initialize_partition status_t _user_initialize_partition(partition_id partitionID, int32* _changeCounter, const char* _diskSystemName, const char* _name, const char* _parameters, @@ -1276,7 +1250,6 @@ _user_initialize_partition(partition_id partitionID, int32* _changeCounter, } -// _user_uninitialize_partition status_t _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter) { @@ -1328,7 +1301,6 @@ _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter) } -// _user_create_child_partition status_t _user_create_child_partition(partition_id partitionID, int32* _changeCounter, off_t offset, off_t size, const char* _type, const char* _name, @@ -1404,7 +1376,6 @@ _user_create_child_partition(partition_id partitionID, int32* _changeCounter, } -// _user_delete_child_partition status_t _user_delete_child_partition(partition_id partitionID, int32* _changeCounter, partition_id childID, int32 childChangeCounter) @@ -1473,3 +1444,20 @@ _user_delete_child_partition(partition_id partitionID, int32* _changeCounter, return B_OK; } + + +status_t +_user_start_watching_disks(uint32 eventMask, port_id port, int32 token) +{ + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + return manager->Notifications().UpdateUserListener(eventMask, port, token); +} + + +status_t +_user_stop_watching_disks(port_id port, int32 token) +{ + KDiskDeviceManager* manager = KDiskDeviceManager::Default(); + return manager->Notifications().RemoveUserListeners(port, token); +} +