55
66#include " disk_monitor.h"
77
8+ #include < DiskDeviceRoster.h>
89#include < NodeMonitor.h>
910
1011#include < sys/poll.h>
1718
1819#include < util/KMessage.h>
1920
21+ #include " disk_device.h"
2022#include " Team.h"
2123#include " KernelDebug.h"
2224
@@ -82,24 +84,56 @@ init_udev()
8284
8385
8486static void
85- send_device_notification (port_id port, uint32 token, uint32 opcode, dev_t newDevice)
87+ send_device_notification (port_id port, uint32 token, uint32 opcode, dev_t device,
88+ dev_t parentDevice = -1 , ino_t parentDirectory = -1 )
8689{
90+ // TODO this code doesn't really understand mount points, we should
91+ // send notifications for volumes that are actually mounted/unmounted.
8792 KMessage message;
88- char buffer[128 ];
93+ char buffer[256 ];
8994 const int32 kPortMessageCode = ' pjpp' ;
9095 message.SetTo (buffer, sizeof (buffer), B_NODE_MONITOR);
9196 message.AddInt32 (" opcode" , opcode);
9297 if (opcode == B_DEVICE_MOUNTED) {
93- message.AddInt32 (" new device" , (int32)newDevice);
98+ message.AddInt32 (" new device" , (int32)device);
99+ if (parentDevice != (dev_t )-1 )
100+ message.AddInt32 (" device" , (int32)parentDevice);
101+ if (parentDirectory != (ino_t )-1 )
102+ message.AddInt64 (" directory" , parentDirectory);
94103 } else {
95- message.AddInt32 (" device" , (int32)newDevice );
104+ message.AddInt32 (" device" , (int32)device );
96105 }
97106 message.SetDeliveryInfo (token, port, -1 , find_thread (NULL ));
98107
99108 write_port (port, kPortMessageCode , message.Buffer (), message.ContentSize ());
100109}
101110
102111
112+ static void
113+ send_disk_device_notification (port_id port, uint32 token, uint32 event,
114+ const char * devNode)
115+ {
116+ partition_id deviceId = -1 ;
117+ if (devNode && devNode[0 ])
118+ deviceId = make_partition_id (devNode);
119+
120+ if (deviceId < 0 )
121+ return ;
122+
123+ KMessage message;
124+ char buffer[256 ];
125+ const int32 kPortMessageCode = ' pjpp' ;
126+
127+ message.SetTo (buffer, sizeof (buffer), B_DEVICE_UPDATE);
128+ message.AddInt32 (" event" , event);
129+ message.AddInt32 (" device_id" , deviceId);
130+ message.AddInt32 (" partition_id" , deviceId);
131+ message.SetDeliveryInfo (token, port, -1 , find_thread (NULL ));
132+
133+ write_port (port, kPortMessageCode , message.Buffer (), message.ContentSize ());
134+ }
135+
136+
103137static uint32
104138udev_action_to_opcode (const char * action)
105139{
@@ -113,6 +147,21 @@ udev_action_to_opcode(const char* action)
113147}
114148
115149
150+ static uint32
151+ udev_action_to_disk_event (const char * action)
152+ {
153+ if (!action)
154+ return 0 ;
155+ if (strcmp (action, " add" ) == 0 )
156+ return B_DEVICE_ADDED;
157+ if (strcmp (action, " remove" ) == 0 )
158+ return B_DEVICE_REMOVED;
159+ if (strcmp (action, " change" ) == 0 )
160+ return B_DEVICE_MEDIA_CHANGED;
161+ return 0 ;
162+ }
163+
164+
116165static void
117166udev_thread_func ()
118167{
@@ -165,10 +214,10 @@ udev_thread_func()
165214 struct udev_device * dev;
166215 while ((dev = udev_monitor_receive_device (udevMonitor)) != nullptr ) {
167216 const char * action = udev_device_get_action (dev);
168- const char * devnode = udev_device_get_devnode (dev);
169- (void )devnode;
217+ const char * devNode = udev_device_get_devnode (dev);
170218
171219 uint32 opcode = udev_action_to_opcode (action);
220+ uint32 diskEvent = udev_action_to_disk_event (action);
172221 if (opcode != 0 ) {
173222 dev_t devnum = udev_device_get_devnum (dev);
174223
@@ -206,12 +255,22 @@ udev_thread_func()
206255 const VolumeWatcherKey& key = p.first ;
207256 uint32 mask = p.second ;
208257 bool send = false ;
209- if (opcode == B_DEVICE_MOUNTED && (mask & WATCH_DISK_ADD))
258+ uint32 eventToSend = 0 ;
259+
260+ if (diskEvent == B_DEVICE_ADDED && (mask & WATCH_DISK_ADD)) {
261+ send = true ;
262+ eventToSend = B_DEVICE_ADDED;
263+ } else if (diskEvent == B_DEVICE_REMOVED && (mask & WATCH_DISK_REMOVE)) {
210264 send = true ;
211- else if (opcode == B_DEVICE_UNMOUNTED && (mask & WATCH_DISK_REMOVE))
265+ eventToSend = B_DEVICE_REMOVED;
266+ } else if (diskEvent == B_DEVICE_MEDIA_CHANGED && (mask & WATCH_DISK_ADD)) {
212267 send = true ;
213- if (send) {
214- send_device_notification (key.port , key.token , opcode, devnum);
268+ eventToSend = B_DEVICE_MEDIA_CHANGED;
269+ }
270+
271+ if (send && eventToSend != 0 ) {
272+ send_disk_device_notification (key.port , key.token ,
273+ eventToSend, devNode);
215274 }
216275 }
217276 }
@@ -231,38 +290,39 @@ udev_thread_func()
231290static void
232291start_thread ()
233292{
234- bool start = false ;
235293 {
236294 std::lock_guard<std::mutex> guard (gWatchLock );
237- if (! gWatchThreadRunning &&
238- (! gMountWatchers . empty () || ! gVolumeWatchers . empty () || ! gDiskWatchers . empty ())) {
239- gWatchThreadRunning = true ;
295+ if (gWatchThreadRunning )
296+ return ;
297+ if (! gMountWatchers . empty () || ! gVolumeWatchers . empty () || ! gDiskWatchers . empty ()) {
240298 gWatcherExitRequested = false ;
241- start = true ;
299+ gWatchThread = std::thread (udev_thread_func);
300+ gWatchThreadRunning = true ;
242301 }
243302 }
244- if (start)
245- gWatchThread = std::thread (udev_thread_func);
246303}
247304
305+
248306static void
249307stop_thread ()
250308{
251- bool stop = false ;
309+ std::thread threadToJoin ;
252310 {
253311 std::lock_guard<std::mutex> guard (gWatchLock );
254- if (gWatchThreadRunning &&
255- gMountWatchers .empty () && gVolumeWatchers .empty () && gDiskWatchers .empty ()) {
256- stop = true ;
312+ if (!gWatchThreadRunning )
313+ return ;
314+
315+ if (gMountWatchers .empty () && gVolumeWatchers .empty () && gDiskWatchers .empty ()) {
316+ gWatcherExitRequested = true ;
317+ if (gWatchThread .joinable ())
318+ threadToJoin = std::move (gWatchThread );
319+
320+ gWatchThreadRunning = false ;
257321 }
258322 }
259- if (stop) {
260- gWatcherExitRequested = true ;
261- if (gWatchThread .joinable ())
262- gWatchThread .join ();
263323
264- gWatchThreadRunning = false ;
265- }
324+ if (threadToJoin. joinable ())
325+ threadToJoin. join ();
266326}
267327
268328
@@ -271,10 +331,11 @@ start_mount_watching(port_id port, uint32 token)
271331{
272332 printf (" start mount_watching\n " );
273333
274- std::lock_guard<std::mutex> guard (gWatchLock );
275-
276- VolumeWatcherKey key = { port, token };
277- gMountWatchers [key] = 1 ;
334+ {
335+ std::lock_guard<std::mutex> guard (gWatchLock );
336+ VolumeWatcherKey key = { port, token };
337+ gMountWatchers [key] = 1 ;
338+ }
278339
279340 start_thread ();
280341 return B_OK;
@@ -302,8 +363,11 @@ start_volume_watching(dev_t device, port_id port, uint32 token)
302363{
303364 std::lock_guard<std::mutex> guard (gWatchLock );
304365
305- VolumeWatcher watcher = { port, token, device };
306- gVolumeWatchers .push_back (watcher);
366+ {
367+ std::lock_guard<std::mutex> guard (gWatchLock );
368+ VolumeWatcher watcher = { port, token, device };
369+ gVolumeWatchers .push_back (watcher);
370+ }
307371
308372 start_thread ();
309373 return B_OK;
@@ -369,15 +433,13 @@ extern "C" {
369433status_t
370434_kern_start_watching_volume (dev_t device, uint32 flags, port_id port, uint32 token)
371435{
372- std::lock_guard<std::mutex> guard (gWatchLock );
373436 return start_volume_watching (device, port, token);
374437}
375438
376439
377440status_t
378441_kern_stop_watching_volume (dev_t device, port_id port, uint32 token)
379442{
380- std::lock_guard<std::mutex> guard (gWatchLock );
381443 return stop_volume_watching (device, port, token);
382444}
383445
0 commit comments